Decompiled source of CraftSupport v1.0.0

BepInEx/plugins/OldMarket.CraftSupport.dll

Decompiled a month 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.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OldMarket.CraftSupport")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OldMarket.CraftSupport")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("041278ab-957b-4957-9f70-eb09000c864e")]
[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 OldMarket.CraftSupport;

[BepInPlugin("oldmarket.craftsupport", "Old Market Craft Support", "1.0.0")]
public class CraftSupportPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "oldmarket.craftsupport";

	public const string PluginName = "Old Market Craft Support";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Harmony val = new Harmony("oldmarket.craftsupport");
		val.PatchAll();
	}

	internal static string GetLocaleCode()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Locale selectedLocale = LocalizationSettings.SelectedLocale;
			object result;
			if (!((Object)(object)selectedLocale != (Object)null))
			{
				result = null;
			}
			else
			{
				LocaleIdentifier identifier = selectedLocale.Identifier;
				result = ((LocaleIdentifier)(ref identifier)).Code;
			}
			return (string)result;
		}
		catch
		{
			return null;
		}
	}

	internal static bool IsJapaneseLocale()
	{
		string localeCode = GetLocaleCode();
		return !string.IsNullOrEmpty(localeCode) && localeCode.StartsWith("ja", StringComparison.OrdinalIgnoreCase);
	}

	internal static string GetAmountLabel()
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (IsJapaneseLocale())
			{
				return "数量";
			}
			return LocalizationSettings.StringDatabase.GetLocalizedString(TableReference.op_Implicit("Translations"), TableEntryReference.op_Implicit("amount"), (Locale)null, (FallbackBehavior)0, Array.Empty<object>());
		}
		catch
		{
			return "Amount";
		}
	}

	internal static string GetWholesaleLabel()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			return LocalizationSettings.StringDatabase.GetLocalizedString(TableReference.op_Implicit("Translations"), TableEntryReference.op_Implicit("wholesale"), (Locale)null, (FallbackBehavior)0, Array.Empty<object>());
		}
		catch
		{
			return "Wholesale";
		}
	}
}
internal static class CraftSupportLogic
{
	private static FieldInfo _panelRecipeIngredientsField;

	private static void CountWorldItems(ItemSO itemSO, out int totalAmount, out int maxStackSeen)
	{
		totalAmount = 0;
		maxStackSeen = 0;
		if ((Object)(object)itemSO == (Object)null)
		{
			return;
		}
		try
		{
			Item[] array = Object.FindObjectsOfType<Item>();
			foreach (Item val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.itemSO != (Object)(object)itemSO)
				{
					continue;
				}
				try
				{
					if (val.amount != null)
					{
						int value = val.amount.Value;
						totalAmount += value;
						if (value > maxStackSeen)
						{
							maxStackSeen = value;
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = CraftSupportPlugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("[CraftSupport] Item.amount read failed for " + ((Object)itemSO).name + ": " + ex.Message));
					}
				}
			}
		}
		catch (Exception arg)
		{
			ManualLogSource log2 = CraftSupportPlugin.Log;
			if (log2 != null)
			{
				log2.LogError((object)$"[CraftSupport] Failed counting stock for {((Object)itemSO).name}: {arg}");
			}
		}
	}

	private static string BuildStockText(int totalAmount, int maxStackSeen)
	{
		string amountLabel = CraftSupportPlugin.GetAmountLabel();
		bool flag = CraftSupportPlugin.IsJapaneseLocale();
		if (totalAmount <= 0)
		{
			amountLabel = (amountLabel ?? string.Empty).ToUpperInvariant();
			return amountLabel + ": 0";
		}
		string text;
		if (maxStackSeen > 1)
		{
			int num = totalAmount / maxStackSeen;
			text = ((num <= 0) ? totalAmount.ToString() : ((!flag) ? $"{totalAmount} (x{num})" : $"{totalAmount}(x{num})"));
		}
		else
		{
			text = totalAmount.ToString();
		}
		amountLabel = (amountLabel ?? string.Empty).ToUpperInvariant();
		return amountLabel + ": " + text;
	}

	internal static string BuildRecipeInfoLine(RecipeSO recipe)
	{
		if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.output == (Object)null)
		{
			return string.Empty;
		}
		ItemSO output = recipe.output;
		ProductSO val = (ProductSO)(object)((output is ProductSO) ? output : null);
		CountWorldItems(output, out var totalAmount, out var maxStackSeen);
		string text = BuildStockText(totalAmount, maxStackSeen);
		string text2 = string.Empty;
		if ((Object)(object)val != (Object)null)
		{
			try
			{
				GameManager instance = GameManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					int wholesalePrice = instance.GetWholesalePrice(val);
					if (wholesalePrice > 0)
					{
						int num = ((recipe.amount <= 0) ? 1 : recipe.amount);
						int num2 = wholesalePrice * num;
						string text3 = CraftSupportPlugin.GetWholesaleLabel() ?? "Wholesale";
						text3 = text3.ToUpperInvariant();
						bool flag = CraftSupportPlugin.IsJapaneseLocale();
						text2 = ((num <= 1) ? $"{text3}: {wholesalePrice} C" : ((!flag) ? $"{text3}: {num2} C ({wholesalePrice} C x{num})" : $"{text3}: {num2} C({wholesalePrice} C x{num})"));
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = CraftSupportPlugin.Log;
				if (log != null)
				{
					log.LogError((object)$"[CraftSupport] Failed calculating price for {((Object)output).name}: {arg}");
				}
			}
		}
		if (!string.IsNullOrEmpty(text2))
		{
			return text + "\n" + text2;
		}
		return text;
	}

	internal static string BuildIngredientInfoLine(ItemSO itemSO)
	{
		if ((Object)(object)itemSO == (Object)null)
		{
			return string.Empty;
		}
		CountWorldItems(itemSO, out var totalAmount, out var maxStackSeen);
		return BuildStockText(totalAmount, maxStackSeen);
	}

	internal static void ApplyToRecipeList(UIManager ui, List<RecipeSO> recipes)
	{
		if ((Object)(object)ui == (Object)null || (Object)(object)ui.listRecipes == (Object)null)
		{
			return;
		}
		Transform listRecipes = ui.listRecipes;
		int childCount = listRecipes.childCount;
		for (int i = 0; i < childCount; i++)
		{
			Transform child = listRecipes.GetChild(i);
			if ((Object)(object)child == (Object)null)
			{
				continue;
			}
			try
			{
				RecipeSO val = FindRecipeOnTile(child, recipes);
				if ((Object)(object)val == (Object)null || (Object)(object)val.output == (Object)null)
				{
					continue;
				}
				TextMeshProUGUI nameLabelOnTile = GetNameLabelOnTile(child, val);
				if (!((Object)(object)nameLabelOnTile == (Object)null))
				{
					string text = BuildRecipeInfoLine(val);
					if (!string.IsNullOrEmpty(text))
					{
						string localizedName = val.output.GetLocalizedName();
						((TMP_Text)nameLabelOnTile).richText = true;
						((TMP_Text)nameLabelOnTile).text = $"<size=140%>{localizedName}</size>\n<size=120%>{text}</size>";
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = CraftSupportPlugin.Log;
				if (log != null)
				{
					log.LogError((object)$"[CraftSupport] ApplyToRecipeList tile {i} failed: {arg}");
				}
			}
		}
	}

	internal static void ApplyToRecipeIngredients(UIManager ui, RecipeSO recipe)
	{
		if ((Object)(object)ui == (Object)null || (Object)(object)recipe == (Object)null)
		{
			return;
		}
		Transform recipeIngredientsParent = GetRecipeIngredientsParent(ui);
		if ((Object)(object)recipeIngredientsParent == (Object)null)
		{
			return;
		}
		GameManager instance = GameManager.Instance;
		if ((Object)(object)instance == (Object)null || instance.itemDatabase == null || instance.itemDatabase.Count == 0)
		{
			return;
		}
		Dictionary<string, ItemSO> dictionary = new Dictionary<string, ItemSO>();
		try
		{
			List<ItemSO> itemDatabase = instance.itemDatabase;
			for (int i = 0; i < itemDatabase.Count; i++)
			{
				ItemSO val = itemDatabase[i];
				if (!((Object)(object)val == (Object)null))
				{
					string localizedName;
					try
					{
						localizedName = val.GetLocalizedName();
					}
					catch
					{
						continue;
					}
					if (!string.IsNullOrEmpty(localizedName) && !dictionary.ContainsKey(localizedName))
					{
						dictionary.Add(localizedName, val);
					}
				}
			}
		}
		catch (Exception arg)
		{
			ManualLogSource log = CraftSupportPlugin.Log;
			if (log != null)
			{
				log.LogError((object)$"[CraftSupport] Build ingredient name map failed: {arg}");
			}
			return;
		}
		int childCount = recipeIngredientsParent.childCount;
		for (int j = 0; j < childCount; j++)
		{
			Transform child = recipeIngredientsParent.GetChild(j);
			if ((Object)(object)child == (Object)null)
			{
				continue;
			}
			try
			{
				TextMeshProUGUI componentInChildren = ((Component)child).GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					continue;
				}
				string text = ((TMP_Text)componentInChildren).text ?? string.Empty;
				int num = text.IndexOf('\n');
				string text2 = ((num < 0) ? text : text.Substring(0, num));
				text2 = text2.Trim();
				if (string.IsNullOrEmpty(text2))
				{
					((TMP_Text)componentInChildren).text = text;
					continue;
				}
				if (!dictionary.TryGetValue(text2, out var value) || (Object)(object)value == (Object)null)
				{
					((TMP_Text)componentInChildren).text = text2;
					continue;
				}
				string text3 = BuildIngredientInfoLine(value);
				if (string.IsNullOrEmpty(text3))
				{
					((TMP_Text)componentInChildren).text = text2;
					continue;
				}
				((TMP_Text)componentInChildren).richText = true;
				((TMP_Text)componentInChildren).text = $"<size=140%>{text2}</size>\n<size=120%>{text3}</size>";
			}
			catch (Exception arg2)
			{
				ManualLogSource log2 = CraftSupportPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"[CraftSupport] ApplyToRecipeIngredients tile {j} failed: {arg2}");
				}
			}
		}
	}

	private static Transform GetRecipeIngredientsParent(UIManager ui)
	{
		if ((Object)(object)ui == (Object)null)
		{
			return null;
		}
		try
		{
			if (_panelRecipeIngredientsField == null)
			{
				_panelRecipeIngredientsField = typeof(UIManager).GetField("panelRecipeIngredients", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_panelRecipeIngredientsField == null)
				{
					FieldInfo[] fields = typeof(UIManager).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						Type fieldType = fieldInfo.FieldType;
						if (typeof(Transform).IsAssignableFrom(fieldType) || typeof(GameObject).IsAssignableFrom(fieldType))
						{
							string text = fieldInfo.Name ?? string.Empty;
							string text2 = text.ToLowerInvariant();
							if (text2.Contains("recipe") && text2.Contains("ingredient"))
							{
								_panelRecipeIngredientsField = fieldInfo;
								break;
							}
						}
					}
				}
			}
			if (_panelRecipeIngredientsField == null)
			{
				ManualLogSource log = CraftSupportPlugin.Log;
				if (log != null)
				{
					log.LogDebug((object)"[CraftSupport] Recipe ingredients panel field not found.");
				}
				return null;
			}
			object value = _panelRecipeIngredientsField.GetValue(ui);
			Transform val = (Transform)((value is Transform) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.transform;
			}
			return null;
		}
		catch (Exception arg)
		{
			ManualLogSource log2 = CraftSupportPlugin.Log;
			if (log2 != null)
			{
				log2.LogError((object)$"[CraftSupport] GetRecipeIngredientsParent failed: {arg}");
			}
			return null;
		}
	}

	private static RecipeSO FindRecipeOnTile(Transform tile, List<RecipeSO> recipes)
	{
		if ((Object)(object)tile == (Object)null)
		{
			return null;
		}
		try
		{
			Component[] componentsInChildren = ((Component)tile).GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Type type = ((object)val).GetType();
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (typeof(RecipeSO).IsAssignableFrom(fieldInfo.FieldType))
					{
						object obj = null;
						try
						{
							obj = fieldInfo.GetValue(val);
						}
						catch
						{
						}
						RecipeSO val2 = (RecipeSO)((obj is RecipeSO) ? obj : null);
						if ((Object)(object)val2 != (Object)null)
						{
							return val2;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = CraftSupportPlugin.Log;
			if (log != null)
			{
				log.LogDebug((object)("[CraftSupport] FindRecipeOnTile reflection failed: " + ex.Message));
			}
		}
		if (recipes != null && recipes.Count > 0)
		{
			TextMeshProUGUI componentInChildren = ((Component)tile).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				string text = ((TMP_Text)componentInChildren).text ?? string.Empty;
				int num = text.IndexOf('\n');
				string text2 = ((num < 0) ? text : text.Substring(0, num));
				string text3 = text2;
				int num2 = text2.LastIndexOf('x');
				if (num2 > 0 && text2[num2 - 1] == ' ')
				{
					text3 = text2.Substring(0, num2 - 1);
				}
				for (int k = 0; k < recipes.Count; k++)
				{
					RecipeSO val3 = recipes[k];
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.output == (Object)null))
					{
						string localizedName = val3.output.GetLocalizedName();
						if (localizedName == text3)
						{
							return val3;
						}
					}
				}
			}
		}
		return null;
	}

	private static TextMeshProUGUI GetNameLabelOnTile(Transform tile, RecipeSO recipe)
	{
		if ((Object)(object)tile == (Object)null || (Object)(object)recipe == (Object)null || (Object)(object)recipe.output == (Object)null)
		{
			return null;
		}
		string localizedName = recipe.output.GetLocalizedName();
		TextMeshProUGUI[] componentsInChildren = ((Component)tile).GetComponentsInChildren<TextMeshProUGUI>(true);
		TextMeshProUGUI val = null;
		foreach (TextMeshProUGUI val2 in componentsInChildren)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				string text = ((TMP_Text)val2).text;
				if (!string.IsNullOrEmpty(text) && text.Contains(localizedName))
				{
					val = val2;
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null && componentsInChildren.Length != 0)
		{
			val = componentsInChildren[0];
		}
		return val;
	}
}
[HarmonyPatch(typeof(UIManager))]
internal static class UIManager_OpenRecipesPanel_Patch
{
	[HarmonyPostfix]
	[HarmonyPatch("OpenRecipesPanel")]
	private static void Postfix(UIManager __instance, List<RecipeSO> recipes)
	{
		CraftSupportLogic.ApplyToRecipeList(__instance, recipes);
	}
}
[HarmonyPatch(typeof(UIManager))]
internal static class UIManager_UpdateRecipeIngredients_Patch
{
	[HarmonyPostfix]
	[HarmonyPatch("UpdateRecipeIngredients")]
	private static void Postfix(UIManager __instance, RecipeSO recipeSO)
	{
		CraftSupportLogic.ApplyToRecipeIngredients(__instance, recipeSO);
	}
}