Decompiled source of ItemsForQuota v1.3.2

ItemsForQuota.dll

Decompiled 6 months 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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LC_API.ServerAPI;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ItemsForQuota")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ItemsForQuota")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ce5cc13d-3777-4a20-816b-34fbe81ba556")]
[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 ItemsForQuota;

[BepInPlugin("Jeremy.ItemsForQuota", "ItemsForQuota", "1.3.0.2")]
public class ItemsForQuotaBase : BaseUnityPlugin
{
	public const string pluginGuid = "Jeremy.ItemsForQuota";

	public const string pluginName = "ItemsForQuota";

	public const string pluginVersion = "1.3.0.2";

	private readonly Harmony harmony = new Harmony("Jeremy.ItemsForQuota");

	public static ItemsForQuotaBase Instance;

	internal ManualLogSource mls;

	public static ConfigEntry<bool> HUD;

	public static ConfigEntry<float> AdjustScreenPositionXaxis;

	public static ConfigEntry<float> AdjustScreenPositionYaxis;

	public static ConfigEntry<string> HUDTextColor;

	public static ConfigEntry<string> HUDLineColor;

	public static ConfigEntry<float> displayTime;

	public static ConfigEntry<bool> ChangeNodeNames;

	public static ConfigEntry<string> NodeNames;

	public static ConfigEntry<int> QuotaOffset;

	public static ConfigEntry<int> NodeColor;

	public static ConfigEntry<string> BlacklistedItems;

	public void Awake()
	{
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
		}
		mls = Logger.CreateLogSource("Jeremy.ItemsForQuota");
		mls.LogInfo((object)"ItemsForQuota has awaken");
		LoadConfig();
		harmony.PatchAll(typeof(ItemsForQuotaBase));
		harmony.PatchAll(typeof(PlayerControllerPatch));
	}

	private void LoadConfig()
	{
		HUD = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "HUD", true, "You can decide if the sum is shown on the HUD.");
		AdjustScreenPositionXaxis = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "AdjustScreenPositionXaxis", 0f, "You will add or take away from its original position. This is irrelevant when HUD option is \"false\"");
		AdjustScreenPositionYaxis = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "AdjustScreenPositionYaxis", 0f, "You will add or take away from its original position. This is irrelevant when HUD option is \"false\"");
		HUDTextColor = ((BaseUnityPlugin)this).Config.Bind<string>("HUD", "HUDTextColor", "#00B37F", "Hexadecimal color code for the HUD text. This is irrelevant when HUD option is \"false\"");
		HUDLineColor = ((BaseUnityPlugin)this).Config.Bind<string>("HUD", "HUDLineColor", "#00B37F", "Hexadecimal color code for the HUD line. This is irrelevant when HUD option is \"false\"");
		displayTime = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "DisplayTime", 5f, "You will decide How long the HUD is visible in seconds. This is irrelevant when HUD option is \"false\"");
		ChangeNodeNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Scannodes", "ChangeNodeNames", true, "You can decide if the Names of the Items to be sold should be changed.");
		NodeNames = ((BaseUnityPlugin)this).Config.Bind<string>("Scannodes", "NodeNames", "SELL ME!", "You can decide what the Names of the Items to be sold should be changed to. This is irrelevant when ChangeNodeNames option is \"false\"");
		NodeColor = ((BaseUnityPlugin)this).Config.Bind<int>("Scannodes", "NodeColor", 1, "You will change the Scan Color of the Items to be sold (0 -> Blue; 1 -> Red; 2 -> Green).");
		QuotaOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Quota", "QuotaOffset", 0, "You will add or take away from the Target-Value(Rest of needed to meet Quota) the mod Calculates for.");
		BlacklistedItems = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BlacklistedItems", "ClipboardManual,StickyNoteItem,Key(Clone)", "Comma-separated list of item names that should be ignored by the mod.");
	}
}
[HarmonyPatch]
internal class PlayerControllerPatch : BaseUnityPlugin
{
	internal static bool CombinationFound = false;

	internal static bool SpecialCondition = false;

	internal static int sum = 0;

	internal static List<GrabbableObject> list = new List<GrabbableObject>();

	internal static List<GrabbableObject> closestGrabbableObjects = new List<GrabbableObject>();

	internal static List<GrabbableObject> previousObjects = new List<GrabbableObject>();

	internal static List<GrabbableObject> originalObjects = new List<GrabbableObject>();

	internal static Dictionary<ScanNodeProperties, string> originalHeaderTexts = new Dictionary<ScanNodeProperties, string>();

	internal static List<GrabbableObject> notMarkedObjects = new List<GrabbableObject>();

	internal static ManualLogSource mls = ItemsForQuotaBase.Instance.mls;

	private static GameObject sumDisplayObject;

	private static TextMeshProUGUI sumDisplayText;

	private static Image sumDisplayLine;

	private static readonly float displayTimeSet = ItemsForQuotaBase.displayTime.Value;

	private static float displayTime = displayTimeSet;

	private static bool isSumDisplayInitialized = false;

	private static Vector3 newTextTransform;

	private static string syncvar = "";

	private static bool isSubscribed = false;

	private static void InitializeSumDisplay()
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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)
		//IL_00a7: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter");
		if (!Object.op_Implicit((Object)(object)val))
		{
			mls.LogError((object)"Failed to find ValueCounter object to copy!");
		}
		sumDisplayObject = Object.Instantiate<GameObject>(val.gameObject, val.transform.parent, false);
		sumDisplayObject.transform.Translate(0f, 1f, 0f);
		Vector3 localPosition = sumDisplayObject.transform.localPosition;
		sumDisplayObject.transform.localPosition = new Vector3(localPosition.x + 62f + ItemsForQuotaBase.AdjustScreenPositionXaxis.Value, -66.8f + ItemsForQuotaBase.AdjustScreenPositionYaxis.Value, localPosition.z);
		sumDisplayText = sumDisplayObject.GetComponentInChildren<TextMeshProUGUI>();
		sumDisplayLine = sumDisplayObject.GetComponentInChildren<Image>();
		if (!isSumDisplayInitialized)
		{
			Vector3 localPosition2 = ((TMP_Text)sumDisplayText).transform.localPosition;
			newTextTransform = new Vector3(localPosition2.x - 8f, localPosition2.y, localPosition2.z);
			isSumDisplayInitialized = true;
		}
	}

	private static void UpdateSumDisplay(int sum, int quota)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		if (ItemsForQuotaBase.HUD.Value)
		{
			if (!Object.op_Implicit((Object)(object)sumDisplayObject))
			{
				InitializeSumDisplay();
			}
			((TMP_Text)sumDisplayText).transform.localPosition = newTextTransform;
			((TMP_Text)sumDisplayText).text = $"SUM: ${sum:F0}/${quota:F0}";
			((Graphic)sumDisplayText).color = ParseColor(ItemsForQuotaBase.HUDTextColor.Value);
			((Graphic)sumDisplayLine).color = ParseColor(ItemsForQuotaBase.HUDLineColor.Value);
			displayTime = displayTimeSet;
			if (!sumDisplayObject.activeSelf)
			{
				((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(SumCoroutine());
			}
		}
	}

	private static IEnumerator SumCoroutine()
	{
		sumDisplayObject.SetActive(true);
		while (displayTime > 0f)
		{
			float displayTimeLeft = displayTime;
			displayTime = 0f;
			yield return (object)new WaitForSeconds(displayTimeLeft);
		}
		sumDisplayObject.SetActive(false);
		isSumDisplayInitialized = false;
	}

	private static Color ParseColor(string hexColor)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		Color result = default(Color);
		ColorUtility.TryParseHtmlString(hexColor, ref result);
		return result;
	}

	public static float Abs(float number)
	{
		if (number < 0f)
		{
			return number * -1f;
		}
		return number;
	}

	private static List<(string, int)> SortItems(List<(string, int)> items)
	{
		items.Sort(delegate((string, int) item1, (string, int) item2)
		{
			int num = item1.Item1.CompareTo(item2.Item1);
			return (num != 0) ? num : item1.Item2.CompareTo(item2.Item2);
		});
		return items;
	}

	private static List<(int id, string name, int value)> SortItems(List<(int id, string name, int value)> items)
	{
		return (from item in items
			orderby item.name, item.value
			select item).ToList();
	}

	private static List<GrabbableObject> FilterGrabbableObjects()
	{
		HashSet<string> blacklistedItems = new HashSet<string>(ItemsForQuotaBase.BlacklistedItems.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
		return (from obj in GameObject.Find("/Environment/HangarShip").GetComponentsInChildren<GrabbableObject>()
			where !blacklistedItems.Contains(((Object)obj).name) && obj.scrapValue != 0
			select obj).ToList();
	}

	private static (List<(string, int)>, int) ProcessGrabbableItems(List<GrabbableObject> list)
	{
		List<(string, int)> list2 = new List<(string, int)>();
		int num = 0;
		foreach (GrabbableObject item in list)
		{
			if (item.scrapValue != 0)
			{
				list2.Add((((Object)item).name, item.scrapValue));
				num += item.scrapValue;
			}
		}
		return (list2, num);
	}

	private static List<int> FindClosestItemsWithIncrement(List<(int id, string name, int value)> grabbableObjectTuples, int targetValue, int maxTries = 100)
	{
		List<(int, string, int)> source = SortItems(grabbableObjectTuples);
		HashSet<int> selectedIds = new HashSet<int>();
		for (int i = 0; i < maxTries; i++)
		{
			List<(int, string, int)> list = source.Where<(int, string, int)>(((int id, string name, int value) item) => !selectedIds.Contains(item.id)).ToList();
			List<(string, int)> list2 = list.Select<(int, string, int), (string, int)>(((int id, string name, int value) item) => (item.name, item.value)).ToList();
			List<(int, string, int)> list3 = FindClosestItems(list, targetValue + i);
			if (list3 == null)
			{
				continue;
			}
			foreach (var closestItem in list3)
			{
				(int, string, int) tuple = list.FirstOrDefault<(int, string, int)>(((int id, string name, int value) item) => item.name == closestItem.Item2 && item.value == closestItem.Item3 && item.id == closestItem.Item1);
				selectedIds.Add(tuple.Item1);
			}
			if (selectedIds.Count > 0)
			{
				return selectedIds.ToList();
			}
		}
		return null;
	}

	private static List<(int id, string name, int value)> FindClosestItems(List<(int id, string name, int value)> items, int targetValue)
	{
		Dictionary<int, List<(int, string, int)>> dictionary = new Dictionary<int, List<(int, string, int)>> { 
		{
			0,
			new List<(int, string, int)>()
		} };
		foreach (var item in items)
		{
			foreach (KeyValuePair<int, List<(int, string, int)>> item2 in dictionary.ToList())
			{
				int key = item2.Key;
				List<(int, string, int)> value = item2.Value;
				int num = key + item.value;
				if (num <= targetValue)
				{
					List<(int, string, int)> value2 = new List<(int, string, int)>(value) { item };
					if (!dictionary.ContainsKey(num))
					{
						dictionary[num] = value2;
					}
				}
			}
		}
		IEnumerable<int> source = dictionary.Keys.Where((int s) => s >= targetValue);
		if (!source.Any())
		{
			return null;
		}
		int key2 = source.Min();
		return dictionary[key2];
	}

	private static (List<GrabbableObject>, int) CalculateClosestItemsAndSum(List<GrabbableObject> list, List<(string, int)> itemsToWrite, int targetValue)
	{
		List<(int, string, int)> grabbableObjectTuples = list.Select((GrabbableObject obj) => (((Object)obj).GetInstanceID(), ((Object)obj).name, obj.scrapValue)).ToList();
		List<int> list2 = FindClosestItemsWithIncrement(grabbableObjectTuples, targetValue);
		List<GrabbableObject> list3 = new List<GrabbableObject>();
		int num = 0;
		foreach (int id in list2)
		{
			GrabbableObject val = list.Find((GrabbableObject obj) => ((Object)obj).GetInstanceID() == id);
			if ((Object)(object)val != (Object)null)
			{
				list3.Add(val);
				num += val.scrapValue;
			}
		}
		return (list3, num);
	}

	private static void UpdateHUDWithClosestItems(List<GrabbableObject> closestGrabbableObjects)
	{
		HUDManager instance = HUDManager.Instance;
		if ((Object)(object)instance != (Object)null)
		{
			List<ScanNodeProperties> list = new List<ScanNodeProperties>();
			foreach (GrabbableObject closestGrabbableObject in closestGrabbableObjects)
			{
				list.Add(((Component)closestGrabbableObject).GetComponentInChildren<ScanNodeProperties>());
			}
			if (list != null)
			{
				foreach (ScanNodeProperties item in list)
				{
					if (!originalHeaderTexts.ContainsKey(item))
					{
						originalHeaderTexts[item] = item.headerText;
					}
					foreach (GrabbableObject closestGrabbableObject2 in closestGrabbableObjects)
					{
						GrabbableObject componentInParent = ((Component)item).GetComponentInParent<GrabbableObject>();
						if ((Object)(object)closestGrabbableObject2 == (Object)(object)componentInParent)
						{
							if (ItemsForQuotaBase.NodeColor.Value >= 0 && ItemsForQuotaBase.NodeColor.Value <= 2)
							{
								item.nodeType = ItemsForQuotaBase.NodeColor.Value;
							}
							item.minRange = 0;
							item.maxRange = 50;
							item.requiresLineOfSight = false;
							if (ItemsForQuotaBase.ChangeNodeNames.Value)
							{
								item.headerText = ItemsForQuotaBase.NodeNames.Value;
							}
						}
					}
				}
			}
		}
		previousObjects = PlayerControllerPatch.list;
		CombinationFound = true;
	}

	private static void ResetHeaderTexts()
	{
		foreach (ScanNodeProperties key in originalHeaderTexts.Keys)
		{
			if ((Object)(object)key != (Object)null)
			{
				key.headerText = originalHeaderTexts[key];
				key.nodeType = 2;
				key.maxRange = 7;
				key.requiresLineOfSight = true;
			}
		}
		originalHeaderTexts.Clear();
	}

	private static void CheckAndResetPreviousObjects(List<GrabbableObject> list)
	{
		if (previousObjects.Count != list.Count && CombinationFound)
		{
			ResetHeaderTexts();
			CombinationFound = false;
		}
	}

	public static List<GrabbableObject> ConvertStringToGrabbableObjects(string syncvar)
	{
		List<GrabbableObject> list = new List<GrabbableObject>();
		string[] array = syncvar.Split(new char[1] { ',' });
		string[] array2 = array;
		foreach (string text in array2)
		{
			if (string.IsNullOrEmpty(text) || !ulong.TryParse(text, out var result))
			{
				continue;
			}
			NetworkObject val = NetworkManager.Singleton.SpawnManager.SpawnedObjects[result];
			if ((Object)(object)val != (Object)null)
			{
				GrabbableObject component = ((Component)val).GetComponent<GrabbableObject>();
				if ((Object)(object)component != (Object)null)
				{
					list.Add(component);
				}
			}
		}
		return list;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
	private static void Main()
	{
		if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost || ((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer)
		{
			list = FilterGrabbableObjects();
			(List<(string, int)>, int) tuple = ProcessGrabbableItems(list);
			List<(string, int)> item = tuple.Item1;
			int item2 = tuple.Item2;
			int num = TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled + ItemsForQuotaBase.QuotaOffset.Value;
			if (GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom || SpecialCondition)
			{
				if (item2 < num || num <= 0)
				{
					return;
				}
				mls.LogInfo((object)"--------------------------------------------------------------");
				mls.LogInfo((object)("Value needed: " + num));
				CheckAndResetPreviousObjects(list);
				if (!CombinationFound)
				{
					syncvar = "";
					(closestGrabbableObjects, sum) = CalculateClosestItemsAndSum(list, SortItems(item), num);
					foreach (GrabbableObject closestGrabbableObject in closestGrabbableObjects)
					{
						syncvar = syncvar + ((Component)closestGrabbableObject).GetComponent<NetworkObject>().NetworkObjectId + ",";
					}
					UpdateHUDWithClosestItems(closestGrabbableObjects);
				}
				if (!SpecialCondition)
				{
					UpdateSumDisplay(sum, num);
				}
				Networking.Broadcast(syncvar, "HostToClientBroad123");
				mls.LogInfo((object)("Sum: " + sum));
				mls.LogInfo((object)"--------------------------------------------------------------");
			}
			else
			{
				CheckAndResetPreviousObjects(list);
			}
		}
		else if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsClient && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer)
		{
			Networking.Broadcast("Need List", "ClientToHostBroad123");
		}
	}

	private static int GetSumFromList(List<GrabbableObject> sumList)
	{
		int num = 0;
		foreach (GrabbableObject sum in sumList)
		{
			num += sum.scrapValue;
		}
		return num;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(HUDManager), "Update")]
	private static void UpdateItemcount()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		if (list == null || !((Object)GameNetworkManager.Instance.localPlayerController != (Object)null))
		{
			return;
		}
		if (!isSubscribed && ((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsClient && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer)
		{
			Networking.GetString = (Action<string, string>)Delegate.Combine(Networking.GetString, (Action<string, string>)delegate(string receivedString, string signature)
			{
				if (signature == "HostToClientBroad123")
				{
					closestGrabbableObjects = ConvertStringToGrabbableObjects(receivedString);
					ResetHeaderTexts();
					UpdateHUDWithClosestItems(closestGrabbableObjects);
					int quota = TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled + ItemsForQuotaBase.QuotaOffset.Value;
					if (GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom)
					{
						UpdateSumDisplay(GetSumFromList(closestGrabbableObjects), quota);
					}
				}
			});
			isSubscribed = true;
		}
		if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost || ((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer)
		{
			list = FilterGrabbableObjects();
			if (previousObjects.Count != list.Count)
			{
				SpecialCondition = true;
				Main();
				SpecialCondition = false;
			}
		}
		if (isSubscribed || (!((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer))
		{
			return;
		}
		Networking.GetString = (Action<string, string>)Delegate.Combine(Networking.GetString, (Action<string, string>)delegate(string receivedString, string signature)
		{
			if (signature == "ClientToHostBroad123")
			{
				SpecialCondition = true;
				Main();
				SpecialCondition = false;
			}
		});
		isSubscribed = true;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(StartOfRound), "Awake")]
	private static void RoundStartReset()
	{
		CombinationFound = false;
		SpecialCondition = false;
		sum = 0;
		list = new List<GrabbableObject>();
		closestGrabbableObjects = new List<GrabbableObject>();
		previousObjects = new List<GrabbableObject>();
		originalObjects = new List<GrabbableObject>();
		originalHeaderTexts = new Dictionary<ScanNodeProperties, string>();
		notMarkedObjects = new List<GrabbableObject>();
		isSumDisplayInitialized = false;
		syncvar = "";
	}
}