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 = "";
}
}