using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using I2.Loc;
using Microsoft.CodeAnalysis;
using PerfectRandom.Sulfur.Core;
using PerfectRandom.Sulfur.Core.Items;
using PerfectRandom.Sulfur.Core.Stats;
using PerfectRandom.Sulfur.Core.UI.Inventory;
using PerfectRandom.Sulfur.Core.UI.ItemDescription;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("net.mizle.SulfurRecipeBook")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Item tooltips show recipes that can be created with that item.")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0")]
[assembly: AssemblyProduct("SulfurRecipeBook")]
[assembly: AssemblyTitle("net.mizle.SulfurRecipeBook")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/eai04191/SulfurRecipeBook")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace SulfurRecipeBook
{
[BepInPlugin("net.mizle.SulfurRecipeBook", "SulfurRecipeBook", "2.1.0")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger;
public static ConfigEntry<bool> ConfigShowHealPerSlot;
public static ConfigEntry<KeyCode> ConfigPrevPageKey;
public static ConfigEntry<KeyCode> ConfigNextPageKey;
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Plugin net.mizle.SulfurRecipeBook is loaded!");
ConfigShowHealPerSlot = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHealPerSlot", false, "Show heal per slot in item description");
ConfigPrevPageKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "PrevPageKey", (KeyCode)282, "Key to go to previous recipe page");
ConfigNextPageKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "NextPageKey", (KeyCode)283, "Key to go to next recipe page");
Harmony.CreateAndPatchAll(typeof(RecipeBook), (string)null);
Harmony.CreateAndPatchAll(typeof(ReversePatch), (string)null);
}
}
internal class QuantityRange
{
public int Min { get; set; } = int.MaxValue;
public int Max { get; set; }
public void Update(int value)
{
Min = Math.Min(Min, value);
Max = Math.Max(Max, value);
}
}
public static class RecipeAnalyzer
{
private const string SeparatorColor = "<size=-1><color=#6D8791>";
private const string ColorEnd = "</color></size>";
public static Dictionary<string, string> AnalyzeRecipes(List<RecipeData> recipes)
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
IEnumerable<IGrouping<string, RecipeData>> enumerable = from recipe in recipes
group recipe by string.Join("+", from i in recipe.itemsNeeded
select i.item.value into x
orderby x
select x);
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (IGrouping<string, RecipeData> item3 in enumerable)
{
List<RecipeData> list = item3.ToList();
Dictionary<ushort, QuantityRange> dictionary2 = new Dictionary<ushort, QuantityRange>();
Dictionary<ushort, (QuantityRange, RecipeData)> dictionary3 = new Dictionary<ushort, (QuantityRange, RecipeData)>();
foreach (RecipeData item4 in list)
{
foreach (IngredientDefinition item5 in item4.itemsNeeded)
{
ushort value = item5.item.value;
if (!dictionary2.TryGetValue(value, out var value2))
{
value2 = (dictionary2[value] = new QuantityRange());
}
value2.Update(item5.quantity);
}
ushort value3 = item4.createsItem.value;
if (!dictionary3.TryGetValue(value3, out var value4))
{
value4 = (dictionary3[value3] = (new QuantityRange(), item4));
}
value4.Item1.Update(item4.quantityCreated);
}
RecipeData firstRecipe = list[0];
IEnumerable<string> values = dictionary2.Select((KeyValuePair<ushort, QuantityRange> kvp) => FormatRange(GetDisplayName(firstRecipe, kvp.Key), kvp.Value));
foreach (KeyValuePair<ushort, (QuantityRange, RecipeData)> item6 in dictionary3)
{
item6.Deconstruct(out var key, out var value5);
(QuantityRange, RecipeData) tuple2 = value5;
ushort identifier = key;
QuantityRange item = tuple2.Item1;
RecipeData item2 = tuple2.Item2;
string text = FormatRange(GetDisplayName(item2, identifier), item);
if (Plugin.ConfigShowHealPerSlot.Value)
{
float num = CalculateHealPerSlot(AssetAccess.GetAsset(item2.createsItem));
if (num > 0f)
{
text += $"<size=-1> [{num:F2}]</size>";
}
}
string value6 = string.Join("<size=-1><color=#6D8791> + </color></size>", values) + "<size=-1><color=#6D8791> = </color></size>" + text;
dictionary[item3.Key] = value6;
}
}
return dictionary;
}
private static string GetDisplayName(RecipeData recipe, ushort identifier)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
if (identifier == recipe.createsItem.value)
{
return AssetAccess.GetAsset(recipe.createsItem).LocalizedDisplayName;
}
return AssetAccess.GetAsset(((IEnumerable<IngredientDefinition>)recipe.itemsNeeded).FirstOrDefault((Func<IngredientDefinition, bool>)((IngredientDefinition i) => i.item.value == identifier)).item).LocalizedDisplayName ?? identifier.ToString();
}
public static float CalculateHealPerSlot(ItemDefinition item)
{
int num = ((Vector2Int)(ref item.inventorySize)).x * ((Vector2Int)(ref item.inventorySize)).y;
BuffDefinition? obj = item.buffsOnConsume.Find((BuffDefinition buff) => (int)buff.attributeId == 54);
if (obj == null)
{
return 0f;
}
return obj.totalValueOverride / (float)num;
}
private static string FormatRange(string itemName, QuantityRange range)
{
string text = ((range.Min == range.Max) ? $"x{range.Min}" : $"x({range.Min}~{range.Max})");
return itemName + "<size=-1><color=#6D8791>" + text + "</color></size>";
}
}
[HarmonyPatch]
internal class ReversePatch
{
[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
public static void AddTextLineAsAttribute(object instance, string key, ref int childIndex, string value = "", string modifier = "", bool skipSeparator = false)
{
throw new NotImplementedException("It's a stub");
}
[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
public static void AddTextLineAsDescription(object instance, string descriptionText, ref int childIndex)
{
throw new NotImplementedException("It's a stub");
}
}
[HarmonyPatch]
internal class RecipeBook
{
private static readonly List<RecipeData> AllRecipe = ((Func<List<RecipeData>>)delegate
{
RecipeDatabase recipeDatabase = StaticInstance<AsyncAssetLoading>.Instance.recipeDatabase;
return (from r in recipeDatabase.enchantmentRecipes.Concat(recipeDatabase.cookingRecipes)
where r.canBeCrafted
select r).ToList();
})();
private static bool _fontAtlasPopulationModeUpdated;
private static int _currentPage;
private static int _totalPages;
private const int ItemsPerPage = 20;
private static ItemDescription? _lastItemDescription;
private static InventoryItem? _lastInventoryItem;
private static Vector2? _originalSizeDelta;
private static InventoryItem GetInventoryItem(ItemDescription instance)
{
return Traverse.Create((object)instance).Field("inventoryRepresentation").GetValue<InventoryItem>();
}
private static Transform GetContentTransform(ItemDescription instance)
{
return Traverse.Create((object)instance).Field("contentTransform").GetValue<Transform>();
}
private static List<RecipeData> FindRecipe(InventoryItem targetItem)
{
InventoryItem targetItem2 = targetItem;
return AllRecipe.Where((RecipeData recipe) => recipe.itemsNeeded.Any((IngredientDefinition ingredient) => ingredient.item.value == targetItem2.itemDefinition.id.value)).ToList();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryUI), "Update")]
private static void HandlePageNavigationInput()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
int num = _currentPage;
if (Input.GetKeyDown(Plugin.ConfigPrevPageKey.Value) && _currentPage > 0)
{
num = _currentPage - 1;
}
else if (Input.GetKeyDown(Plugin.ConfigNextPageKey.Value) && _currentPage < _totalPages - 1)
{
num = _currentPage + 1;
}
if (num != _currentPage)
{
_currentPage = num;
RefreshItemDescription();
Plugin.Logger.LogInfo((object)$"Switched to page {_currentPage}");
}
}
private static void RefreshItemDescription()
{
if (_lastItemDescription != null)
{
InventoryItem inventoryItem = GetInventoryItem(_lastItemDescription);
((Component)_lastItemDescription).gameObject.SetActive(false);
((Component)_lastItemDescription).gameObject.SetActive(true);
_lastItemDescription.Setup(inventoryItem);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemDescription), "Setup", new Type[] { typeof(InventoryItem) })]
private static void DescriptionSetupPostfix(ItemDescription __instance, InventoryItem inventoryItem)
{
//IL_0011: 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)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
RectTransform component = ((Component)__instance).gameObject.GetComponent<RectTransform>();
Vector2 valueOrDefault = _originalSizeDelta.GetValueOrDefault();
if (!_originalSizeDelta.HasValue)
{
valueOrDefault = component.sizeDelta;
_originalSizeDelta = valueOrDefault;
}
component.sizeDelta = _originalSizeDelta.Value;
if ((Object)(object)_lastInventoryItem != (Object)(object)inventoryItem)
{
_currentPage = 0;
}
_lastItemDescription = __instance;
_lastInventoryItem = inventoryItem;
List<RecipeData> list = FindRecipe(inventoryItem);
if (list.Count == 0)
{
return;
}
Dictionary<string, string> dictionary = RecipeAnalyzer.AnalyzeRecipes(list);
Plugin.Logger.LogInfo((object)$"Found {dictionary.Count} recipes for this item.");
_totalPages = (int)Math.Ceiling((double)dictionary.Count / 20.0);
List<KeyValuePair<string, string>> list2 = dictionary.Skip(_currentPage * 20).Take(20).ToList();
Transform contentTransform = GetContentTransform(__instance);
if (!_fontAtlasPopulationModeUpdated)
{
TextMeshProUGUI componentInChildren = ((Component)contentTransform).GetComponentInChildren<TextMeshProUGUI>();
if (componentInChildren != null)
{
((TMP_Text)componentInChildren).font.atlasPopulationMode = (AtlasPopulationMode)0;
_fontAtlasPopulationModeUpdated = true;
}
}
int childIndex = contentTransform.childCount;
ReversePatch.AddTextLineAsAttribute(__instance, $"Recipes ({_currentPage + 1} / {_totalPages}):", ref childIndex);
foreach (KeyValuePair<string, string> item in list2)
{
ReversePatch.AddTextLineAsDescription(__instance, item.Value, ref childIndex);
}
((Component)__instance).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(300f, 100f);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemDescription), "AddDescriptionText")]
private static void AddDescriptionTextPostfix(ItemDescription __instance, string descriptionText)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Invalid comparison between Unknown and I4
if (!Plugin.ConfigShowHealPerSlot.Value)
{
return;
}
InventoryItem inventoryItem = GetInventoryItem(__instance);
if (inventoryItem.itemDefinition.buffsOnConsume.Find((BuffDefinition b) => (int)b.attributeId == 54) == null)
{
return;
}
foreach (BuffDefinition item in inventoryItem.itemDefinition.buffsOnConsume)
{
if ((int)item.attributeId != 54 || LocalizationManager.GetTranslation("ItemDescriptions/DynamicString_HealthConsumable", true, 0, true, false, (GameObject)null, (string)null, true).Replace("VALUE_X", item.totalValueOverride.ToString()).Replace("DURATION_X", item.duration.ToString()) != descriptionText)
{
break;
}
float num = RecipeAnalyzer.CalculateHealPerSlot(inventoryItem.itemDefinition);
string newDescription = $"{descriptionText} [Heal per Slot: {num}]";
UpdateLatestDescription(__instance, newDescription);
}
}
private static void UpdateLatestDescription(ItemDescription instance, string newDescription)
{
Transform child = ((Component)instance).transform.GetChild(0);
TextMeshProUGUI componentInChildren = ((Component)child.GetChild(child.childCount - 1)).GetComponentInChildren<TextMeshProUGUI>();
if ((Object)(object)componentInChildren == (Object)null)
{
Plugin.Logger.LogInfo((object)"No TextMeshProUGUI found.");
}
else
{
((TMP_Text)componentInChildren).text = newDescription;
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "net.mizle.SulfurRecipeBook";
public const string PLUGIN_NAME = "SulfurRecipeBook";
public const string PLUGIN_VERSION = "2.1.0";
}
}