Decompiled source of JournalInfo v1.0.0

BepInEx/plugins/OldMarket.JournalInfo.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
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("OldMarket.JournalInfo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OldMarket.JournalInfo")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2f65e314-8a52-49b7-bb5b-b863db3476f8")]
[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")]
[BepInPlugin("oldmarket.journalinfo", "Old Market Journal Info", "1.0.0")]
public class JournalInfoPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "oldmarket.journalinfo";

	public const string PluginName = "Old Market Journal Info";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			Harmony val = new Harmony("oldmarket.journalinfo");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[JournalInfo] Patches applied.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[JournalInfo] Failed to apply patches: " + ex));
		}
	}
}
namespace OldMarket.JournalInfo;

internal static class JournalIconLoader
{
	private const string MissingIconResourceName = "OldMarket.JournalInfo.Resources.Missing.png";

	private static Sprite _missingSprite;

	public static Sprite GetMissingSprite()
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_missingSprite != (Object)null)
		{
			return _missingSprite;
		}
		try
		{
			Assembly assembly = typeof(JournalIconLoader).Assembly;
			using Stream stream = assembly.GetManifestResourceStream("OldMarket.JournalInfo.Resources.Missing.png");
			if (stream == null)
			{
				ManualLogSource log = JournalInfoPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[JournalInfo.Icon] Embedded resource 'OldMarket.JournalInfo.Resources.Missing.png' not found.");
				}
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num = stream.Read(array, 0, array.Length);
			if (num != array.Length)
			{
				ManualLogSource log2 = JournalInfoPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[JournalInfo.Icon] Read size mismatch (stream truncated?).");
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				ManualLogSource log3 = JournalInfoPlugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)"[JournalInfo.Icon] ImageConversion.LoadImage failed.");
				}
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Object)val).name = "JournalInfo.MissingIconTexture";
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			_missingSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			((Object)_missingSprite).name = "JournalInfo.MissingIcon";
			return _missingSprite;
		}
		catch (Exception ex)
		{
			ManualLogSource log4 = JournalInfoPlugin.Log;
			if (log4 != null)
			{
				log4.LogError((object)("[JournalInfo.Icon] Failed to load embedded Missing.png: " + ex));
			}
			return null;
		}
	}
}
public static class JournalInfoApi
{
	public static IReadOnlyDictionary<long, int> GetMissingProducts()
	{
		return MissingProductTracker.GetSnapshot();
	}

	public static Sprite GetMissingIcon()
	{
		return JournalIconLoader.GetMissingSprite();
	}
}
internal static class MissingProductTracker
{
	private static readonly Dictionary<long, int> MissingCounts = new Dictionary<long, int>();

	public static void Clear()
	{
		MissingCounts.Clear();
	}

	public static void RegisterMissingProduct(ProductSO product)
	{
		if ((Object)(object)product == (Object)null)
		{
			return;
		}
		long id = ((ItemSO)product).id;
		if (id != 0)
		{
			if (MissingCounts.TryGetValue(id, out var value))
			{
				MissingCounts[id] = value + 1;
			}
			else
			{
				MissingCounts[id] = 1;
			}
		}
	}

	public static Dictionary<long, int> GetSnapshot()
	{
		return new Dictionary<long, int>(MissingCounts);
	}
}
[HarmonyPatch(typeof(GameManager))]
internal static class GameManager_OnDayChanged_MissingProductsPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("OnDayChanged")]
	private static void Postfix(GameManager __instance, int previous, int current)
	{
		MissingProductTracker.Clear();
	}
}
[HarmonyPatch(typeof(StateSearchProduct))]
internal static class StateSearchProduct_FindProduct_MissingProductsPatch
{
	private struct SearchState
	{
		public int IndexBefore;
	}

	private static readonly FieldInfo ScField = AccessTools.Field(typeof(State), "sc");

	[HarmonyPrefix]
	[HarmonyPatch("FindProduct")]
	private static void Prefix(StateSearchProduct __instance, ref SearchState __state)
	{
		CustomerController customer = GetCustomer(__instance);
		if ((Object)(object)customer == (Object)null)
		{
			__state.IndexBefore = -1;
		}
		else
		{
			__state.IndexBefore = customer.currentIndex;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("FindProduct")]
	private static void Postfix(StateSearchProduct __instance, SearchState __state)
	{
		if (__state.IndexBefore >= 0)
		{
			CustomerController customer = GetCustomer(__instance);
			if (!((Object)(object)customer == (Object)null) && customer.currentIndex == __state.IndexBefore + 1 && customer.shoppingList != null && __state.IndexBefore >= 0 && __state.IndexBefore < customer.shoppingList.Count)
			{
				ProductSO product = customer.shoppingList[__state.IndexBefore];
				MissingProductTracker.RegisterMissingProduct(product);
			}
		}
	}

	private static CustomerController GetCustomer(StateSearchProduct state)
	{
		if ((Object)(object)state == (Object)null || ScField == null)
		{
			return null;
		}
		try
		{
			object? value = ScField.GetValue(state);
			return (CustomerController)((value is CustomerController) ? value : null);
		}
		catch
		{
			return null;
		}
	}
}
internal static class JournalInventoryMaterialOrder
{
	private const string CategoryFileDirectory = "OldMarket.AutoStorage";

	private const string CategoryFileName = "OldMarket.AutoStorage.materialCategories.json";

	private static readonly Dictionary<long, int> CategoryOrder;

	static JournalInventoryMaterialOrder()
	{
		CategoryOrder = new Dictionary<long, int>();
		LoadCategoryOrder();
	}

	private static void LoadCategoryOrder()
	{
		try
		{
			string path = Path.Combine(Paths.ConfigPath, "OldMarket.AutoStorage");
			string text = Path.Combine(path, "OldMarket.AutoStorage.materialCategories.json");
			ManualLogSource log = JournalInfoPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[JournalInfo] Looking for AutoStorage material category file at: " + text));
			}
			if (!File.Exists(text))
			{
				ManualLogSource log2 = JournalInfoPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"[JournalInfo] AutoStorage material category file not found.");
				}
				return;
			}
			string text2 = File.ReadAllText(text);
			if (string.IsNullOrWhiteSpace(text2))
			{
				ManualLogSource log3 = JournalInfoPlugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)"[JournalInfo] AutoStorage material category file is empty.");
				}
				return;
			}
			if (text2.Length > 0 && text2[0] == '\ufeff')
			{
				ManualLogSource log4 = JournalInfoPlugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)"[JournalInfo] BOM detected at start of category file. Stripping it.");
				}
				text2 = text2.Substring(1);
			}
			ManualLogSource log5 = JournalInfoPlugin.Log;
			if (log5 != null)
			{
				log5.LogInfo((object)$"[JournalInfo] Category file length: {text2.Length} chars");
			}
			MatchCollection matchCollection = Regex.Matches(text2, "\"itemIds\"\\s*:\\s*\\[(.*?)\\]", RegexOptions.Singleline);
			if (matchCollection.Count == 0)
			{
				ManualLogSource log6 = JournalInfoPlugin.Log;
				if (log6 != null)
				{
					log6.LogWarning((object)"[JournalInfo] No \"itemIds\" blocks found in materialCategories file.");
				}
				return;
			}
			int num = 0;
			foreach (Match item in matchCollection)
			{
				string value = item.Groups[1].Value;
				MatchCollection matchCollection2 = Regex.Matches(value, "\\d+");
				foreach (Match item2 in matchCollection2)
				{
					int index = item2.Index;
					int length = item2.Length;
					bool flag = index > 0 && value[index - 1] == '.';
					bool flag2 = index + length < value.Length && value[index + length] == '.';
					if (!(flag || flag2) && long.TryParse(item2.Value, out var result) && !CategoryOrder.ContainsKey(result))
					{
						CategoryOrder[result] = num++;
					}
				}
			}
			ManualLogSource log7 = JournalInfoPlugin.Log;
			if (log7 != null)
			{
				log7.LogInfo((object)$"[JournalInfo] Parsed material category order from AutoStorage: {CategoryOrder.Count} itemIds.");
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log8 = JournalInfoPlugin.Log;
			if (log8 != null)
			{
				log8.LogError((object)("[JournalInfo] Failed to parse AutoStorage materialCategories.json: " + ex));
			}
		}
	}

	public static int GetGroupPriority(ItemSO item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return 100;
		}
		long id = item.id;
		if (id != 0L && CategoryOrder.ContainsKey(id))
		{
			return 0;
		}
		if (item is SeedSO)
		{
			return 2;
		}
		if (item is TreeSO)
		{
			return 3;
		}
		if (item is ToolSO)
		{
			return 4;
		}
		if (item is AnimalSO)
		{
			return 5;
		}
		if (item is BlockSO)
		{
			return 6;
		}
		if (item is BagSO)
		{
			return 7;
		}
		return 1;
	}

	public static int GetCategoryOrder(ItemSO item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return int.MaxValue;
		}
		if (CategoryOrder.TryGetValue(item.id, out var value))
		{
			return value;
		}
		return int.MaxValue;
	}
}
internal static class JournalInventoryBuilder
{
	private sealed class InventoryEntry
	{
		public ItemSO Item;

		public int StackCount;

		public int TotalAmount;
	}

	public static void RebuildJournalInventory(UIManager ui, JournalInventoryTab tab)
	{
		if ((Object)(object)ui == (Object)null || (Object)(object)ui.listInventory == (Object)null)
		{
			return;
		}
		Transform listInventory = ui.listInventory;
		Transform tabRow = JournalInventoryTabs.TabRow;
		for (int num = listInventory.childCount - 1; num >= 0; num--)
		{
			Transform child = listInventory.GetChild(num);
			if (!((Object)(object)child == (Object)(object)tabRow))
			{
				Object.Destroy((Object)(object)((Component)child).gameObject);
			}
		}
		VerticalLayoutGroup component = ((Component)listInventory).GetComponent<VerticalLayoutGroup>();
		if ((Object)(object)component != (Object)null)
		{
			((HorizontalOrVerticalLayoutGroup)component).spacing = 4f;
		}
		if (tab == JournalInventoryTab.Missing)
		{
			BuildMissingProductsSection(ui, listInventory);
			return;
		}
		Item[] array;
		try
		{
			array = Object.FindObjectsOfType<Item>();
		}
		catch (Exception ex)
		{
			ManualLogSource log = JournalInfoPlugin.Log;
			if (log != null)
			{
				log.LogError((object)("[JournalInfo.Inventory] FindObjectsOfType<Item>() failed: " + ex));
			}
			return;
		}
		if (array == null || array.Length == 0)
		{
			return;
		}
		Dictionary<ItemSO, InventoryEntry> dictionary = new Dictionary<ItemSO, InventoryEntry>();
		Dictionary<ItemSO, InventoryEntry> dictionary2 = new Dictionary<ItemSO, InventoryEntry>();
		Item[] array2 = array;
		foreach (Item val in array2)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			ItemSO itemSO = val.itemSO;
			if ((Object)(object)itemSO == (Object)null || itemSO is ToolSO || itemSO is BlockSO)
			{
				continue;
			}
			int value;
			try
			{
				value = val.amount.Value;
			}
			catch
			{
				continue;
			}
			if (value > 0)
			{
				Dictionary<ItemSO, InventoryEntry> dictionary3 = ((itemSO is ProductSO) ? dictionary : dictionary2);
				if (!dictionary3.TryGetValue(itemSO, out var value2))
				{
					value2 = (dictionary3[itemSO] = new InventoryEntry
					{
						Item = itemSO,
						StackCount = 0,
						TotalAmount = 0
					});
				}
				value2.StackCount++;
				value2.TotalAmount += value;
			}
		}
		bool flag = dictionary.Count > 0;
		bool flag2 = dictionary2.Count > 0;
		switch (tab)
		{
		case JournalInventoryTab.Products:
			if (!flag)
			{
				break;
			}
			{
				foreach (InventoryEntry item in dictionary.Values.OrderBy((InventoryEntry x) => x.Item.GetLocalizedName()))
				{
					AddInventoryRow(ui, listInventory, item.Item, item.StackCount, item.TotalAmount, isMaterial: false);
				}
				break;
			}
		case JournalInventoryTab.Materials:
		{
			if (!flag2)
			{
				break;
			}
			IOrderedEnumerable<InventoryEntry> orderedEnumerable = from e in dictionary2.Values
				orderby JournalInventoryMaterialOrder.GetGroupPriority(e.Item), JournalInventoryMaterialOrder.GetCategoryOrder(e.Item), e.Item.GetLocalizedName()
				select e;
			{
				foreach (InventoryEntry item2 in orderedEnumerable)
				{
					AddInventoryRow(ui, listInventory, item2.Item, item2.StackCount, item2.TotalAmount, isMaterial: true);
				}
				break;
			}
		}
		}
	}

	private static void AddInventoryRow(UIManager ui, Transform parent, ItemSO item, int stackCount, int totalAmount, bool isMaterial)
	{
		if ((Object)(object)ui.prefabIngredientTile == (Object)null || (Object)(object)item == (Object)null)
		{
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(ui.prefabIngredientTile, parent);
		IngredientTile component = val.GetComponent<IngredientTile>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		string text = item.GetLocalizedName();
		if (!isMaterial)
		{
			int num = CalculateBoxCountForProduct(item, totalAmount, stackCount);
			if (num > 0)
			{
				text = $"{text} x{num}";
			}
		}
		string text2 = FormatInventoryAmount(stackCount, totalAmount, isMaterial);
		component.BuildTile(item.sprite, text, text2);
	}

	private static int CalculateBoxCountForProduct(ItemSO item, int totalAmount, int stackCount)
	{
		if (totalAmount <= 0)
		{
			return 0;
		}
		ProductSO val = (ProductSO)(object)((item is ProductSO) ? item : null);
		if (val != null && ((ItemSO)val).amount > 0)
		{
			float num = ((ItemSO)val).amount;
			float num2 = (float)totalAmount / num;
			return Mathf.CeilToInt(num2);
		}
		return stackCount;
	}

	private static string FormatInventoryAmount(int stackCount, int totalAmount, bool isMaterial)
	{
		return totalAmount.ToString();
	}

	private static string GetMissingSectionTitle()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Locale selectedLocale = LocalizationSettings.SelectedLocale;
		object obj;
		if (selectedLocale == null)
		{
			obj = null;
		}
		else
		{
			LocaleIdentifier identifier = selectedLocale.Identifier;
			obj = ((LocaleIdentifier)(ref identifier)).Code;
		}
		if (obj == null)
		{
			obj = "en";
		}
		string text = (string)obj;
		if (text.StartsWith("ja"))
		{
			return "見つけられなかった商品";
		}
		return "Missing products";
	}

	private static void BuildMissingProductsSection(UIManager ui, Transform parent)
	{
		GameManager gm = GameManager.Instance;
		if ((Object)(object)gm == (Object)null)
		{
			return;
		}
		Dictionary<long, int> snapshot = MissingProductTracker.GetSnapshot();
		if (snapshot.Count == 0)
		{
			return;
		}
		Sprite missingSprite = JournalIconLoader.GetMissingSprite();
		AddSectionHeader(ui, parent, GetMissingSectionTitle(), missingSprite);
		var orderedEnumerable = from x in snapshot.Select(delegate(KeyValuePair<long, int> kv)
			{
				ItemSO itemById = gm.GetItemById(kv.Key);
				return new
				{
					Product = (ProductSO)(object)((itemById is ProductSO) ? itemById : null),
					Count = kv.Value
				};
			})
			where (Object)(object)x.Product != (Object)null && x.Count > 0
			orderby x.Count descending, ((ItemSO)x.Product).GetLocalizedName()
			select x;
		foreach (var item in orderedEnumerable)
		{
			AddMissingRow(ui, parent, item.Product, item.Count);
		}
	}

	private static void AddSectionHeader(UIManager ui, Transform parent, string title, Sprite icon)
	{
		if (!((Object)(object)ui.prefabIngredientTile == (Object)null))
		{
			GameObject val = Object.Instantiate<GameObject>(ui.prefabIngredientTile, parent);
			IngredientTile component = val.GetComponent<IngredientTile>();
			if (!((Object)(object)component == (Object)null))
			{
				component.BuildTile(icon, "<b>" + title + "</b>", string.Empty);
			}
		}
	}

	private static void AddMissingRow(UIManager ui, Transform parent, ProductSO product, int count)
	{
		if (!((Object)(object)ui.prefabIngredientTile == (Object)null) && !((Object)(object)product == (Object)null))
		{
			GameObject val = Object.Instantiate<GameObject>(ui.prefabIngredientTile, parent);
			IngredientTile component = val.GetComponent<IngredientTile>();
			if (!((Object)(object)component == (Object)null))
			{
				string text = FormatMissingCount(count);
				component.BuildTile(((ItemSO)product).sprite, ((ItemSO)product).GetLocalizedName(), text);
			}
		}
	}

	private static string FormatMissingCount(int count)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Locale selectedLocale = LocalizationSettings.SelectedLocale;
		object obj;
		if (selectedLocale == null)
		{
			obj = null;
		}
		else
		{
			LocaleIdentifier identifier = selectedLocale.Identifier;
			obj = ((LocaleIdentifier)(ref identifier)).Code;
		}
		if (obj == null)
		{
			obj = "en";
		}
		string text = (string)obj;
		if (text.StartsWith("ja"))
		{
			return $"×{count}";
		}
		return $"x{count}";
	}
}
[HarmonyPatch(typeof(UIManager))]
internal static class UIManager_OpenJournal_InventoryPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("OpenJournal")]
	private static void Postfix(UIManager __instance)
	{
		JournalInventoryTabs.OnOpenJournal(__instance);
	}
}
internal enum JournalInventoryTab
{
	Products,
	Materials,
	Missing
}
internal static class JournalInventoryTabs
{
	public static JournalInventoryTab CurrentTab;

	private static Transform _tabRow;

	private static UIManager _ui;

	internal static Transform TabRow => _tabRow;

	public static void OnOpenJournal(UIManager ui)
	{
		if (!((Object)(object)ui == (Object)null))
		{
			_ui = ui;
			_tabRow = null;
			EnsureTabs();
			JournalInventoryBuilder.RebuildJournalInventory(ui, CurrentTab);
			UpdateTabVisual();
		}
	}

	private static void EnsureTabs()
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		if (!((Object)(object)_ui == (Object)null) && !((Object)(object)_ui.listInventory == (Object)null))
		{
			Transform listInventory = _ui.listInventory;
			if ((Object)(object)_tabRow == (Object)null || (Object)(object)_tabRow.parent != (Object)(object)listInventory)
			{
				_tabRow = null;
				GameObject val = new GameObject("JournalInventoryTabsRow", new Type[3]
				{
					typeof(RectTransform),
					typeof(HorizontalLayoutGroup),
					typeof(LayoutElement)
				});
				RectTransform component = val.GetComponent<RectTransform>();
				((Transform)component).SetParent(listInventory, false);
				HorizontalLayoutGroup component2 = val.GetComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component2).spacing = 8f;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
				((LayoutGroup)component2).childAlignment = (TextAnchor)3;
				((LayoutGroup)component2).padding = new RectOffset(8, 8, 4, 4);
				LayoutElement component3 = val.GetComponent<LayoutElement>();
				component3.minHeight = 32f;
				component3.preferredHeight = 32f;
				_tabRow = val.transform;
				bool flag = JournalLocalizationUtil.IsJapanese();
				CreateTabButton(_tabRow, flag ? "商品" : "Products", JournalInventoryTab.Products);
				CreateTabButton(_tabRow, flag ? "その他" : "Other", JournalInventoryTab.Materials);
				CreateTabButton(_tabRow, flag ? "不足" : "Missing", JournalInventoryTab.Missing);
			}
			_tabRow.SetSiblingIndex(0);
		}
	}

	private static void CreateTabButton(Transform parent, string label, JournalInventoryTab tab)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Expected O, but got Unknown
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Tab_" + tab, new Type[3]
		{
			typeof(RectTransform),
			typeof(Image),
			typeof(Button)
		});
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		component.sizeDelta = new Vector2(0f, 32f);
		LayoutElement val2 = val.AddComponent<LayoutElement>();
		val2.preferredWidth = 120f;
		val2.minHeight = 32f;
		Image component2 = val.GetComponent<Image>();
		((Graphic)component2).color = new Color(1f, 1f, 1f, 0.15f);
		Button component3 = val.GetComponent<Button>();
		((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
		{
			CurrentTab = tab;
			if ((Object)(object)_ui != (Object)null)
			{
				JournalInventoryBuilder.RebuildJournalInventory(_ui, CurrentTab);
				UpdateTabVisual();
			}
		});
		GameObject val3 = new GameObject("Label", new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		RectTransform component4 = val3.GetComponent<RectTransform>();
		((Transform)component4).SetParent(val.transform, false);
		component4.anchorMin = Vector2.zero;
		component4.anchorMax = Vector2.one;
		component4.offsetMin = Vector2.zero;
		component4.offsetMax = Vector2.zero;
		TextMeshProUGUI component5 = val3.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component5).text = label;
		((TMP_Text)component5).alignment = (TextAlignmentOptions)514;
		((TMP_Text)component5).enableAutoSizing = true;
		((TMP_Text)component5).fontSizeMin = 14f;
		((TMP_Text)component5).fontSizeMax = 24f;
		if ((Object)(object)_ui != (Object)null && (Object)(object)_ui.textJournalRent != (Object)null)
		{
			((TMP_Text)component5).font = ((TMP_Text)_ui.textJournalRent).font;
			((Graphic)component5).color = ((Graphic)_ui.textJournalRent).color;
		}
	}

	private static void UpdateTabVisual()
	{
		if ((Object)(object)_tabRow == (Object)null)
		{
			return;
		}
		for (int i = 0; i < _tabRow.childCount; i++)
		{
			Transform child = _tabRow.GetChild(i);
			TextMeshProUGUI componentInChildren = ((Component)child).GetComponentInChildren<TextMeshProUGUI>();
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				bool flag = ((Object)child).name == "Tab_" + CurrentTab;
				((TMP_Text)componentInChildren).fontStyle = (FontStyles)(flag ? 1 : 0);
				((TMP_Text)componentInChildren).alpha = (flag ? 1f : 0.6f);
			}
		}
	}
}
internal static class JournalLocalizationUtil
{
	public static bool IsJapanese()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Locale selectedLocale = LocalizationSettings.SelectedLocale;
			if ((Object)(object)selectedLocale == (Object)null)
			{
				return false;
			}
			LocaleIdentifier identifier = selectedLocale.Identifier;
			string code = ((LocaleIdentifier)(ref identifier)).Code;
			if (string.IsNullOrEmpty(code))
			{
				return false;
			}
			return code.StartsWith("ja", StringComparison.OrdinalIgnoreCase);
		}
		catch
		{
			return false;
		}
	}

	public static string GetLocalized(string table, string key, string fallback)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			LocalizedStringDatabase stringDatabase = LocalizationSettings.StringDatabase;
			if (stringDatabase == null)
			{
				return fallback;
			}
			string localizedString = stringDatabase.GetLocalizedString(TableReference.op_Implicit(table), TableEntryReference.op_Implicit(key), (Locale)null, (FallbackBehavior)0, Array.Empty<object>());
			return string.IsNullOrEmpty(localizedString) ? fallback : localizedString;
		}
		catch
		{
			return fallback;
		}
	}
}
internal static class JournalBudgetCalculator
{
	private static readonly FieldInfo DailyTransactionsField = AccessTools.Field(typeof(GameManager), "dailyTransactions");

	public static int CalculateRequiredBalance()
	{
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		GameManager instance = GameManager.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			return 0;
		}
		int rent = instance.GetRent();
		int maintenanceValue = instance.GetMaintenanceValue();
		int num = 0;
		List<long> activeEmployees = instance.GetActiveEmployees();
		if (activeEmployees != null)
		{
			for (int i = 0; i < activeEmployees.Count; i++)
			{
				long num2 = activeEmployees[i];
				EmployeeSO employeeById = instance.GetEmployeeById(num2);
				if ((Object)(object)employeeById != (Object)null)
				{
					num += employeeById.price;
				}
			}
		}
		int num3 = 0;
		try
		{
			if (DailyTransactionsField?.GetValue(instance) is List<Transaction> list)
			{
				for (int j = 0; j < list.Count; j++)
				{
					num3 += list[j].Amount;
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = JournalInfoPlugin.Log;
			if (log != null)
			{
				log.LogError((object)("[JournalInfo.SafeBudget] Failed to read dailyTransactions: " + ex));
			}
		}
		int num4 = num3 - rent - maintenanceValue;
		if (num4 < 0)
		{
			num4 = 0;
		}
		int num5 = instance.CalculateTax(num4);
		if (num5 < 0)
		{
			num5 = -num5;
		}
		int num6 = rent + maintenanceValue + num + num5;
		if (num6 < 0)
		{
			num6 = 0;
		}
		return num6;
	}
}
[HarmonyPatch(typeof(UIManager))]
internal static class UIManager_OpenJournal_SafeBudgetPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("OpenJournal")]
	private static void Postfix(UIManager __instance)
	{
		GameManager instance = GameManager.Instance;
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.textJournalBankruptcy == (Object)null) && !((Object)(object)instance == (Object)null))
		{
			int num = JournalBudgetCalculator.CalculateRequiredBalance();
			int coinsValue = instance.GetCoinsValue();
			bool flag = JournalLocalizationUtil.IsJapanese();
			int bankruptcyDayCounterValue = instance.GetBankruptcyDayCounterValue();
			int maxDaysForBankruptcy = instance.maxDaysForBankruptcy;
			string text = $"{bankruptcyDayCounterValue}/{maxDaysForBankruptcy}";
			string arg = (flag ? "翌朝に必要な残高" : "Required balance for next morning");
			string arg2 = $"{arg}: {num} C";
			string text2;
			if (coinsValue < num)
			{
				string arg3 = (flag ? "すでに安全ラインを下回っています" : "Already below the safe line");
				text2 = $"\n<color=#CC4444><size=80%>{arg2}\n{arg3}</size></color>";
			}
			else
			{
				text2 = $"\n<size=80%>{arg2}</size>";
			}
			((TMP_Text)__instance.textJournalBankruptcy).text = text + text2;
		}
	}
}