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 ItemsForQuota v1.3.3
ItemsForQuota.dll
Decompiled 2 years agousing 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.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace ItemsForQuota; [BepInPlugin("Jeremy.ItemsForQuota", "ItemsForQuota", "1.3.0.3")] public class ItemsForQuotaBase : BaseUnityPlugin { public const string pluginGuid = "Jeremy.ItemsForQuota"; public const string pluginName = "ItemsForQuota"; public const string pluginVersion = "1.3.0.3"; 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 = ""; } }