Decompiled source of ProfitPercent v1.2.1

ProfitPercent.dll

Decompiled 2 months ago
using System;
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 HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ProfitPercent")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProfitPercent")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1aa9f185-5e80-46e0-935b-a30791a11860")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ProfitPercent;

[BepInPlugin("pr0skynesis.profitpercent", "Profit Percent", "1.2.1")]
public class ProfitPercentMain : BaseUnityPlugin
{
	public const string pluginGuid = "pr0skynesis.profitpercent";

	public const string pluginName = "Profit Percent";

	public const string pluginVersion = "1.2.1";

	public static ConfigEntry<bool> coloredTextConfig;

	public static ConfigEntry<int> greenThresholdConfig;

	public static ConfigEntry<int> blueThresholdConfig;

	public static ConfigEntry<bool> showBestDealsConfig;

	public static ConfigEntry<bool> autoReceiptConfig;

	public void Awake()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		Harmony val = new Harmony("pr0skynesis.profitpercent");
		MethodInfo methodInfo = AccessTools.Method(typeof(EconomyUI), "Awake", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(ProfitPercentPatches), "AwakePatch", (Type[])null, (Type[])null);
		val.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		MethodInfo methodInfo3 = AccessTools.Method(typeof(EconomyUI), "ShowGoodPage", (Type[])null, (Type[])null);
		MethodInfo methodInfo4 = AccessTools.Method(typeof(ProfitPercentPatches), "MainPatch", (Type[])null, (Type[])null);
		val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		MethodInfo methodInfo5 = AccessTools.Method(typeof(EconomyUIButton), "OnActivate", (Type[])null, (Type[])null);
		MethodInfo methodInfo6 = AccessTools.Method(typeof(ProfitPercentPatches), "ButtonPatch", (Type[])null, (Type[])null);
		val.Patch((MethodBase)methodInfo5, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		coloredTextConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("A) Colored text", "coloredText", true, "Enables the coloring of the profit in red (loss), green (profit), yellow (neither) and blue (high profit)");
		greenThresholdConfig = ((BaseUnityPlugin)this).Config.Bind<int>("A) Colored text", "greenThreshold", 0, "Sets the value above which the profit % will be colored in green. E.g.: set to 30 to have the text be displayed as green only above 30% profit.");
		blueThresholdConfig = ((BaseUnityPlugin)this).Config.Bind<int>("A) Colored text", "blueThreshold", 100, "Sets the value above which the profit % will be colored in blue, used to identify high profit margins.");
		showBestDealsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Best Deals", "showBestDeals", true, "Display the best deals from the current port to the destinations in the currently selected bookmark. Set to false to disable.");
		autoReceiptConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Automatic Receipts", "autoReceipts", true, "Get the receipt automatically when closing the trade book, if one is available. Set to false to disable.");
	}
}
public class ProfitPercentPatches
{
	private static TextMesh productionText = new TextMesh();

	private static TextMesh percentText = new TextMesh();

	private static TextMesh perPoundText = new TextMesh();

	private static TextMesh highlightBar = new TextMesh();

	private static TextMesh islandNames;

	private static TextMesh buyColumn;

	private static TextMesh goodName;

	private static TextMesh sellColumn;

	private static TextMesh header;

	private static TextMesh profitColumn;

	private static TextMesh daysAgo;

	private static TextMesh tabLines;

	private static TextMesh horizontalLine;

	private static TextMesh conversionFees;

	private static TextMesh bdBestDeals = new TextMesh();

	private static TextMesh bdPercent = new TextMesh();

	private static TextMesh bdPerPound = new TextMesh();

	private static TextMesh bdAbsolute = new TextMesh();

	private static MethodInfo buypInfo;

	private static MethodInfo sellpInfo;

	private static Good[] goods;

	public static Dictionary<int, float[]> portProd = new Dictionary<int, float[]>();

	private const float charSize = 0.8f;

	private const float spacing = 0.073f;

	private static float[] goodWeights;

	private static string[] goodNames;

	public static void AwakePatch(EconomyUI __instance)
	{
		buypInfo = AccessTools.Method(typeof(EconomyUI), "GetBuyPrice", (Type[])null, (Type[])null);
		sellpInfo = AccessTools.Method(typeof(EconomyUI), "GetSellPrice", (Type[])null, (Type[])null);
		Transform detailsUI = ((Component)__instance).transform.Find("good details (right panel)").Find("details UI");
		GetVanillaColumns(detailsUI);
		AddModColumns(detailsUI);
		DisableUnusedUI(detailsUI);
		InitializeProd();
	}

	public static void MainPatch(int[][] ___bookmarkIslands, int ___currentBookmark, IslandMarket ___currentIsland)
	{
		goodName.text = Capitalize(goodName.text);
		InitializeUI();
		if (goods == null)
		{
			InitializeGoods();
		}
		for (int i = 0; i < ___bookmarkIslands[___currentBookmark].Length; i++)
		{
			int num = ___bookmarkIslands[___currentBookmark][i];
			int currentSelectedGood = EconomyUI.instance.currentSelectedGood;
			if (num == ___currentIsland.GetPortIndex())
			{
				SetHighlightBar(i);
			}
			if (ProfitPercentMain.showBestDealsConfig.Value)
			{
				bdBestDeals.text = "<color=#4D0000>★ Best Deals! ★</color>";
				FindBestDeals(___bookmarkIslands, ___currentBookmark, ___currentIsland);
			}
			else
			{
				bdBestDeals.text = "";
				bdPercent.text = "";
				bdPerPound.text = "";
				bdAbsolute.text = "";
			}
			GetProduction(num, currentSelectedGood);
			if (___currentIsland.knownPrices[num] == null || ___currentIsland.knownPrices[num].buyPrices == null)
			{
				if (num == ___currentIsland.GetPortIndex())
				{
					if (ProfitPercentMain.coloredTextConfig.Value)
					{
						TextMesh obj = islandNames;
						obj.text = obj.text + "<color=#4D0000>• " + Port.ports[num].GetPortName() + "</color>\n";
					}
					else
					{
						TextMesh obj2 = islandNames;
						obj2.text = obj2.text + "• " + Port.ports[num].GetPortName() + "\n";
					}
				}
				else
				{
					TextMesh obj3 = islandNames;
					obj3.text = obj3.text + Port.ports[num].GetPortName() + "\n";
				}
				TextMesh obj4 = profitColumn;
				obj4.text += "?\n";
				TextMesh obj5 = percentText;
				obj5.text += "?\n";
				TextMesh obj6 = perPoundText;
				obj6.text += "?\n";
				continue;
			}
			int num2 = BuyP(___currentIsland.GetPortIndex(), currentSelectedGood);
			int num3 = SellP(num, currentSelectedGood);
			int num4 = num3 - num2;
			float num5 = Mathf.Round((float)num4 / (float)num2 * 100f);
			float num6 = goodWeights[currentSelectedGood];
			float num7 = (float)Math.Round((float)num4 / num6, 2);
			if (ProfitPercentMain.coloredTextConfig.Value)
			{
				if (num == ___currentIsland.GetPortIndex())
				{
					TextMesh obj7 = islandNames;
					obj7.text = obj7.text + "<color=#4D0000>• " + Port.ports[num].GetPortName() + "</color>\n";
				}
				else
				{
					TextMesh obj8 = islandNames;
					obj8.text = obj8.text + Port.ports[num].GetPortName() + "\n";
				}
				int value = ProfitPercentMain.blueThresholdConfig.Value;
				int value2 = ProfitPercentMain.greenThresholdConfig.Value;
				if (ProfitPercentMain.blueThresholdConfig.Value < ProfitPercentMain.greenThresholdConfig.Value)
				{
					value = ProfitPercentMain.greenThresholdConfig.Value;
					value2 = ProfitPercentMain.blueThresholdConfig.Value;
				}
				if (float.IsInfinity(num5))
				{
					TextMesh obj9 = profitColumn;
					obj9.text += "<color=#CC7F00>- </color>\n";
					TextMesh obj10 = percentText;
					obj10.text += "<color=#CC7F00>- </color>\n";
					TextMesh obj11 = perPoundText;
					obj11.text += "<color=#CC7F00>- </color>\n";
				}
				else if (num5 > (float)value)
				{
					TextMesh obj12 = profitColumn;
					obj12.text += $"<color=#051139>{num4}</color>\n";
					TextMesh obj13 = percentText;
					obj13.text += $"<color=#051139>{num5}<size=40%>%</size></color>\n";
					TextMesh obj14 = perPoundText;
					obj14.text += $"<color=#051139>{num7}</color>\n";
				}
				else if (num5 > (float)value2)
				{
					TextMesh obj15 = profitColumn;
					obj15.text += $"<color=#003300>{num4}</color>\n";
					TextMesh obj16 = percentText;
					obj16.text += $"<color=#003300>{num5}<size=40%>%</size></color>\n";
					TextMesh obj17 = perPoundText;
					obj17.text += $"<color=#003300>{num7}</color>\n";
				}
				else if (num5 < 0f)
				{
					TextMesh obj18 = profitColumn;
					obj18.text += $"<color=#4D0000>{num4}</color>\n";
					TextMesh obj19 = percentText;
					obj19.text += $"<color=#4D0000>{num5}<size=40%>%</size></color>\n";
					TextMesh obj20 = perPoundText;
					obj20.text += $"<color=#4D0000>{num7}</color>\n";
				}
				else
				{
					TextMesh obj21 = profitColumn;
					obj21.text += $"<color=#CC7F00>{num4}</color>\n";
					TextMesh obj22 = percentText;
					obj22.text += $"<color=#CC7F00>{num5}<size=40%>%</size></color>\n";
					TextMesh obj23 = perPoundText;
					obj23.text += $"<color=#CC7F00>{num7}</color>\n";
				}
			}
			else
			{
				if (num == ___currentIsland.GetPortIndex())
				{
					TextMesh obj24 = islandNames;
					obj24.text = obj24.text + "• " + Port.ports[num].GetPortName() + "\n";
				}
				else
				{
					TextMesh obj25 = islandNames;
					obj25.text = obj25.text + Port.ports[num].GetPortName() + "\n";
				}
				if (float.IsInfinity(num5))
				{
					TextMesh obj26 = profitColumn;
					obj26.text += "- \n";
					TextMesh obj27 = percentText;
					obj27.text += "- \n";
					TextMesh obj28 = perPoundText;
					obj28.text += "- \n";
				}
				else
				{
					TextMesh obj29 = profitColumn;
					obj29.text += $"{num4}\n";
					TextMesh obj30 = percentText;
					obj30.text += $"{num5}<size=40%>%</size>\n";
					TextMesh obj31 = perPoundText;
					obj31.text += $"{num7}\n";
				}
			}
		}
	}

	public static void ButtonPatch(EconomyUIButton __instance)
	{
		if (((Object)__instance).name == "bookmark_button_X" && ProfitPercentMain.autoReceiptConfig.Value && EconomyUIReceiptScribe.instance.ReceiptAvailable())
		{
			EconomyUI.instance.PrintReceipt();
		}
	}

	private static void GetVanillaColumns(Transform detailsUI)
	{
		islandNames = ((Component)detailsUI.GetChild(2)).GetComponent<TextMesh>();
		islandNames.characterSize = 0.8f;
		Move(((Component)islandNames).transform, 0.23f);
		buyColumn = ((Component)detailsUI.GetChild(3)).GetComponent<TextMesh>();
		buyColumn.characterSize = 0.8f;
		Move(((Component)buyColumn).transform, -0.11f);
		goodName = ((Component)detailsUI.GetChild(6)).GetComponent<TextMesh>();
		sellColumn = ((Component)detailsUI.GetChild(7)).GetComponent<TextMesh>();
		sellColumn.characterSize = 0.8f;
		Move(((Component)sellColumn).transform, -0.27f);
		header = ((Component)detailsUI.GetChild(8)).GetComponent<TextMesh>();
		header.characterSize = 0.85f;
		header.text = "days ago  P.    buy     sell     profit      %    p. pound";
		profitColumn = ((Component)detailsUI.GetChild(9)).GetComponent<TextMesh>();
		profitColumn.characterSize = 0.8f;
		Move(((Component)profitColumn).transform, -0.45f);
		daysAgo = ((Component)detailsUI.GetChild(11)).GetComponent<TextMesh>();
		daysAgo.characterSize = 0.8f;
		Move(((Component)daysAgo).transform, 0.133f);
		tabLines = ((Component)detailsUI.GetChild(13)).GetComponent<TextMesh>();
		tabLines.text = "        |   |       |       |        |       |";
		horizontalLine = ((Component)detailsUI.GetChild(14)).GetComponent<TextMesh>();
		Move(((Component)horizontalLine).transform, -0.94f);
		conversionFees = ((Component)detailsUI.GetChild(16)).GetComponent<TextMesh>();
		conversionFees.characterSize = 0.8f;
		Move(((Component)conversionFees).transform, 0.64f, -0.8f);
	}

	private static void AddModColumns(Transform detailsUI)
	{
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		productionText = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)productionText).name = "productionText";
		productionText.characterSize = 0.8f;
		Move(((Component)productionText).transform, 0.05f);
		percentText = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)percentText).name = "percentText";
		percentText.characterSize = 0.8f;
		Move(((Component)percentText).transform, -0.61f);
		perPoundText = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)perPoundText).name = "perPoundText";
		perPoundText.characterSize = 0.8f;
		Move(((Component)perPoundText).transform, -0.78f);
		bdBestDeals = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)bdBestDeals).name = "bdBestDeals";
		bdBestDeals.characterSize = 1f;
		bdBestDeals.text = "<color=#4D0000>★ Best Deals! ★</color>";
		((Component)bdBestDeals).transform.Rotate(0f, 0f, 15f);
		Move(((Component)bdBestDeals).transform, 0.74f, -0.15f);
		bdBestDeals.anchor = (TextAnchor)3;
		bdPercent = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)bdPercent).name = "bdPercent";
		bdPercent.characterSize = 0.7f;
		bdPercent.text = "Salmon from here to there will give X in profit";
		Move(((Component)bdPercent).transform, 0.64f, -0.2f);
		bdPercent.anchor = (TextAnchor)3;
		bdPerPound = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)bdPerPound).name = "bdPerPound";
		bdPerPound.characterSize = 0.7f;
		bdPerPound.text = "Salmon from here to there will give X in profit";
		Move(((Component)bdPerPound).transform, 0.64f, -0.25f);
		bdPerPound.anchor = (TextAnchor)3;
		bdAbsolute = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)bdAbsolute).name = "bdAbsolute";
		bdAbsolute.characterSize = 0.7f;
		bdAbsolute.text = "Salmon from here to there will give X in profit";
		Move(((Component)bdAbsolute).transform, 0.64f, -0.3f);
		bdAbsolute.anchor = (TextAnchor)3;
		highlightBar = Object.Instantiate<TextMesh>(buyColumn, detailsUI);
		((Object)highlightBar).name = "highlightBar";
		highlightBar.characterSize = 1f;
		highlightBar.text = "┌───────────────────────────────────┐\n└───────────────────────────────────┘";
		highlightBar.lineSpacing = 0.9f;
		highlightBar.color = new Color(0.25f, 0f, 0f);
		Move(((Component)highlightBar).transform, 0.64f, 0.622f);
		highlightBar.anchor = (TextAnchor)3;
	}

	private static void DisableUnusedUI(Transform detailsUI)
	{
		((Component)detailsUI.Find("highlight (parent)")).gameObject.SetActive(false);
	}

	private static void InitializeUI()
	{
		islandNames.text = "";
		productionText.text = "";
		profitColumn.text = "";
		perPoundText.text = "";
		percentText.text = "";
		((Component)highlightBar).gameObject.SetActive(false);
	}

	private static void InitializeProd()
	{
		Port[] array = Object.FindObjectsOfType<Port>();
		Port[] array2 = array;
		foreach (Port val in array2)
		{
			if (!((Object)(object)((Component)val).GetComponent<IslandMarket>() == (Object)null))
			{
				portProd.Add(val.portIndex, ((Component)val.island).GetComponent<IslandMarket>().production);
			}
		}
	}

	private static void InitializeGoods()
	{
		goods = (Good[])(object)new Good[portProd[0].Length];
		goodNames = new string[portProd[0].Length];
		goodWeights = new float[portProd[0].Length];
		for (int i = 0; i < goods.Length; i++)
		{
			ShipItem good = PrefabsDirectory.instance.GetGood(i);
			if (!((Object)(object)good == (Object)null))
			{
				goods[i] = ((Component)good).GetComponent<Good>();
				goodNames[i] = good.name;
				goodWeights[i] = goods[i].GetCargoWeight();
			}
		}
	}

	private static void SetHighlightBar(int i)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		((Component)highlightBar).gameObject.SetActive(true);
		float y = 0.622f - 0.073f * (float)i;
		Move(((Component)highlightBar).transform, ((Component)highlightBar).transform.localPosition.x, y);
	}

	private static void GetProduction(int portIndex, int goodIndex)
	{
		if (portProd[portIndex][goodIndex] >= 8f)
		{
			TextMesh obj = productionText;
			obj.text += "★\n";
		}
		else if (portProd[portIndex][goodIndex] > 0f)
		{
			TextMesh obj2 = productionText;
			obj2.text += "✓\n";
		}
		else if (portProd[portIndex][goodIndex] <= -5f)
		{
			TextMesh obj3 = productionText;
			obj3.text += "‼\n";
		}
		else if (portProd[portIndex][goodIndex] <= 0f)
		{
			TextMesh obj4 = productionText;
			obj4.text += "✗\n";
		}
		else
		{
			TextMesh obj5 = productionText;
			obj5.text += "error\n";
		}
	}

	private static int BuyP(int portIndex, int goodIndex)
	{
		object[] parameters = new object[2] { portIndex, goodIndex };
		return (int)buypInfo.Invoke(EconomyUI.instance, parameters);
	}

	private static int SellP(int portIndex, int goodIndex)
	{
		object[] parameters = new object[2] { portIndex, goodIndex };
		return (int)sellpInfo.Invoke(EconomyUI.instance, parameters);
	}

	private static void FindBestDeals(int[][] bookmark, int currentBookmark, IslandMarket currentMarket)
	{
		int num = int.MinValue;
		float num2 = float.MinValue;
		float num3 = float.MinValue;
		int num4 = -1;
		int num5 = -1;
		int num6 = -1;
		int num7 = -1;
		int num8 = -1;
		int num9 = -1;
		int portIndex = currentMarket.GetPortIndex();
		for (int i = 0; i < goods.Length; i++)
		{
			if ((Object)(object)goods[i] == (Object)null)
			{
				continue;
			}
			int num10 = BuyP(portIndex, i);
			for (int j = 0; j < bookmark[currentBookmark].Length; j++)
			{
				int num11 = bookmark[currentBookmark][j];
				if (currentMarket.knownPrices[num11] != null && currentMarket.knownPrices[num11].buyPrices != null)
				{
					int num12 = SellP(num11, i);
					int num13 = ((num10 != 0) ? (num12 - num10) : int.MinValue);
					float num14 = ((num10 != 0) ? Mathf.Round((float)num13 / (float)num10 * 100f) : float.MinValue);
					float num15 = goodWeights[i];
					float num16 = ((num10 != 0) ? ((float)Math.Round((float)num13 / num15, 2)) : float.MinValue);
					if (num13 > num)
					{
						num = num13;
						num4 = i;
						num7 = num11;
					}
					if (num14 > num2)
					{
						num2 = num14;
						num5 = i;
						num8 = num11;
					}
					if (num16 > num3)
					{
						num3 = num16;
						num6 = i;
						num9 = num11;
					}
				}
			}
		}
		bdPercent.text = $"• {Capitalize(goodNames[num5])} to {Port.ports[num8].GetPortName()} will return a profit of {num2}%!";
		bdPerPound.text = $"• {Capitalize(goodNames[num6])} to {Port.ports[num9].GetPortName()} will return a profit of {num3} per pound!";
		bdAbsolute.text = $"• {Capitalize(goodNames[num4])} to {Port.ports[num7].GetPortName()} will return a profit of {num} per unit!";
	}

	private static void Move(Transform transform, float x)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Vector3 localPosition = transform.localPosition;
		localPosition.x = x;
		transform.localPosition = localPosition;
	}

	private static void Move(Transform transform, float x, float y)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		Vector3 localPosition = transform.localPosition;
		localPosition.x = x;
		localPosition.y = y;
		transform.localPosition = localPosition;
	}

	private static string Capitalize(string s)
	{
		return char.ToUpper(s[0]) + s.Substring(1);
	}
}