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 HarmonyLib;
using TMPro;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FoodMenuServingCounts")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FoodMenuServingCounts")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c26237b0-d31e-4d87-9e33-d235560dffdc")]
[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 FoodMenuServingCounts;
[BepInPlugin("FoodMenuServingCounts", "Food Menu Serving Counts", "1.0.0")]
public class FoodMenuServingCounts : BaseUnityPlugin
{
public const string PluginGuid = "FoodMenuServingCounts";
public const string PluginName = "Food Menu Serving Counts";
public const string PluginVersion = "1.0.0";
private void Awake()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
new Harmony("FoodMenuServingCounts").PatchAll(typeof(FoodMenuServingCounts).Assembly);
}
}
internal static class ServingTableCountsCache
{
private static bool _dirty = true;
private static float _nextRecalcTime = 0f;
private static readonly Dictionary<ushort, int> _counts = new Dictionary<ushort, int>(128);
internal static IReadOnlyDictionary<ushort, int> GetCounts()
{
Ensure();
return _counts;
}
internal static void MarkDirty()
{
_dirty = true;
}
private static void Ensure()
{
if (_dirty || !(Time.unscaledTime < _nextRecalcTime))
{
Recalc();
}
}
private static void Recalc()
{
_dirty = false;
_nextRecalcTime = Time.unscaledTime + 0.25f;
_counts.Clear();
ServingTableSlot[] array = Object.FindObjectsOfType<ServingTableSlot>(true);
foreach (ServingTableSlot val in array)
{
if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).IsSpawned)
{
continue;
}
ServingTable componentInParent = ((Component)val).GetComponentInParent<ServingTable>(true);
if (!((Object)(object)componentInParent != (Object)null) || !IsBedroomServingTable(componentInParent))
{
ushort value = val.itemDataId.Value;
if (value != 0)
{
_counts.TryGetValue(value, out var value2);
_counts[value] = value2 + 1;
}
}
}
}
private static bool IsBedroomServingTable(ServingTable st)
{
try
{
if (st.IsBedroomTable)
{
return true;
}
}
catch
{
}
if (ContainsBedroom(((Object)(object)((Component)st).gameObject != (Object)null) ? ((Object)((Component)st).gameObject).name : null))
{
return true;
}
Transform val = ((Component)st).transform;
while ((Object)(object)val != (Object)null)
{
if (ContainsBedroom(((Object)val).name))
{
return true;
}
val = val.parent;
}
return false;
}
private static bool ContainsBedroom(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
return name.IndexOf("Bedroom", StringComparison.OrdinalIgnoreCase) >= 0;
}
}
internal static class ServingCountUI
{
private sealed class ElementState
{
public ushort ItemDataId;
public string BaseName;
}
private static readonly Dictionary<RecipeMenuElement, ElementState> _states = new Dictionary<RecipeMenuElement, ElementState>(64);
private static readonly List<RecipeMenuElement> _remove = new List<RecipeMenuElement>(16);
private static float _nextUiUpdateTime = 0f;
private static FieldInfo _fiName;
internal static void RegisterOrUpdate(RecipeMenuElement element, ushort itemDataId)
{
if ((Object)(object)element == (Object)null)
{
return;
}
TextMeshProUGUI nameText = GetNameText(element);
if (!((Object)(object)nameText == (Object)null))
{
((TMP_Text)nameText).richText = true;
if (!_states.TryGetValue(element, out var value))
{
value = new ElementState();
_states[element] = value;
}
value.ItemDataId = itemDataId;
value.BaseName = StripInjectedCount(((TMP_Text)nameText).text);
UpdateElement(element, value, ServingTableCountsCache.GetCounts());
}
}
internal static void UpdateAllIfNeeded()
{
if (Time.unscaledTime < _nextUiUpdateTime)
{
return;
}
_nextUiUpdateTime = Time.unscaledTime + 0.25f;
IReadOnlyDictionary<ushort, int> counts = ServingTableCountsCache.GetCounts();
foreach (KeyValuePair<RecipeMenuElement, ElementState> state in _states)
{
RecipeMenuElement key = state.Key;
ElementState value = state.Value;
if ((Object)(object)key == (Object)null)
{
_remove.Add(key);
}
else
{
UpdateElement(key, value, counts);
}
}
for (int i = 0; i < _remove.Count; i++)
{
_states.Remove(_remove[i]);
}
_remove.Clear();
}
private static void UpdateElement(RecipeMenuElement element, ElementState st, IReadOnlyDictionary<ushort, int> counts)
{
if ((Object)(object)element == (Object)null || st == null)
{
return;
}
TextMeshProUGUI nameText = GetNameText(element);
if (!((Object)(object)nameText == (Object)null))
{
((TMP_Text)nameText).richText = true;
if (string.IsNullOrEmpty(st.BaseName))
{
st.BaseName = StripInjectedCount(((TMP_Text)nameText).text);
}
counts.TryGetValue(st.ItemDataId, out var value);
string text = "×" + value;
switch (value)
{
case 0:
text = "<color=#FF4040>" + text + "</color>";
break;
case 1:
text = "<color=#FFD200>" + text + "</color>";
break;
}
((TMP_Text)nameText).text = st.BaseName + " " + text;
}
}
private static string StripInjectedCount(string s)
{
if (string.IsNullOrEmpty(s))
{
return s;
}
s = s.TrimEnd(Array.Empty<char>());
if (s.EndsWith("</color>", StringComparison.OrdinalIgnoreCase))
{
int num = s.LastIndexOf("<color=", StringComparison.OrdinalIgnoreCase);
if (num >= 0)
{
int num2 = s.LastIndexOf(' ', num);
if (num2 >= 0)
{
return s.Substring(0, num2).TrimEnd(Array.Empty<char>());
}
}
}
int num3 = s.LastIndexOf('×');
if (num3 >= 1 && s[num3 - 1] == ' ' && int.TryParse(s.Substring(num3 + 1), out var _))
{
return s.Substring(0, num3 - 1).TrimEnd(Array.Empty<char>());
}
return s;
}
private static TextMeshProUGUI GetNameText(RecipeMenuElement element)
{
if (_fiName == null)
{
_fiName = AccessTools.Field(typeof(RecipeMenuElement), "_name");
}
if (!(_fiName != null))
{
return null;
}
object? value = _fiName.GetValue(element);
return (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
}
}
[HarmonyPatch(typeof(RecipeMenuElement), "SetItem")]
internal static class Patch_RecipeMenuElement_SetItem
{
private static void Postfix(RecipeMenuElement __instance, ItemData itemData)
{
if (!((Object)(object)__instance == (Object)null) && !((Object)(object)itemData == (Object)null))
{
ServingCountUI.RegisterOrUpdate(__instance, itemData.id);
}
}
}
[HarmonyPatch(typeof(FoodMenuUI), "Update")]
internal static class Patch_FoodMenuUI_Update
{
private static void Postfix()
{
ServingCountUI.UpdateAllIfNeeded();
}
}
[HarmonyPatch(typeof(ServingTableSlot), "OnItemDataIdChanged")]
internal static class Patch_ServingTableSlot_OnItemDataIdChanged
{
private static void Postfix()
{
ServingTableCountsCache.MarkDirty();
}
}