Decompiled source of ShipLoot v1.2.1

plugins/ShipLoot/ShipLoot.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShipLoot
{
	[BepInPlugin("com.github.tinyhoot.ShipLoot", "ShipLoot", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class ShipLoot : BaseUnityPlugin
	{
		public const string GUID = "com.github.tinyhoot.ShipLoot";

		public const string NAME = "ShipLoot";

		public const string VERSION = "1.2.1";

		internal static ShipLootConfig PluginConfig;

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig = new ShipLootConfig(((BaseUnityPlugin)this).Config);
			PluginConfig.RegisterOptions();
			new Harmony("com.github.tinyhoot.ShipLoot").PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)"ShipLoot 1.2.1 loaded.");
		}

		private void Start()
		{
			SetLobbyCompatibility();
		}

		private void SetLobbyCompatibility()
		{
			if (!Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method("LobbyCompatibility.Features.PluginHelper:RegisterPlugin", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log.LogWarning((object)"Found LobbyCompatibility mod but failed to find plugin register API method!");
				return;
			}
			Log.LogDebug((object)"Registering compatibility with LobbyCompatibility.");
			try
			{
				methodInfo.Invoke(null, new object[4]
				{
					"com.github.tinyhoot.ShipLoot",
					new Version("1.2.1"),
					0,
					0
				});
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to register plugin compatibility with LobbyCompatibility.\n{arg}");
				return;
			}
			Log.LogDebug((object)"Successfully registered with LobbyCompatibility.");
		}
	}
	internal class ShipLootConfig
	{
		private readonly ConfigFile _configFile;

		public ConfigEntry<float> DisplayTime;

		public ConfigEntry<float> VerticalOffset;

		public ShipLootConfig(ConfigFile configFile)
		{
			_configFile = configFile;
		}

		public void RegisterOptions()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			DisplayTime = _configFile.Bind<float>("General", "DisplayTime", 5f, new ConfigDescription("How long to display the total scrap value for, counted in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			VerticalOffset = _configFile.Bind<float>("General", "VerticalOffset", 50f, new ConfigDescription("How far below the game's own scan total to place the ship total, in UI units. Negative values move it above instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-500f, 500f), Array.Empty<object>()));
		}
	}
}
namespace ShipLoot.Patches
{
	[HarmonyPatch]
	internal class HudManagerPatcher
	{
		private const float RefreshInterval = 0.2f;

		private static GameObject _totalCounter;

		private static TextMeshProUGUI _valueText;

		private static TextMeshProUGUI _labelText;

		private static float _displayTimeLeft;

		private static bool _diagnosticsLogged;

		private static float _lastLoggedTotal = float.NaN;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
		private static void OnScan(HUDManager __instance, CallbackContext context)
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null || !((CallbackContext)(ref context)).performed || !__instance.CanPlayerScan() || __instance.playerPingingScan > -1f || (Object)(object)StartOfRound.Instance == (Object)null || (!StartOfRound.Instance.inShipPhase && !GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)_totalCounter))
			{
				BuildCounter(__instance);
			}
			if (Object.op_Implicit((Object)(object)_totalCounter) && Object.op_Implicit((Object)(object)_valueText))
			{
				UpdateDisplayedTotal();
				_displayTimeLeft = ShipLoot.PluginConfig.DisplayTime.Value;
				if (!_totalCounter.activeSelf)
				{
					((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(ShipLootCoroutine());
				}
			}
		}

		private static void ApplyShownState()
		{
			Transform[] componentsInChildren = _totalCounter.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(true);
			}
			CanvasGroup[] componentsInChildren2 = _totalCounter.GetComponentsInChildren<CanvasGroup>(true);
			foreach (CanvasGroup obj in componentsInChildren2)
			{
				obj.alpha = 1f;
				obj.interactable = false;
				obj.blocksRaycasts = false;
			}
			Graphic[] componentsInChildren3 = _totalCounter.GetComponentsInChildren<Graphic>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = true;
			}
		}

		private static IEnumerator ShipLootCoroutine()
		{
			_totalCounter.SetActive(true);
			ApplyShownState();
			if (!_diagnosticsLogged)
			{
				_diagnosticsLogged = true;
				yield return (object)new WaitForEndOfFrame();
				LogLayoutDiagnostics();
			}
			float refreshTimer = 0.2f;
			while (_displayTimeLeft > 0f)
			{
				_displayTimeLeft -= Time.deltaTime;
				refreshTimer -= Time.deltaTime;
				if (refreshTimer <= 0f)
				{
					refreshTimer = 0.2f;
					UpdateDisplayedTotal();
				}
				yield return null;
			}
			_totalCounter.SetActive(false);
		}

		private static void UpdateDisplayedTotal()
		{
			if (Object.op_Implicit((Object)(object)_valueText))
			{
				((TMP_Text)_valueText).text = $"${CalculateLootValue():F0}";
				if (Object.op_Implicit((Object)(object)_labelText))
				{
					((TMP_Text)_labelText).text = "SHIP:";
				}
			}
		}

		private static bool CountsAsScrap(GrabbableObject obj)
		{
			if ((Object)(object)obj.itemProperties != (Object)null && obj.itemProperties.isScrap && !obj.deactivated && !obj.itemUsedUp)
			{
				return !(obj is RagdollGrabbableObject);
			}
			return false;
		}

		private static float CalculateLootValue()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Collider val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.shipInnerRoomBounds : null);
			List<GrabbableObject> list;
			string arg;
			if ((Object)(object)val != (Object)null)
			{
				Bounds bounds = val.bounds;
				list = (from obj in Object.FindObjectsOfType<GrabbableObject>()
					where ((Bounds)(ref bounds)).Contains(((Component)obj).transform.position)
					select obj).ToList();
				arg = "ship bounds";
			}
			else
			{
				GameObject val2 = FindShip();
				if (!Object.op_Implicit((Object)(object)val2))
				{
					ShipLoot.Log.LogError((object)"Failed to find the ship, cannot total up its scrap.");
					return 0f;
				}
				list = val2.GetComponentsInChildren<GrabbableObject>().ToList();
				arg = "ship hierarchy (fallback)";
			}
			List<GrabbableObject> list2 = list.Where(CountsAsScrap).ToList();
			float num = list2.Sum((GrabbableObject scrap) => scrap.scrapValue);
			if (!num.Equals(_lastLoggedTotal))
			{
				_lastLoggedTotal = num;
				ShipLoot.Log.LogDebug((object)($"Ship scrap total is now ${num:F0}, found via {arg}. " + $"{list.Count} grabbable object(s) in the ship, {list2.Count} counted."));
				CollectionExtensions.Do<GrabbableObject>((IEnumerable<GrabbableObject>)list2, (Action<GrabbableObject>)delegate(GrabbableObject scrap)
				{
					ShipLoot.Log.LogDebug((object)$"  counted: {((Object)scrap).name} - ${scrap.scrapValue}");
				});
				foreach (GrabbableObject item in list.Except(list2))
				{
					string arg2 = (((Object)(object)item.itemProperties == (Object)null) ? "no item properties" : ((item is RagdollGrabbableObject) ? "is a body" : (item.deactivated ? "deactivated" : (item.itemUsedUp ? "used up" : "not marked as scrap"))));
					ShipLoot.Log.LogDebug((object)$"  skipped: {((Object)item).name} - ${item.scrapValue} ({arg2})");
				}
			}
			return num;
		}

		private static GameObject FindShip()
		{
			Transform val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.elevatorTransform : null);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			return GameObject.Find("/Environment/HangarShip");
		}

		private static void BuildCounter(HUDManager hudManager)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindScanContainer(hudManager);
			if ((Object)(object)val == (Object)null)
			{
				ShipLoot.Log.LogError((object)"Failed to find the scan info container to copy!");
				return;
			}
			string text = (((Object)(object)hudManager.totalValueText != (Object)null) ? GetRelativePath(val, ((TMP_Text)hudManager.totalValueText).transform) : null);
			_totalCounter = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent, false);
			((Object)_totalCounter).name = "ShipLootCounter";
			Animator component = _totalCounter.GetComponent<Animator>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			ApplyShownState();
			Transform transform = _totalCounter.transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (val2 != null)
			{
				RectTransform val3 = (RectTransform)(object)((val is RectTransform) ? val : null);
				if (val3 != null)
				{
					val2.anchoredPosition = val3.anchoredPosition + new Vector2(0f, 0f - ShipLoot.PluginConfig.VerticalOffset.Value);
				}
			}
			_valueText = null;
			if (!string.IsNullOrEmpty(text))
			{
				Transform val4 = _totalCounter.transform.Find(text);
				if ((Object)(object)val4 != (Object)null)
				{
					_valueText = ((Component)val4).GetComponent<TextMeshProUGUI>();
				}
			}
			TextMeshProUGUI[] componentsInChildren = _totalCounter.GetComponentsInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)_valueText == (Object)null)
			{
				_valueText = componentsInChildren.FirstOrDefault();
			}
			_labelText = ((IEnumerable<TextMeshProUGUI>)componentsInChildren).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI val5) => (Object)(object)val5 != (Object)(object)_valueText));
			if ((Object)(object)_valueText == (Object)null)
			{
				ShipLoot.Log.LogError((object)"Failed to find a text component on the copied scan info container!");
			}
			_totalCounter.SetActive(false);
		}

		private static Transform FindScanContainer(HUDManager hudManager)
		{
			if ((Object)(object)hudManager == (Object)null)
			{
				return null;
			}
			if ((Object)(object)hudManager.scanInfoAnimator != (Object)null)
			{
				return ((Component)hudManager.scanInfoAnimator).transform;
			}
			if ((Object)(object)hudManager.totalValueText == (Object)null)
			{
				return null;
			}
			Transform val = ((TMP_Text)hudManager.totalValueText).transform;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)((Component)val).GetComponent<Animator>() != (Object)null)
				{
					return val;
				}
				val = val.parent;
			}
			return ((TMP_Text)hudManager.totalValueText).transform.parent;
		}

		private static string GetRelativePath(Transform root, Transform target)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)target == (Object)null)
			{
				return null;
			}
			string text = null;
			Transform val = target;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				text = ((text == null) ? ((Object)val).name : (((Object)val).name + "/" + text));
				val = val.parent;
			}
			return text;
		}

		private static string GetPath(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "<null>";
			}
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return "/" + text;
		}

		private static void LogLayoutDiagnostics()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource log = ShipLoot.Log;
			if (!Object.op_Implicit((Object)(object)_totalCounter))
			{
				log.LogDebug((object)"ShipLoot counter is gone before it could be measured.");
				return;
			}
			log.LogDebug((object)"===== ShipLoot layout diagnostics =====");
			log.LogDebug((object)$"screen        : {Screen.width}x{Screen.height}");
			log.LogDebug((object)("counter path  : " + GetPath(_totalCounter.transform)));
			log.LogDebug((object)$"counter active: self={_totalCounter.activeSelf} inHierarchy={_totalCounter.activeInHierarchy}");
			Transform transform = _totalCounter.transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (val != null)
			{
				log.LogDebug((object)$"counter rect  : anchoredPos={val.anchoredPosition} sizeDelta={val.sizeDelta} lossyScale={((Transform)val).lossyScale}");
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val.GetWorldCorners(array);
				log.LogDebug((object)$"counter corner: bottomLeft={array[0]} topRight={array[2]}");
			}
			Transform val2 = _totalCounter.transform;
			while ((Object)(object)val2 != (Object)null)
			{
				CanvasGroup component = ((Component)val2).GetComponent<CanvasGroup>();
				Canvas component2 = ((Component)val2).GetComponent<Canvas>();
				if (!((Object)(object)component == (Object)null) || !((Object)(object)component2 == (Object)null) || !((Object)(object)val2 != (Object)(object)_totalCounter.transform))
				{
					log.LogDebug((object)($"  chain '{((Object)val2).name}': activeSelf={((Component)val2).gameObject.activeSelf}" + (((Object)(object)component != (Object)null) ? $" alpha={component.alpha}" : "") + (((Object)(object)component2 != (Object)null) ? $" canvasEnabled={((Behaviour)component2).enabled}" : "")));
				}
				val2 = val2.parent;
			}
			if (Object.op_Implicit((Object)(object)_valueText))
			{
				log.LogDebug((object)("value text    : " + GetPath(((TMP_Text)_valueText).transform) + " '" + ((TMP_Text)_valueText).text + "' " + $"enabled={((Behaviour)_valueText).enabled} activeInHierarchy={((Component)_valueText).gameObject.activeInHierarchy} " + $"color={((Graphic)_valueText).color}"));
			}
			if (Object.op_Implicit((Object)(object)_labelText))
			{
				log.LogDebug((object)("label text    : " + GetPath(((TMP_Text)_labelText).transform) + " '" + ((TMP_Text)_labelText).text + "' " + $"enabled={((Behaviour)_labelText).enabled} activeInHierarchy={((Component)_labelText).gameObject.activeInHierarchy}"));
			}
			log.LogDebug((object)"===== end diagnostics =====");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}