using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using NodeCanvas.DialogueTrees;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("IngredientTracker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("IngredientTracker")]
[assembly: AssemblyTitle("IngredientTracker")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace IngredientTracker;
[HarmonyPatch]
internal static class CraftingPatches
{
private static readonly FieldRef<CraftingMenu, List<KeyValuePair<int, Recipe>>> s_recipes = AccessTools.FieldRefAccess<CraftingMenu, List<KeyValuePair<int, Recipe>>>("m_complexeRecipes");
private static readonly FieldRef<CraftingMenu, List<RecipeDisplay>> s_displays = AccessTools.FieldRefAccess<CraftingMenu, List<RecipeDisplay>>("m_recipeDisplays");
private static readonly FieldRef<CraftingMenu, int> s_selected = AccessTools.FieldRefAccess<CraftingMenu, int>("m_lastRecipeIndex");
private static readonly FieldRef<CraftingMenu, int> s_lastCrafted = AccessTools.FieldRefAccess<CraftingMenu, int>("m_lastCraftedRecipeIndex");
private static readonly FieldRef<RecipeDisplay, Image> s_preview = AccessTools.FieldRefAccess<RecipeDisplay, Image>("m_imgRecipeResultPreview");
private static readonly Action<CraftingMenu> s_refreshAutoRecipe = AccessTools.MethodDelegate<Action<CraftingMenu>>(AccessTools.Method(typeof(CraftingMenu), "RefreshAutoRecipe", (Type[])null, (Type[])null), (object)null, true);
private static Character s_sorting;
[HarmonyPrefix]
[HarmonyPatch(typeof(CraftingMenu), "RefreshAutoRecipe")]
private static void BeforeRefresh(CraftingMenu __instance)
{
s_sorting = ((UIElement)__instance).LocalCharacter;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(CraftingMenu), "RefreshAutoRecipe")]
private static IEnumerable<CodeInstruction> SortTrackedFirst(IEnumerable<CodeInstruction> instructions)
{
MethodInfo byName = AccessTools.Method(typeof(Recipe), "SortByName", new Type[2]
{
typeof(KeyValuePair<int, Recipe>),
typeof(KeyValuePair<int, Recipe>)
}, (Type[])null);
MethodInfo trackedFirst = AccessTools.Method(typeof(CraftingPatches), "TrackedFirstThenName", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (instruction.opcode == OpCodes.Ldftn && object.Equals(instruction.operand, byName))
{
instruction.operand = trackedFirst;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
Plugin.Log.LogWarning((object)($"CraftingMenu.RefreshAutoRecipe: {replaced} recipe sorts found instead of 1, " + "tracked recipes are not moved to the top"));
}
}
private static int TrackedFirstThenName(KeyValuePair<int, Recipe> a, KeyValuePair<int, Recipe> b)
{
bool flag = TrackedRecipes.IsTracked(s_sorting, a.Value);
bool flag2 = TrackedRecipes.IsTracked(s_sorting, b.Value);
if (flag == flag2)
{
return Recipe.SortByName(a, b);
}
if (!flag)
{
return 1;
}
return -1;
}
[HarmonyFinalizer]
[HarmonyPatch(typeof(CraftingMenu), "RefreshAutoRecipe")]
private static void AfterRefresh(CraftingMenu __instance)
{
s_sorting = null;
try
{
List<KeyValuePair<int, Recipe>> list = s_recipes.Invoke(__instance);
List<RecipeDisplay> list2 = s_displays.Invoke(__instance);
Character localCharacter = ((UIElement)__instance).LocalCharacter;
for (int i = 0; i < list.Count && i < list2.Count; i++)
{
RecipeTick.Attach(list2[i], s_preview.Invoke(list2[i]), __instance).Show(list[i].Value, TrackedRecipes.IsTracked(localCharacter, list[i].Value));
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("recipe ticks: " + ex));
}
}
internal static void Toggle(CraftingMenu menu, Recipe recipe)
{
Character localCharacter = ((UIElement)menu).LocalCharacter;
if ((Object)(object)localCharacter == (Object)null || (Object)(object)recipe == (Object)null)
{
return;
}
TrackedRecipes.SetTracked(localCharacter, recipe, !TrackedRecipes.IsTracked(localCharacter, recipe));
List<KeyValuePair<int, Recipe>> list = s_recipes.Invoke(menu);
List<RecipeDisplay> list2 = s_displays.Invoke(menu);
int num = s_selected.Invoke(menu);
Recipe selectedRecipe = ((num >= 0 && num < list.Count) ? list[num].Value : null);
if ((Object)(object)selectedRecipe != (Object)null)
{
list2[num].SetHighlight(false);
}
int num2 = s_lastCrafted.Invoke(menu);
if (num2 >= 0 && num2 < list2.Count && list2[num2].RealSiblingIndex != -1)
{
list2[num2].ResetRealSiblingIndex();
}
s_lastCrafted.Invoke(menu) = -1;
s_refreshAutoRecipe(menu);
if ((Object)(object)selectedRecipe != (Object)null)
{
int num3 = list.FindIndex((KeyValuePair<int, Recipe> r) => (Object)(object)r.Value == (Object)(object)selectedRecipe);
s_selected.Invoke(menu) = num3;
menu.OnRecipeSelected(num3, true);
}
IngredientBadges.RefreshAll();
}
}
internal class RecipeTick : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
private const float UntickedAlpha = 0.45f;
private Image m_image;
private CraftingMenu m_menu;
private Recipe m_recipe;
private bool m_tracked;
private bool m_hovered;
public bool Tracked => m_tracked;
public static RecipeTick Attach(RecipeDisplay display, Image preview, CraftingMenu menu)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
RecipeTick recipeTick = ((Component)display).GetComponentInChildren<RecipeTick>(true);
if ((Object)(object)recipeTick == (Object)null)
{
GameObject val = new GameObject("IngredientTrackerTick", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
RectTransform val2 = (RectTransform)val.transform;
((Transform)val2).SetParent(((Object)(object)preview != (Object)null) ? ((Component)preview).transform : ((Component)display).transform, false);
val2.anchorMin = new Vector2(-0.06f, 1.04f);
val2.anchorMax = new Vector2(0.52f, 1.04f);
val2.pivot = new Vector2(0.5f, 1f);
Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
val2.offsetMin = offsetMin;
AspectRatioFitter obj = val.AddComponent<AspectRatioFitter>();
obj.aspectMode = (AspectMode)1;
obj.aspectRatio = 1f;
recipeTick = val.AddComponent<RecipeTick>();
recipeTick.m_image = val.GetComponent<Image>();
((Graphic)recipeTick.m_image).raycastTarget = true;
recipeTick.m_image.preserveAspect = true;
}
recipeTick.m_menu = menu;
return recipeTick;
}
public void Show(Recipe recipe, bool tracked)
{
m_recipe = recipe;
m_tracked = tracked;
Refresh();
}
private void Refresh()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
m_image.sprite = (m_tracked ? Sprites.BoxTicked : Sprites.BoxEmpty);
((Graphic)m_image).color = new Color(1f, 1f, 1f, (m_tracked || m_hovered) ? 1f : 0.45f);
}
public void OnPointerDown(PointerEventData eventData)
{
}
public void OnPointerClick(PointerEventData eventData)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
if ((int)eventData.button == 0 && !((Object)(object)m_menu == (Object)null) && !((Object)(object)m_recipe == (Object)null))
{
GlobalAudioManager audioManager = Global.AudioManager;
if (audioManager != null)
{
audioManager.PlaySound((Sounds)90001, 0f, 1f, 1f, 1f, 1f);
}
CraftingPatches.Toggle(m_menu, m_recipe);
}
}
public void OnPointerEnter(PointerEventData eventData)
{
m_hovered = true;
Refresh();
}
public void OnPointerExit(PointerEventData eventData)
{
m_hovered = false;
Refresh();
}
}
[HarmonyPatch]
internal static class IngredientBadges
{
private static readonly FieldRef<ItemDisplay, Image> s_icon = AccessTools.FieldRefAccess<ItemDisplay, Image>("m_imgItemIcon");
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemDisplay), "SetReferencedItem")]
private static void AfterSetItem(ItemDisplay __instance)
{
Refresh(__instance);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemDisplay), "Clear")]
private static void AfterClear(ItemDisplay __instance)
{
Refresh(__instance);
}
public static void RefreshAll()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
ItemDisplay[] array = Resources.FindObjectsOfTypeAll<ItemDisplay>();
foreach (ItemDisplay val in array)
{
if ((Object)(object)val != (Object)null)
{
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
Refresh(val);
}
}
}
}
public static void Refresh(ItemDisplay display)
{
try
{
Image val = s_icon.Invoke(display);
if ((Object)(object)val == (Object)null)
{
return;
}
List<Recipe> list = null;
Item refItem = display.RefItem;
Character localCharacter = ((UIElement)display).LocalCharacter;
if ((Object)(object)refItem != (Object)null && (Object)(object)localCharacter != (Object)null && !(refItem is Skill) && IsLoot(display, refItem, localCharacter))
{
list = TrackedRecipes.UsingIngredient(localCharacter, refItem);
}
IngredientBadge ingredientBadge = ((Component)val).GetComponentInChildren<IngredientBadge>(true);
if (list == null || list.Count == 0)
{
if ((Object)(object)ingredientBadge != (Object)null)
{
ingredientBadge.Show(null);
}
return;
}
if ((Object)(object)ingredientBadge == (Object)null)
{
ingredientBadge = IngredientBadge.Create(((Component)val).transform);
}
ingredientBadge.Show(list);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("ingredient badge: " + ex));
}
}
internal static bool IsLoot(ItemDisplay display, Item item, Character character)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Invalid comparison between Unknown and I4
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Invalid comparison between Unknown and I4
if (item.IsChildToPlayer)
{
return false;
}
IItemListDisplay parentDisplay = display.ParentDisplay;
IItemListDisplay obj = ((parentDisplay is ContainerDisplay) ? parentDisplay : null);
ItemContainer val = ((obj != null) ? ((ContainerDisplay)obj).ReferencedContainer : null) ?? item.ParentContainer;
int num = 0;
while ((Object)(object)val != (Object)null && num < 8)
{
if (((Item)val).IsChildToPlayer || (Object)(object)val == (Object)(object)character.Inventory.Stash || (int)val.SpecialType == 4 || (int)val.SpecialType == 2)
{
return false;
}
if ((Object)(object)val.RefBag != (Object)null && IsPlayersBag(val.RefBag))
{
return false;
}
num++;
val = ((Item)val).ParentContainer;
}
if ((Object)(object)((Component)display).GetComponentInParent<CraftingMenu>() != (Object)null)
{
return false;
}
if (!Plugin.MarkInShops.Value && (Object)(object)((Component)display).GetComponentInParent<ShopMenu>() != (Object)null)
{
return false;
}
return true;
}
private static bool IsPlayersBag(Bag bag)
{
string previousOwnerUID = ((Item)bag).PreviousOwnerUID;
if (string.IsNullOrEmpty(previousOwnerUID) || (Object)(object)CharacterManager.Instance == (Object)null)
{
return false;
}
Character character = CharacterManager.Instance.GetCharacter(previousOwnerUID);
if ((Object)(object)character != (Object)null)
{
return (Object)(object)character.OwnerPlayerSys != (Object)null;
}
return false;
}
}
internal class IngredientBadge : MonoBehaviour
{
private const float CycleSeconds = 1.5f;
private Image m_recipeIcon;
private Image m_frame;
private AspectRatioFitter m_fitter;
private readonly List<Recipe> m_recipes = new List<Recipe>();
private int m_shown;
private float m_nextSwitch;
public IReadOnlyList<Recipe> Recipes => m_recipes;
public static IngredientBadge Create(Transform icon)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("IngredientTrackerBadge", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val.transform.SetParent(icon, false);
Image component = val.GetComponent<Image>();
((Graphic)component).color = new Color(0.09f, 0.07f, 0.05f, 0.9f);
((Graphic)component).raycastTarget = false;
IngredientBadge ingredientBadge = val.AddComponent<IngredientBadge>();
ingredientBadge.m_fitter = val.AddComponent<AspectRatioFitter>();
ingredientBadge.m_fitter.aspectMode = (AspectMode)1;
ingredientBadge.m_recipeIcon = Child(val.transform, "RecipeIcon");
ingredientBadge.m_recipeIcon.preserveAspect = true;
ingredientBadge.m_frame = Child(val.transform, "Frame");
ingredientBadge.m_frame.sprite = Sprites.BadgeFrame;
ingredientBadge.m_frame.type = (Type)1;
ingredientBadge.m_frame.fillCenter = false;
return ingredientBadge;
}
private static Image Child(Transform parent, string name)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
RectTransform val2 = (RectTransform)val.transform;
((Transform)val2).SetParent(parent, false);
val2.anchorMin = Vector2.zero;
val2.anchorMax = Vector2.one;
Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
val2.offsetMin = offsetMin;
Image component = val.GetComponent<Image>();
((Graphic)component).raycastTarget = false;
return component;
}
public void Show(List<Recipe> recipes)
{
m_recipes.Clear();
if (recipes != null)
{
m_recipes.AddRange(recipes);
}
bool flag = m_recipes.Count > 0;
if (((Component)this).gameObject.activeSelf != flag)
{
((Component)this).gameObject.SetActive(flag);
}
if (flag)
{
Place();
m_shown = 0;
m_nextSwitch = Time.unscaledTime + 1.5f;
ShowIcon();
}
}
private void Place()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: 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_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
float value = Plugin.BadgeSize.Value;
Corner value2 = Plugin.BadgeCorner.Value;
bool flag = value2 == Corner.TopRight || value2 == Corner.BottomRight;
float num = ((value2 == Corner.TopLeft || value2 == Corner.TopRight) ? 1f : 0f);
RectTransform val = (RectTransform)((Component)this).transform;
val.anchorMin = new Vector2(flag ? (1f - value) : 0f, num);
val.anchorMax = new Vector2(flag ? 1f : value, num);
val.pivot = new Vector2(0.5f, num);
Vector2 offsetMin = (val.offsetMax = Vector2.zero);
val.offsetMin = offsetMin;
((Transform)val).SetAsLastSibling();
m_frame.pixelsPerUnitMultiplier = FrameMultiplier(m_frame);
}
internal static float FrameMultiplier(Image frame)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
Canvas val = (((Object)(object)((Graphic)frame).canvas != (Object)null) ? ((Graphic)frame).canvas.rootCanvas : null);
if ((Object)(object)val == (Object)null || ((Component)val).transform.lossyScale.x <= 0f)
{
return 1f;
}
float num = val.scaleFactor * ((Component)frame).transform.lossyScale.x / ((Component)val).transform.lossyScale.x;
return val.referencePixelsPerUnit / frame.sprite.pixelsPerUnit * num;
}
private void ShowIcon()
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
Recipe val = m_recipes[m_shown % m_recipes.Count];
Sprite val2 = ((val.Results != null && val.Results.Length != 0 && (Object)(object)val.Results[0].RefItem != (Object)null) ? val.Results[0].RefItem.ItemIcon : null);
m_recipeIcon.sprite = val2;
AspectRatioFitter fitter = m_fitter;
float aspectRatio;
if ((Object)(object)val2 != (Object)null)
{
Rect rect = val2.rect;
if (((Rect)(ref rect)).height > 0f)
{
rect = val2.rect;
float width = ((Rect)(ref rect)).width;
rect = val2.rect;
aspectRatio = width / ((Rect)(ref rect)).height;
goto IL_00ae;
}
}
aspectRatio = 1f;
goto IL_00ae;
IL_00ae:
fitter.aspectRatio = aspectRatio;
}
private void Update()
{
float num = FrameMultiplier(m_frame);
if (num != m_frame.pixelsPerUnitMultiplier)
{
m_frame.pixelsPerUnitMultiplier = num;
}
if (m_recipes.Count >= 2 && !(Time.unscaledTime < m_nextSwitch))
{
m_shown++;
m_nextSwitch = Time.unscaledTime + 1.5f;
ShowIcon();
}
}
}
[BepInPlugin("tchernobill.ingredienttracker", "IngredientTracker", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "tchernobill.ingredienttracker";
public const string NAME = "IngredientTracker";
public const string VERSION = "1.0.0";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> MarkInShops;
internal static ConfigEntry<Corner> BadgeCorner;
internal static ConfigEntry<float> BadgeSize;
private void Awake()
{
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
MarkInShops = ((BaseUnityPlugin)this).Config.Bind<bool>("Ingredients", "Mark In Shops", true, "Also mark the ingredients of tracked recipes in a merchant's wares.");
BadgeCorner = ((BaseUnityPlugin)this).Config.Bind<Corner>("Ingredients", "Badge Corner", Corner.TopLeft, "Corner of the ingredient's icon where the recipe's icon is shown (top right is where stack counts are).");
BadgeSize = ((BaseUnityPlugin)this).Config.Bind<float>("Ingredients", "Badge Size", 0.33f, new ConfigDescription("Size of the recipe's icon, relative to the ingredient's icon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 0.7f), Array.Empty<object>()));
BadgeCorner.SettingChanged += delegate
{
IngredientBadges.RefreshAll();
};
BadgeSize.SettingChanged += delegate
{
IngredientBadges.RefreshAll();
};
MarkInShops.SettingChanged += delegate
{
IngredientBadges.RefreshAll();
};
Harmony val = new Harmony("tchernobill.ingredienttracker");
val.PatchAll(typeof(CraftingPatches));
val.PatchAll(typeof(IngredientBadges));
TestHarness.StartIfRequested(((Component)this).gameObject);
Showcase.StartIfRequested(((Component)this).gameObject);
}
}
public enum Corner
{
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
public class Showcase : MonoBehaviour
{
private const int Fps = 30;
private static readonly FieldRef<CraftingMenu, List<KeyValuePair<int, Recipe>>> s_recipes = AccessTools.FieldRefAccess<CraftingMenu, List<KeyValuePair<int, Recipe>>>("m_complexeRecipes");
private static readonly FieldRef<CraftingMenu, List<RecipeDisplay>> s_displays = AccessTools.FieldRefAccess<CraftingMenu, List<RecipeDisplay>>("m_recipeDisplays");
private static readonly FieldRef<CraftingMenu, InventorySectionButton[]> s_tabs = AccessTools.FieldRefAccess<CraftingMenu, InventorySectionButton[]>("m_craftingTabs");
private static readonly FieldRef<CraftingMenu, CraftingType[]> s_tabTypes = AccessTools.FieldRefAccess<CraftingMenu, CraftingType[]>("CraftingTabOrder");
private string m_frames;
private int m_frame;
private bool m_recording;
private RectTransform m_cursor;
private Vector2 m_cursorPos;
private readonly List<GameObject> m_hovered = new List<GameObject>();
public static void StartIfRequested(GameObject host)
{
if (UnityEngineExtensions.Contains<string>(Environment.GetCommandLineArgs(), "--it-showcase"))
{
host.AddComponent<Showcase>();
}
}
private static string Arg(string name)
{
string[] commandLineArgs = Environment.GetCommandLineArgs();
int num = Array.IndexOf(commandLineArgs, name);
if (num < 0 || num + 1 >= commandLineArgs.Length)
{
return null;
}
return commandLineArgs[num + 1];
}
private static void Log(string message)
{
Plugin.Log.LogMessage((object)("it-showcase: " + message));
}
private static Exception Fail(string reason)
{
return new InvalidOperationException(reason);
}
private void Start()
{
((MonoBehaviour)this).StartCoroutine(Run());
}
private IEnumerator Run()
{
Character character = null;
float deadline = Time.realtimeSinceStartup + 900f;
while ((Object)(object)character == (Object)null)
{
if (Time.realtimeSinceStartup > deadline)
{
Plugin.Log.LogError((object)"it-showcase: FAILED no local character after 900 s");
yield break;
}
yield return null;
if (!((Object)(object)NetworkLevelLoader.Instance == (Object)null) && NetworkLevelLoader.Instance.IsOverallLoadingDone)
{
try
{
CharacterManager instance = CharacterManager.Instance;
character = ((instance != null) ? instance.GetFirstLocalCharacter() : null);
}
catch (NullReferenceException)
{
}
}
}
yield return Wait(2f);
MenuManager.Instance.MasterCanvas.alpha = 1f;
MenuManager.Instance.MasterCanvas.interactable = true;
m_frames = Arg("--it-showcase-frames") ?? Path.Combine(Paths.BepInExRootPath, "IngredientTrackerShowcase");
Directory.CreateDirectory(m_frames);
string[] files = Directory.GetFiles(m_frames, "*.jpg");
for (int i = 0; i < files.Length; i++)
{
File.Delete(files[i]);
}
string name = character.Name;
object arg = character.UID;
Scene activeScene = SceneManager.GetActiveScene();
Log($"local character {name} ({arg}) in {((Scene)(ref activeScene)).name}");
string problem = null;
Stack<IEnumerator> steps = new Stack<IEnumerator>();
steps.Push(Steps(character));
while (steps.Count > 0)
{
object current;
try
{
if (!steps.Peek().MoveNext())
{
steps.Pop();
continue;
}
current = steps.Peek().Current;
}
catch (Exception ex2)
{
problem = ((ex2 is InvalidOperationException) ? ex2.Message : ("exception " + ex2));
break;
}
if (current is IEnumerator item)
{
steps.Push(item);
}
else
{
yield return current;
}
}
StopRecording();
if (problem != null)
{
Plugin.Log.LogError((object)("it-showcase: FAILED " + problem));
}
else
{
Log($"done, {m_frame} frames in {m_frames}");
}
}
private IEnumerator Wait(float seconds)
{
if (m_recording)
{
for (int i = Mathf.RoundToInt(seconds * 30f); i > 0; i--)
{
yield return null;
}
}
else
{
float end = Time.realtimeSinceStartup + seconds;
while (Time.realtimeSinceStartup < end)
{
yield return null;
}
}
}
private IEnumerator WaitUntil(Func<bool> condition, float seconds, string what)
{
int frames = Mathf.RoundToInt(seconds * 30f);
float end = Time.realtimeSinceStartup + seconds;
while (!condition())
{
bool num;
if (!m_recording)
{
num = Time.realtimeSinceStartup > end;
}
else
{
int num2 = frames - 1;
frames = num2;
num = num2 < 0;
}
if (num)
{
throw Fail("timed out waiting for " + what);
}
yield return null;
}
}
private void StartRecording()
{
Time.captureFramerate = 30;
m_recording = true;
((MonoBehaviour)this).StartCoroutine(RecordFrames());
Log("recording");
}
private void StopRecording()
{
m_recording = false;
Time.captureFramerate = 0;
}
private IEnumerator RecordFrames()
{
WaitForEndOfFrame endOfFrame = new WaitForEndOfFrame();
while (m_recording)
{
yield return endOfFrame;
if (m_recording)
{
Texture2D val = ScreenCapture.CaptureScreenshotAsTexture();
if (m_frame == 0)
{
Log($"frame size {((Texture)val).width}x{((Texture)val).height}");
}
File.WriteAllBytes(Path.Combine(m_frames, $"f{m_frame++:D5}.jpg"), ImageConversion.EncodeToJPG(val, 95));
Object.Destroy((Object)(object)val);
continue;
}
break;
}
}
private void MakeCursor()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: 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)
GameObject val = new GameObject("ITShowcaseCursor", new Type[2]
{
typeof(RectTransform),
typeof(Canvas)
});
Object.DontDestroyOnLoad((Object)(object)val);
Canvas component = val.GetComponent<Canvas>();
component.renderMode = (RenderMode)0;
component.sortingOrder = 32767;
GameObject val2 = new GameObject("Arrow", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val2.transform.SetParent(val.transform, false);
Image component2 = val2.GetComponent<Image>();
component2.sprite = ArrowSprite();
((Graphic)component2).raycastTarget = false;
m_cursor = (RectTransform)val2.transform;
RectTransform cursor = m_cursor;
Vector2 anchorMin = (m_cursor.anchorMax = Vector2.zero);
cursor.anchorMin = anchorMin;
m_cursor.sizeDelta = new Vector2(32f, 32f);
m_cursor.pivot = new Vector2(0.0625f, 0.9375f);
SetCursor(new Vector2((float)Screen.width * 0.62f, (float)Screen.height * 0.42f));
}
private static Sprite ArrowSprite()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: 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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
Vector2[] poly = (Vector2[])(object)new Vector2[7]
{
new Vector2(2f, 2f),
new Vector2(2f, 25f),
new Vector2(7.5f, 19.8f),
new Vector2(11.4f, 28.4f),
new Vector2(15f, 26.8f),
new Vector2(11.2f, 18.4f),
new Vector2(18.6f, 18.4f)
};
return Sprites.Make(32, delegate(float x, float y)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: 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_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: 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_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: 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_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor(x, 32f - y);
float num = float.MaxValue;
bool flag = false;
int num2 = 0;
int num3 = poly.Length - 1;
while (num2 < poly.Length)
{
Vector2 val2 = poly[num3];
Vector2 val3 = poly[num2];
Vector2 val4 = val3 - val2;
float num4 = Mathf.Clamp01(Vector2.Dot(val - val2, val4) / ((Vector2)(ref val4)).sqrMagnitude);
float num5 = num;
Vector2 val5 = val - (val2 + val4 * num4);
num = Mathf.Min(num5, ((Vector2)(ref val5)).magnitude);
if (val2.y > val.y != val3.y > val.y && val.x < val2.x + (val.y - val2.y) / (val3.y - val2.y) * (val3.x - val2.x))
{
flag = !flag;
}
num3 = num2++;
}
float num6 = (flag ? (0f - num) : num);
float a = Mathf.Clamp01(1.6f - num6);
float num7 = Mathf.Clamp01(0f - num6 - 0.6f);
Color result = Color.Lerp(Color.black, Color.white, num7);
result.a = a;
return result;
}, default(Vector4), (FilterMode)1);
}
private void SetCursor(Vector2 screen)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
m_cursorPos = screen;
m_cursor.anchoredPosition = screen;
UpdateHover();
}
private static Vector2 ScreenCenter(RectTransform rect)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
Camera obj = (((Object)(object)val != (Object)null && (int)val.renderMode != 0) ? val.worldCamera : null);
Rect rect2 = rect.rect;
return RectTransformUtility.WorldToScreenPoint(obj, ((Transform)rect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect2)).center)));
}
private IEnumerator MoveTo(Vector2 target, float seconds = 0.45f)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
Vector2 from = m_cursorPos;
int frames = Mathf.Max(1, Mathf.RoundToInt(seconds * 30f));
for (int i = 1; i <= frames; i++)
{
float num = (float)i / (float)frames;
SetCursor(Vector2.Lerp(from, target, num * num * (3f - 2f * num)));
yield return null;
}
}
private IEnumerator MoveTo(Component target, float seconds = 0.45f)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
return MoveTo(ScreenCenter((RectTransform)target.transform), seconds);
}
private GameObject Raycast(out RaycastResult hit)
{
//IL_0001: 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)
//IL_001e: 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_002b: Expected O, but got Unknown
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
hit = default(RaycastResult);
EventSystem current = EventSystem.current;
if ((Object)(object)current == (Object)null)
{
return null;
}
PointerEventData val = new PointerEventData(current)
{
position = m_cursorPos
};
List<RaycastResult> list = new List<RaycastResult>();
current.RaycastAll(val, list);
if (list.Count == 0)
{
return null;
}
hit = list[0];
return ((RaycastResult)(ref hit)).gameObject;
}
private void UpdateHover()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
RaycastResult hit;
GameObject val = Raycast(out hit);
List<GameObject> now = new List<GameObject>();
Transform val2 = (((Object)(object)val != (Object)null) ? val.transform : null);
while ((Object)(object)val2 != (Object)null)
{
now.Add(((Component)val2).gameObject);
val2 = val2.parent;
}
PointerEventData val3 = new PointerEventData(EventSystem.current)
{
position = m_cursorPos
};
foreach (GameObject item in m_hovered.Where((GameObject g) => (Object)(object)g != (Object)null && !now.Contains(g)).ToList())
{
ExecuteEvents.Execute<IPointerExitHandler>(item, (BaseEventData)(object)val3, ExecuteEvents.pointerExitHandler);
}
foreach (GameObject item2 in now.Where((GameObject g) => !m_hovered.Contains(g)))
{
ExecuteEvents.Execute<IPointerEnterHandler>(item2, (BaseEventData)(object)val3, ExecuteEvents.pointerEnterHandler);
}
m_hovered.Clear();
m_hovered.AddRange(now);
}
private IEnumerator Click()
{
RaycastResult hit2;
GameObject hit = Raycast(out hit2);
if ((Object)(object)hit == (Object)null)
{
throw Fail($"nothing under the cursor at {m_cursorPos}");
}
PointerEventData data = new PointerEventData(EventSystem.current)
{
position = m_cursorPos,
button = (InputButton)0,
pointerCurrentRaycast = hit2,
pointerPressRaycast = hit2,
eligibleForClick = true,
clickCount = 1,
clickTime = Time.unscaledTime
};
GameObject press = (data.pointerPress = ExecuteEvents.ExecuteHierarchy<IPointerDownHandler>(hit, (BaseEventData)(object)data, ExecuteEvents.pointerDownHandler) ?? ExecuteEvents.GetEventHandler<IPointerClickHandler>(hit));
data.rawPointerPress = hit;
Log("click on " + HierarchyPath(hit.transform) + " -> " + (((Object)(object)press != (Object)null) ? ((Object)press).name : "nothing"));
((Transform)m_cursor).localScale = Vector3.one * 0.85f;
yield return Wait(0.1f);
((Transform)m_cursor).localScale = Vector3.one;
if ((Object)(object)press != (Object)null)
{
ExecuteEvents.Execute<IPointerUpHandler>(press, (BaseEventData)(object)data, ExecuteEvents.pointerUpHandler);
if ((Object)(object)press == (Object)(object)ExecuteEvents.GetEventHandler<IPointerClickHandler>(hit))
{
ExecuteEvents.Execute<IPointerClickHandler>(press, (BaseEventData)(object)data, ExecuteEvents.pointerClickHandler);
}
}
}
private static string HierarchyPath(Transform t)
{
List<string> list = new List<string>();
int num = 0;
while ((Object)(object)t != (Object)null && num < 5)
{
list.Insert(0, ((Object)t).name);
t = t.parent;
num++;
}
return string.Join("/", list);
}
private static Merchant FindOuntz()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
Merchant val = null;
Merchant[] array = Object.FindObjectsOfType<Merchant>();
foreach (Merchant val2 in array)
{
Log($"merchant '{val2.ShopName}' at {((Component)val2).transform.position}");
if (val2.ShopName != null && val2.ShopName.Contains("Ountz"))
{
val = val2;
}
}
return val ?? throw Fail("Ountz the Melon Farmer not found");
}
private static InteractionActivator Activator(Merchant merchant)
{
DialogueActor componentInParent = ((Component)merchant).GetComponentInParent<DialogueActor>();
InteractionActivator[] componentsInChildren = ((Component)(((componentInParent != null) ? ((Component)componentInParent).transform : null) ?? ((Component)merchant).transform.root)).GetComponentsInChildren<InteractionActivator>(true);
InteractionActivator[] array = componentsInChildren;
foreach (InteractionActivator val in array)
{
Log($"activator {HierarchyPath(((Component)val).transform)} basic={((EventActivator)val).HasBasicInteraction} text='{((EventActivator)val).BasicText}'");
}
return ((IEnumerable<InteractionActivator>)componentsInChildren).FirstOrDefault((Func<InteractionActivator, bool>)((InteractionActivator a) => ((EventActivator)a).HasBasicInteraction && ((EventActivator)a).CanBeActivated)) ?? ((IEnumerable<InteractionActivator>)componentsInChildren).FirstOrDefault((Func<InteractionActivator, bool>)((InteractionActivator a) => ((EventActivator)a).HasBasicInteraction)) ?? throw Fail("no interaction on Ountz");
}
private static void PlaceInFront(Character character, Merchant merchant)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: 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)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
DialogueActor componentInParent = ((Component)merchant).GetComponentInParent<DialogueActor>();
Transform val = ((componentInParent != null) ? ((Component)componentInParent).transform : null) ?? ((Component)merchant).transform;
Vector3 val2 = val.position + val.forward * 1.8f;
NavMeshHit val4 = default(NavMeshHit);
Vector3 val3 = (NavMesh.SamplePosition(val2, ref val4, 3f, -1) ? ((NavMeshHit)(ref val4)).position : val2);
Vector3 val5 = val.position - val3;
val5.y = 0f;
Log($"Ountz at {val.position} facing {val.forward}; player placed at {val3} (wanted {val2})");
character.Teleport(val3, Quaternion.LookRotation(val5));
}
private static void FrameScene(Character character)
{
//IL_001c: 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)
CharacterCamera characterCamera = character.CharacterCamera;
characterCamera.ResetCameraToPlayer();
((Component)characterCamera).transform.rotation = Quaternion.Euler(0f, ((Component)character).transform.eulerAngles.y + 32f, 0f);
}
private static void Daylight()
{
TOD_Sky.Instance.Cycle.Hour = 10.5f;
FieldInfo fieldInfo = AccessTools.Field(typeof(NotificationDisplay), "m_bufferedNotifications");
NotificationDisplay[] array = Resources.FindObjectsOfTypeAll<NotificationDisplay>();
foreach (NotificationDisplay val in array)
{
if (fieldInfo.GetValue(val) is IList { Count: >0 } list)
{
Log($"dropped {list.Count} buffered notifications of {((Object)val).name}");
list.Clear();
}
}
}
private void Focus(Rect? screen, string what)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (screen.HasValue)
{
Rect valueOrDefault = screen.GetValueOrDefault();
Log($"focus {m_frame} {((Rect)(ref valueOrDefault)).xMin:0} {(float)Screen.height - ((Rect)(ref valueOrDefault)).yMax:0} {((Rect)(ref valueOrDefault)).xMax:0} {(float)Screen.height - ((Rect)(ref valueOrDefault)).yMin:0} {what}");
}
else
{
Log($"focus {m_frame} full {what}");
}
}
private static Rect ScreenRect(RectTransform rect)
{
//IL_001d: 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_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_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
Camera obj = (((Object)(object)val != (Object)null && (int)val.renderMode != 0) ? val.worldCamera : null);
Vector3[] array = (Vector3[])(object)new Vector3[4];
rect.GetWorldCorners(array);
Vector2 val2 = RectTransformUtility.WorldToScreenPoint(obj, array[0]);
Vector2 val3 = RectTransformUtility.WorldToScreenPoint(obj, array[2]);
return Rect.MinMaxRect(Mathf.Min(val2.x, val3.x), Mathf.Min(val2.y, val3.y), Mathf.Max(val2.x, val3.x), Mathf.Max(val2.y, val3.y));
}
private static Rect Union(IEnumerable<Rect> rects)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
Rect result = rects.First();
foreach (Rect rect in rects)
{
Rect current = rect;
result = Rect.MinMaxRect(Mathf.Min(((Rect)(ref result)).xMin, ((Rect)(ref current)).xMin), Mathf.Min(((Rect)(ref result)).yMin, ((Rect)(ref current)).yMin), Mathf.Max(((Rect)(ref result)).xMax, ((Rect)(ref current)).xMax), Mathf.Max(((Rect)(ref result)).yMax, ((Rect)(ref current)).yMax));
}
return result;
}
private static Rect PanelRect(Component menu)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
return Union((from r in (from g in menu.GetComponentsInChildren<Graphic>(false)
where ((Behaviour)g).enabled && g.color.a > 0.05f
select g).Select(Clipped)
where ((Rect)(ref r)).width > 2f && ((Rect)(ref r)).height > 2f && ((Rect)(ref r)).width < (float)Screen.width * 0.9f && ((Rect)(ref r)).height < (float)Screen.height * 0.9f
select r).DefaultIfEmpty(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height)));
}
private static Rect Clipped(Graphic g)
{
//IL_0006: 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)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
Rect val = Intersect(ScreenRect(g.rectTransform), new Rect(0f, 0f, (float)Screen.width, (float)Screen.height));
Transform parent = ((Component)g).transform.parent;
while ((Object)(object)parent != (Object)null)
{
if ((Object)(object)((Component)parent).GetComponent<RectMask2D>() != (Object)null || (Object)(object)((Component)parent).GetComponent<Mask>() != (Object)null)
{
val = Intersect(val, ScreenRect((RectTransform)parent));
}
parent = parent.parent;
}
return val;
}
private static Rect Intersect(Rect a, Rect b)
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
return Rect.MinMaxRect(Mathf.Max(((Rect)(ref a)).xMin, ((Rect)(ref b)).xMin), Mathf.Max(((Rect)(ref a)).yMin, ((Rect)(ref b)).yMin), Mathf.Max(Mathf.Max(((Rect)(ref a)).xMin, ((Rect)(ref b)).xMin), Mathf.Min(((Rect)(ref a)).xMax, ((Rect)(ref b)).xMax)), Mathf.Max(Mathf.Max(((Rect)(ref a)).yMin, ((Rect)(ref b)).yMin), Mathf.Min(((Rect)(ref a)).yMax, ((Rect)(ref b)).yMax)));
}
private static Rect Grow(Rect r, float margin)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
return Rect.MinMaxRect(((Rect)(ref r)).xMin - margin, ((Rect)(ref r)).yMin - margin, ((Rect)(ref r)).xMax + margin, ((Rect)(ref r)).yMax + margin);
}
private static void LearnAllRecipes(Character character)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
Dictionary<string, Recipe> obj = AccessTools.FieldRefAccess<RecipeManager, Dictionary<string, Recipe>>("m_recipes").Invoke(RecipeManager.Instance);
IList<string> learnedItemUIDs = ((CharacterKnowledge)character.Inventory.RecipeKnowledge).GetLearnedItemUIDs();
int count = learnedItemUIDs.Count;
foreach (Recipe value in obj.Values)
{
if (!learnedItemUIDs.Contains(UID.op_Implicit(value.UID)))
{
learnedItemUIDs.Add(UID.op_Implicit(value.UID));
}
}
Log($"recipes known: {count} -> {learnedItemUIDs.Count}");
}
private static List<ItemDisplay> Wares(ShopMenu shop)
{
return (from d in ((Component)shop).GetComponentsInChildren<ItemDisplay>(false)
where (Object)(object)d.RefItem != (Object)null && d.RefItem.ParentContainer is MerchantPouch
select d).ToList();
}
private static Recipe[] PickRecipes(List<ItemDisplay> wares)
{
Dictionary<string, Recipe>.ValueCollection values = AccessTools.FieldRefAccess<RecipeManager, Dictionary<string, Recipe>>("m_recipes").Invoke(RecipeManager.Instance).Values;
string[] wanted = (Arg("--it-showcase-recipes") ?? "").Split(new char[1] { ';' });
Recipe[] array = (Recipe[])(object)new Recipe[2];
CraftingType[] types = (CraftingType[])(object)new CraftingType[2]
{
(CraftingType)1,
default(CraftingType)
};
int k;
for (k = 0; k < 2; k++)
{
List<(Recipe, List<ItemDisplay>)> list = (from r in values
where (int)r.CraftingStationType == (int)types[k] && r.Results.Length != 0 && r.Ingredients.Length > 1
select (recipe: r, used: wares.Where((ItemDisplay w) => r.Ingredients.Any((RecipeIngredient i) => i.Match(w.RefItem))).ToList()) into c
where c.used.Count > 0 && c.used.All(Visible)
orderby c.recipe.Name
select c).ToList();
foreach (var item in list)
{
Log(string.Format("{0} candidate: {1} <- {2}{3}", types[k], item.Item1.Name, string.Join(", ", item.Item2.Select((ItemDisplay w) => w.RefItem.Name)), Specific(item) ? " (specific)" : ""));
}
array[k] = ((k < wanted.Length) ? list.FirstOrDefault<(Recipe, List<ItemDisplay>)>(((Recipe recipe, List<ItemDisplay> used) c) => c.recipe.Name == wanted[k]).Item1 : null) ?? list.FirstOrDefault(Specific).Item1 ?? UnityEngineExtensions.FirstOrDefault<(Recipe, List<ItemDisplay>)>((IList<(Recipe, List<ItemDisplay>)>)list).Item1 ?? throw Fail($"no {types[k]} recipe uses Ountz's wares");
Log($"{types[k]} recipe: {array[k].Name}");
}
return array;
static bool Specific((Recipe recipe, List<ItemDisplay> used) c)
{
return c.recipe.Ingredients.Any((RecipeIngredient i) => (Object)(object)i.AddedIngredient != (Object)null && c.used.Any((ItemDisplay w) => w.RefItem.ItemID == i.AddedIngredient.ItemID));
}
}
private static bool Visible(ItemDisplay d)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: 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)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Rect val = ScreenRect((RectTransform)((Component)d).transform);
ScrollRect componentInParent = ((Component)d).GetComponentInParent<ScrollRect>();
Rect val2 = (((Object)(object)componentInParent != (Object)null) ? ScreenRect((RectTransform)(((Object)(object)componentInParent.viewport != (Object)null) ? ((object)componentInParent.viewport) : ((object)(RectTransform)((Component)componentInParent).transform))) : val);
return ((Rect)(ref val2)).Contains(new Vector2(((Rect)(ref val)).center.x, ((Rect)(ref val)).yMax - 4f));
}
private static Button CloseButton(Component menu)
{
Button[] componentsInChildren = menu.GetComponentsInChildren<Button>(false);
Button? obj = ((IEnumerable<Button>)componentsInChildren).FirstOrDefault((Func<Button, bool>)((Button b) => ((Object)b).name.IndexOf("close", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<Button>)componentsInChildren).FirstOrDefault((Func<Button, bool>)((Button b) => ((Object)b).name.IndexOf("exit", StringComparison.OrdinalIgnoreCase) >= 0));
if ((Object)(object)obj == (Object)null)
{
Log("no close button in " + ((Object)menu).name + ": " + string.Join(", ", componentsInChildren.Select((Button b) => HierarchyPath(((Component)b).transform))));
}
return obj;
}
private IEnumerator CloseMenu(Component menu, Action fallback)
{
Button val = CloseButton(menu);
if ((Object)(object)val != (Object)null)
{
yield return MoveTo((Component)(object)val);
yield return Wait(0.15f);
yield return Click();
}
else
{
fallback();
}
}
private static List<DialogueAnswer> Answers(Character character)
{
return (from a in ((Component)character.CharacterUI).GetComponentsInChildren<DialogueAnswer>(false)
where ((Component)a).gameObject.activeInHierarchy
select a).ToList();
}
private static string Text(DialogueAnswer answer)
{
return (from t in ((Component)answer).GetComponentsInChildren<Text>()
select t.text ?? "" into t
orderby t.Length descending
select t).FirstOrDefault() ?? "";
}
private IEnumerator OpenShop(Character character, InteractionActivator activator, ShopMenu shop)
{
((EventActivator)activator).ActivateBasicInteraction(character);
yield return WaitUntil(() => Answers(character).Count > 0 || ((UIElement)shop).IsDisplayed, 10f, "Ountz's answers");
if (!((UIElement)shop).IsDisplayed)
{
yield return Wait(0.6f);
List<DialogueAnswer> list = Answers(character);
Log("answers: " + string.Join(" | ", list.Select(Text)));
DialogueAnswer target = ((IEnumerable<DialogueAnswer>)list).FirstOrDefault((Func<DialogueAnswer, bool>)((DialogueAnswer a) => Regex.IsMatch(Text(a), "trade|wares|buy|sell|shop|goods|selling", RegexOptions.IgnoreCase))) ?? list[0];
yield return MoveTo((Component)(object)target);
yield return Wait(0.25f);
yield return Click();
yield return WaitUntil(() => ((UIElement)shop).IsDisplayed, 10f, "Ountz's shop");
}
yield return Wait(0.3f);
}
private IEnumerator LeaveShop(Character character, ShopMenu shop)
{
yield return CloseMenu((Component)(object)shop, (Action)((Panel)shop).OnCancelInput);
yield return WaitUntil(() => !((UIElement)shop).IsDisplayed, 5f, "the shop to close");
yield return Wait(0.5f);
List<DialogueAnswer> list = Answers(character);
if (list.Count > 0)
{
Log("answers after the shop: " + string.Join(" | ", list.Select(Text)));
yield return MoveTo((Component)(object)list.Last());
yield return Wait(0.2f);
yield return Click();
yield return Wait(0.5f);
}
}
private static List<ItemDisplay> Used(ShopMenu shop, Recipe[] recipes)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
List<ItemDisplay> list = (from d in Wares(shop)
where recipes.Any((Recipe r) => r.Ingredients.Any((RecipeIngredient i) => i.Match(d.RefItem)))
select d).ToList();
foreach (ItemDisplay item in list)
{
Log(string.Format("ware {0} at {1}, {2}", item.RefItem.Name, ScreenRect((RectTransform)((Component)item).transform), Visible(item) ? "visible" : "OUT OF VIEW"));
}
return list.Where(Visible).ToList();
}
private IEnumerator Browse(List<ItemDisplay> items, float hold)
{
foreach (ItemDisplay item in items)
{
yield return MoveTo((Component)(object)item, 0.4f);
yield return Wait(hold);
}
}
private static ScrollRect Scroll(RecipeDisplay display)
{
return ((Component)display).GetComponentInParent<ScrollRect>();
}
private IEnumerator ScrollTo(RecipeDisplay display, float seconds = 0.6f)
{
ScrollRect val = Scroll(display);
if (!((Object)(object)val == (Object)null))
{
RectTransform content = val.content;
RectTransform val2 = (RectTransform)(((Object)(object)val.viewport != (Object)null) ? ((object)val.viewport) : ((object)(RectTransform)((Component)val).transform));
RectTransform val3 = (RectTransform)((Component)display).transform;
Rect rect = val3.rect;
float y = ((Transform)content).InverseTransformPoint(((Transform)val3).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMax))).y;
rect = content.rect;
float height = ((Rect)(ref rect)).height;
rect = val2.rect;
float num = Mathf.Max(0f, height - ((Rect)(ref rect)).height);
float target = Mathf.Clamp(0f - y - 40f, 0f, num);
float from = content.anchoredPosition.y;
Log($"scroll {((Object)display).name}: {from:0} -> {target:0} (max {num:0})");
Showcase showcase = this;
Vector2 val4 = ScreenCenter(val2);
rect = val2.rect;
yield return showcase.MoveTo(val4 + new Vector2(0f, ((Rect)(ref rect)).height * 0.15f), 0.3f);
int frames = Mathf.Max(1, Mathf.RoundToInt(seconds * 30f));
for (int i = 1; i <= frames; i++)
{
float num2 = (float)i / (float)frames;
content.anchoredPosition = new Vector2(content.anchoredPosition.x, Mathf.Lerp(from, target, num2 * num2 * (3f - 2f * num2)));
UpdateHover();
yield return null;
}
}
}
private static RecipeDisplay DisplayOf(CraftingMenu menu, Recipe recipe)
{
int num = s_recipes.Invoke(menu).FindIndex((KeyValuePair<int, Recipe> r) => (Object)(object)r.Value == (Object)(object)recipe);
if (num < 0)
{
throw Fail(recipe.Name + " is not in the crafting list");
}
return s_displays.Invoke(menu)[num];
}
private IEnumerator Track(CraftingMenu menu, Character character, Recipe recipe)
{
InventorySectionButton[] array = s_tabs.Invoke(menu);
int num = Array.IndexOf(s_tabTypes.Invoke(menu), recipe.CraftingStationType);
yield return MoveTo((Component)(object)array[num]);
yield return Wait(0.2f);
yield return Click();
yield return Wait(0.5f);
RecipeDisplay display = DisplayOf(menu, recipe);
yield return ScrollTo(display);
yield return Wait(0.3f);
RecipeTick target = ((Component)display).GetComponentInChildren<RecipeTick>(true) ?? throw Fail("no box on " + recipe.Name);
yield return MoveTo((Component)(object)target);
yield return Wait(0.35f);
yield return Click();
if (!TrackedRecipes.IsTracked(character, recipe))
{
throw Fail(recipe.Name + " not tracked after the click");
}
yield return Wait(0.6f);
yield return ScrollTo(DisplayOf(menu, recipe), 0.5f);
yield return Wait(0.8f);
}
private IEnumerator Steps(Character character)
{
CharacterUI ui = character.CharacterUI;
ShopMenu shop = UnityEngineExtensions.FirstOrDefault<ShopMenu>((IList<ShopMenu>)((Component)ui).GetComponentsInChildren<ShopMenu>(true)) ?? throw Fail("no shop menu");
CraftingMenu crafting = UnityEngineExtensions.FirstOrDefault<CraftingMenu>((IList<CraftingMenu>)((Component)ui).GetComponentsInChildren<CraftingMenu>(true)) ?? throw Fail("no crafting menu");
LearnAllRecipes(character);
foreach (Recipe item in AccessTools.FieldRefAccess<RecipeManager, Dictionary<string, Recipe>>("m_recipes").Invoke(RecipeManager.Instance).Values.Where((Recipe r) => TrackedRecipes.IsTracked(character, r)).ToList())
{
TrackedRecipes.SetTracked(character, item, tracked: false);
}
Merchant ountz = FindOuntz();
InteractionActivator activator = Activator(ountz);
PlaceInFront(character, ountz);
yield return Wait(0.5f);
FrameScene(character);
MakeCursor();
yield return Wait(4f);
yield return OpenShop(character, activator, shop);
yield return Wait(1f);
List<ItemDisplay> list = Wares(shop);
Log("wares: " + string.Join(", ", list.Select((ItemDisplay w) => w.RefItem.Name + (Visible(w) ? "" : " (out of view)"))));
Recipe[] recipes = PickRecipes(list);
yield return LeaveShop(character, shop);
yield return Wait(1f);
Daylight();
PlaceInFront(character, ountz);
yield return Wait(0.5f);
FrameScene(character);
yield return Wait(6f);
StartRecording();
Focus(null, "start");
yield return Wait(1.2f);
yield return OpenShop(character, activator, shop);
Focus(Grow(PanelRect((Component)(object)shop), 12f), "shop");
List<ItemDisplay> used = Used(shop, recipes);
yield return Wait(0.6f);
yield return Browse(used, 0.9f);
Focus(null, "leave shop");
yield return LeaveShop(character, shop);
ui.ShowMenu((MenuScreens)14);
yield return Wait(0.3f);
Focus(Grow(PanelRect((Component)(object)crafting), 12f), "crafting");
yield return Wait(0.5f);
Recipe[] array = recipes;
foreach (Recipe recipe in array)
{
yield return Track(crafting, character, recipe);
}
Focus(null, "leave crafting");
yield return CloseMenu((Component)(object)crafting, delegate
{
ui.HideMenu((MenuScreens)14, true);
});
yield return WaitUntil(() => !((UIElement)crafting).IsDisplayed, 5f, "the crafting menu to close");
yield return Wait(0.6f);
yield return OpenShop(character, activator, shop);
Focus(Grow(PanelRect((Component)(object)shop), 12f), "shop again");
used = Used(shop, recipes);
int num2 = used.Count(delegate(ItemDisplay d)
{
IngredientBadge componentInChildren = ((Component)d).GetComponentInChildren<IngredientBadge>(false);
return componentInChildren != null && componentInChildren.Recipes.Count > 0;
});
Log($"badged wares: {num2}/{used.Count}");
if (num2 == 0)
{
throw Fail("no badge on Ountz's wares");
}
yield return Wait(0.8f);
Focus(Grow(Union(from d in Wares(shop).Where(Visible)
select Clipped(((Component)d).GetComponent<Graphic>() ?? ((Component)d).GetComponentInChildren<Graphic>())), 60f), "merchant's stock");
yield return Wait(0.8f);
yield return Browse(used, 1.6f);
yield return Wait(1.2f);
StopRecording();
}
}
internal static class Sprites
{
internal static readonly Color Gold = new Color(0.93f, 0.76f, 0.36f);
private static readonly Color Ink = new Color(0.09f, 0.07f, 0.05f);
private static Sprite s_boxEmpty;
private static Sprite s_boxTicked;
private static Sprite s_badge;
public static Sprite BoxEmpty => s_boxEmpty ?? (s_boxEmpty = Make(32, delegate(float x, float y)
{
//IL_003e: 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_0053: Unknown result type (might be due to invalid IL or missing references)
float d = RoundedBox(x, y, 32, 3.5f, 5f);
return Over(new Color(Ink.r, Ink.g, Ink.b, 0.45f * Fill(d)), Color.white, Ring(d, 2.2f));
}, default(Vector4), (FilterMode)1));
public static Sprite BoxTicked => s_boxTicked ?? (s_boxTicked = Make(32, delegate(float x, float y)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
float d = RoundedBox(x, y, 32, 3.5f, 5f);
Color val = default(Color);
((Color)(ref val))..ctor(Gold.r, Gold.g, Gold.b, Fill(d));
val = Over(val, Ink, Ring(d, 1.6f) * val.a);
float num = Mathf.Min(Segment(x, y, 9f, 16.5f, 14f, 11.5f), Segment(x, y, 14f, 11.5f, 23.5f, 21f));
return Over(val, Ink, Mathf.Clamp01(2.4f - num) * val.a);
}, default(Vector4), (FilterMode)1));
public static Sprite BadgeFrame => s_badge ?? (s_badge = Make(8, (float x, float y) => (Color)((!(Mathf.Min(Mathf.Min(x, 8f - x), Mathf.Min(y, 8f - y)) < 1f)) ? new Color(0f, 0f, 0f, 0f) : Gold), new Vector4(1f, 1f, 1f, 1f), (FilterMode)0));
private static float RoundedBox(float x, float y, int size, float inset, float radius)
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
float num = (float)size / 2f - inset - radius;
float num2 = Mathf.Abs(x - (float)size / 2f) - num;
float num3 = Mathf.Abs(y - (float)size / 2f) - num;
Vector2 val = new Vector2(Mathf.Max(num2, 0f), Mathf.Max(num3, 0f));
return ((Vector2)(ref val)).magnitude + Mathf.Min(Mathf.Max(num2, num3), 0f) - radius;
}
private static float Segment(float x, float y, float ax, float ay, float bx, float by)
{
//IL_0006: 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)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = new Vector2(x - ax, y - ay);
Vector2 val2 = default(Vector2);
((Vector2)(ref val2))..ctor(bx - ax, by - ay);
float num = Mathf.Clamp01(Vector2.Dot(val, val2) / ((Vector2)(ref val2)).sqrMagnitude);
Vector2 val3 = val - val2 * num;
return ((Vector2)(ref val3)).magnitude;
}
private static float Fill(float d)
{
return Mathf.Clamp01(0.5f - d);
}
private static float Ring(float d, float width)
{
return Mathf.Clamp01(0.5f - d) * Mathf.Clamp01(d + width + 0.5f);
}
private static Color Over(Color below, Color above, float alpha)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
float num = alpha + below.a * (1f - alpha);
if (num <= 0f)
{
return new Color(0f, 0f, 0f, 0f);
}
Color result = (above * alpha + below * below.a * (1f - alpha)) / num;
result.a = num;
return result;
}
internal static Sprite Make(int size, Func<float, float, Color> pixel, Vector4 border = default(Vector4), FilterMode filter = (FilterMode)1)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: 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)
//IL_0018: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
{
wrapMode = (TextureWrapMode)1,
filterMode = filter
};
Color[] array = (Color[])(object)new Color[size * size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i * size + j] = pixel((float)j + 0.5f, (float)i + 0.5f);
}
}
val.SetPixels(array);
val.Apply(false, true);
Object.DontDestroyOnLoad((Object)(object)val);
Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, border);
Object.DontDestroyOnLoad((Object)(object)obj);
return obj;
}
}
public class TestHarness : MonoBehaviour
{
private static readonly FieldRef<CraftingMenu, List<KeyValuePair<int, Recipe>>> s_recipes = AccessTools.FieldRefAccess<CraftingMenu, List<KeyValuePair<int, Recipe>>>("m_complexeRecipes");
private static readonly FieldRef<CraftingMenu, List<RecipeDisplay>> s_displays = AccessTools.FieldRefAccess<CraftingMenu, List<RecipeDisplay>>("m_recipeDisplays");
private static readonly FieldRef<CraftingMenu, int> s_selected = AccessTools.FieldRefAccess<CraftingMenu, int>("m_lastRecipeIndex");
private string m_dir;
private string m_problem;
public static void StartIfRequested(GameObject host)
{
if (UnityEngineExtensions.Contains<string>(Environment.GetCommandLineArgs(), "--it-test"))
{
host.AddComponent<TestHarness>();
}
}
private void Start()
{
((MonoBehaviour)this).StartCoroutine(Run());
}
private static void Log(string message)
{
Plugin.Log.LogMessage((object)("it-test: " + message));
}
private void Check(bool ok, string what)
{
Log((ok ? "ok " : "FAIL ") + what);
if (!ok && m_problem == null)
{
m_problem = what;
}
}
private static IEnumerator WaitRealtime(float seconds)
{
float end = Time.realtimeSinceStartup + seconds;
while (Time.realtimeSinceStartup < end)
{
yield return null;
}
}
private IEnumerator Capture(string name)
{
yield return (object)new WaitForEndOfFrame();
Texture2D val = ScreenCapture.CaptureScreenshotAsTexture();
string text = Path.Combine(m_dir, name + ".png");
File.WriteAllBytes(text, ImageConversion.EncodeToPNG(val));
Object.Destroy((Object)(object)val);
Log("captured " + text);
}
private IEnumerator Run()
{
Character character = null;
float deadline = Time.realtimeSinceStartup + 900f;
while ((Object)(object)character == (Object)null)
{
if (Time.realtimeSinceStartup > deadline)
{
Plugin.Log.LogError((object)"it-test: FAILED no local character after 900 s");
yield break;
}
yield return null;
if (!((Object)(object)NetworkLevelLoader.Instance == (Object)null) && NetworkLevelLoader.Instance.IsOverallLoadingDone)
{
try
{
CharacterManager instance = CharacterManager.Instance;
character = ((instance != null) ? instance.GetFirstLocalCharacter() : null);
}
catch (NullReferenceException)
{
}
}
}
yield return WaitRealtime(3f);
MenuManager.Instance.MasterCanvas.alpha = 1f;
MenuManager.Instance.MasterCanvas.interactable = true;
m_dir = Path.Combine(Paths.BepInExRootPath, "IngredientTrackerTest");
Directory.CreateDirectory(m_dir);
string[] files = Directory.GetFiles(m_dir, "*.png");
for (int i = 0; i < files.Length; i++)
{
File.Delete(files[i]);
}
Log($"local character {character.Name} ({character.UID})");
SaveRequestedIcons();
IEnumerator steps = Steps(character);
while (true)
{
object current;
try
{
if (!steps.MoveNext())
{
break;
}
current = steps.Current;
goto IL_01d7;
}
catch (Exception ex2)
{
if (m_problem == null)
{
m_problem = "exception " + ex2;
}
}
break;
IL_01d7:
yield return current;
}
if (m_problem != null)
{
Plugin.Log.LogError((object)("it-test: FAILED " + m_problem));
}
else
{
Log("done");
}
}
private static void Blocks(CraftingMenu menu, out List<Recipe> craftable, out List<Recipe> missing)
{
craftable = new List<Recipe>();
missing = new List<Recipe>();
List<KeyValuePair<int, Recipe>> list = s_recipes.Invoke(menu);
List<RecipeDisplay> list2 = s_displays.Invoke(menu);
Dictionary<Transform, Recipe> dictionary = new Dictionary<Transform, Recipe>();
for (int i = 0; i < list.Count; i++)
{
dictionary[((Component)list2[i]).transform] = list[i].Value;
}
Transform parent = ((Component)list2[0]).transform.parent;
bool flag = false;
for (int j = 0; j < parent.childCount; j++)
{
Transform child = parent.GetChild(j);
if (((Component)child).gameObject.activeSelf)
{
Recipe value;
if (((Object)child).name == "zSeparator")
{
flag = true;
}
else if (dictionary.TryGetValue(child, out value))
{
(flag ? missing : craftable).Add(value);
}
}
}
}
private static string Names(IEnumerable<Recipe> recipes)
{
return string.Join(", ", recipes.Select((Recipe r) => r.Name));
}
private static Item Prefab(RecipeIngredient ingredient)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
if ((int)ingredient.ActionType == 1)
{
return ingredient.AddedIngredient;
}
return (from p in ((Dictionary<string, Item>)AccessTools.Field(typeof(ResourcesPrefabManager), "ITEM_PREFABS").GetValue(null)).Values
where (Object)(object)p != (Object)null && !(p is WaterItem) && ingredient.Match(p)
orderby p.ItemID
select p).FirstOrDefault();
}
private static bool Badged(ItemDisplay display)
{
IngredientBadge componentInChildren = ((Component)display).GetComponentInChildren<IngredientBadge>(true);
if ((Object)(object)componentInChildren != (Object)null && ((Component)componentInChildren).gameObject.activeInHierarchy)
{
return componentInChildren.Recipes.Count > 0;
}
return false;
}
private static ItemDisplay DisplayOf(Character character, Item item)
{
return ((IEnumerable<ItemDisplay>)((Component)character.CharacterUI).GetComponentsInChildren<ItemDisplay>(false)).FirstOrDefault((Func<ItemDisplay, bool>)((ItemDisplay d) => (Object)(object)d.RefItem == (Object)(object)item));
}
private IEnumerator Steps(Character character)
{
CharacterUI ui = character.CharacterUI;
CraftingMenu menu = UnityEngineExtensions.FirstOrDefault<CraftingMenu>((IList<CraftingMenu>)((Component)ui).GetComponentsInChildren<CraftingMenu>(true));
Check((Object)(object)menu != (Object)null, "crafting menu found");
if ((Object)(object)menu == (Object)null)
{
yield break;
}
List<Recipe> source = (from r in RecipeManager.Instance.GetRecipes((CraftingType)2, character)
where r.IngredientCount > 1 && r.Results.Length != 0 && (Object)(object)r.Results[0].RefItem != (Object)null && r.Ingredients.All((RecipeIngredient i) => (Object)(object)Prefab(i) != (Object)null)
orderby r.Name
select r).ToList();
CharacterRecipeKnowledge knowledge = character.Inventory.RecipeKnowledge;
foreach (Recipe item in source.Take(8))
{
if (!knowledge.IsRecipeLearned(UID.op_Implicit(item.UID)))
{
knowledge.LearnRecipe(item);
}
}
List<Recipe> list = source.Where((Recipe r) => knowledge.IsRecipeLearned(UID.op_Implicit(r.UID))).ToList();
Log($"{list.Count} known survival recipes: {Names(list)}");
foreach (Recipe item2 in list)
{
TrackedRecipes.SetTracked(character, item2, tracked: false);
}
Recipe craftableTarget = list.Last();
Recipe[] array = (Recipe[])(object)new Recipe[2]
{
list.First(),
craftableTarget
};
for (int num = 0; num < array.Length; num++)
{
RecipeIngredient[] ingredients = array[num].Ingredients;
foreach (RecipeIngredient ingredient in ingredients)
{
character.Inventory.GenerateItem(Prefab(ingredient), 1, false);
}
}
yield return WaitRealtime(1f);
ui.ShowMenu((MenuScreens)14);
yield return WaitRealtime(1.5f);
Blocks(menu, out var craftable, out var missing);
Log("before: craftable [" + Names(craftable) + "] | missing [" + Names(missing) + "]");
Check(craftable.Count >= 2 && (Object)(object)craftable.Last() == (Object)(object)craftableTarget, craftableTarget.Name + " is craftable, last of 2+");
Check(missing.Count >= 2, "at least two recipes miss ingredients");
if (m_problem == null)
{
Recipe missingTarget = missing.Last();
yield return Capture("1_crafting_before");
List<KeyValuePair<int, Recipe>> list2 = s_recipes.Invoke(menu);
RecipeTick componentInChildren = ((Component)s_displays.Invoke(menu)[list2.FindIndex((KeyValuePair<int, Recipe> r) => (Object)(object)r.Value == (Object)(object)missingTarget)]).GetComponentInChildren<RecipeTick>(true);
Check((Object)(object)componentInChildren != (Object)null && !componentInChildren.Tracked, "unticked box on " + missingTarget.Name);
PointerEventData val = new PointerEventData(EventSystem.current)
{
button = (InputButton)0
};
ExecuteEvents.Execute<IPointerDownHandler>(((Component)componentInChildren).gameObject, (BaseEventData)(object)val, ExecuteEvents.pointerDownHandler);
ExecuteEvents.Execute<IPointerClickHandler>(((Component)componentInChildren).gameObject, (BaseEventData)(object)val, ExecuteEvents.pointerClickHandler);
int num3 = s_recipes.Invoke(menu).FindIndex((KeyValuePair<int, Recipe> r) => (Object)(object)r.Value == (Object)(object)craftableTarget);
menu.OnRecipeSelected(num3, false);
CraftingPatches.Toggle(menu, craftableTarget);
yield return WaitRealtime(0.5f);
Blocks(menu, out craftable, out missing);
Log("after: craftable [" + Names(craftable) + "] | missing [" + Names(missing) + "]");
Check((Object)(object)UnityEngineExtensions.FirstOrDefault<Recipe>((IList<Recipe>)craftable) == (Object)(object)craftableTarget, craftableTarget.Name + " first among craftable recipes");
Check((Object)(object)UnityEngineExtensions.FirstOrDefault<Recipe>((IList<Recipe>)missing) == (Object)(object)missingTarget, missingTarget.Name + " first among recipes missing ingredients");
int num4 = s_selected.Invoke(menu);
Check(num4 >= 0 && (Object)(object)s_recipes.Invoke(menu)[num4].Value == (Object)(object)craftableTarget, "selection follows the ticked recipe");
Check(TrackedRecipes.IsTracked(character, missingTarget) && TrackedRecipes.IsTracked(character, craftableTarget), "both recipes tracked");
string configPath = Paths.ConfigPath;
UID uID = character.UID;
string text = Path.Combine(configPath, "IngredientTracker", ((UID)(ref uID)).Value + ".txt");
Check(File.Exists(text) && File.ReadAllLines(text).Length == 2, "tracked recipes saved to " + text);
yield return Capture("2_crafting_ticked");
ui.HideMenu((MenuScreens)14, true);
yield return WaitRealtime(0.5f);
Dictionary<string, Item> dictionary = (Dictionary<string, Item>)AccessTools.Field(typeof(ResourcesPrefabManager), "ITEM_PREFABS").GetValue(null);
Item val2 = (Item)(object)(from b in dictionary.Values.OfType<Bag>()
where ((Item)b).GetIsDLCOwned()
orderby ((Item)b).ItemID
select b).FirstOrDefault();
Item unrelatedPrefab = (Item)(object)((IEnumerable<Weapon>)(from w in dictionary.Values.OfType<Weapon>()
orderby ((Item)w).ItemID
select w)).FirstOrDefault((Func<Weapon, bool>)((Weapon w) => !TrackedRecipes.UsingIngredient(character, (Item)(object)w).Any() && ((Item)w).GetIsDLCOwned() && !((Item)w).Name.StartsWith("Test")));
Item missingIngredient = Prefab(missingTarget.Ingredients[0]);
Item craftableIngredient = Prefab(craftableTarget.Ingredients[0]);
string[] obj = new string[8]
{
"bag ",
(val2 != null) ? val2.Name : null,
", unrelated ",
null,
null,
null,
null,
null
};
obj[3] = ((unrelatedPrefab != null) ? unrelatedPrefab.Name : null);
obj[4] = ", ingredients ";
obj[5] = ((missingIngredient != null) ? missingIngredient.Name : null);
obj[6] = " / ";
Item obj2 = craftableIngredient;
obj[7] = ((obj2 != null) ? obj2.Name : null);
Log(string.Concat(obj));
Bag loose = MakeBag(character, val2, 1.5f);
Bag dropped = MakeBag(character, val2, -1.5f);
yield return WaitRealtime(0.5f);
Item lootA = Put(loose, missingIngredient);
Item lootB = Put(loose, craftableIngredient);
Item lootC = Put(loose, unrelatedPrefab);
yield return WaitRealtime(0.5f);
loose.ShowContent(character);
yield return WaitRealtime(1.5f);
ItemDisplay dA = DisplayOf(character, lootA);
ItemDisplay val3 = DisplayOf(character, lootB);
ItemDisplay val4 = DisplayOf(character, lootC);
Check((Object)(object)dA != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null, "loose bag's items displayed");
if ((Object)(object)dA != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
{
Check(Badged(dA), "loot " + lootA.Name + " badged");
Check(Badged(val3), "loot " + lootB.Name + " badged");
Check(!Badged(val4), "loot " + lootC.Name + " not badged");
Image component = ((Component)((Component)((Component)dA).GetComponentInChildren<IngredientBadge>(true)).transform.Find("Frame")).GetComponent<Image>();
Canvas rootCanvas = ((Graphic)component).canvas.rootCanvas;
Log($"badge frame: multiplier {component.pixelsPerUnitMultiplier:0.###}, canvas scale {rootCanvas.scaleFactor:0.###}, " + $"ref PPU {rootCanvas.referencePixelsPerUnit}, frame lossy scale {((Component)component).transform.lossyScale.x:0.###}, render mode {rootCanvas.renderMode}");
}
yield return Capture("3_loose_bag");
SaveIcon(craftableIngredient.ItemIcon, "ingredient_icon");
SaveIcon(craftableTarget.Results[0].RefItem.ItemIcon, "recipe_icon");
ui.HideMenu((MenuScreens)11, true);
yield return WaitRealtime(0.5f);
uID = character.UID;
((Item)dropped).PreviousOwnerUID = ((UID)(ref uID)).Value;
Item ownA = Put(dropped, missingIngredient);
yield return WaitRealtime(0.5f);
dropped.ShowContent(character);
yield return WaitRealtime(1.5f);
ItemDisplay val5 = DisplayOf(character, ownA);
Check((Object)(object)val5 != (Object)null && !Badged(val5), ownA.Name + " in the player's dropped bag not badged");
ui.HideMenu((MenuScreens)11, true);
yield return WaitRealtime(0.5f);
ui.ShowMenu((MenuScreens)2);
yield return WaitRealtime(1.5f);
List<ItemDisplay> list3 = (from d in ((Component)ui).GetComponentsInChildren<ItemDisplay>(false)
where (Object)(object)d.RefItem != (Object)null && d.RefItem.ItemID == craftableIngredient.ItemID && d.RefItem.IsChildToPlayer
select d).ToList();
Check(list3.Count > 0 && list3.All((ItemDisplay d) => !Badged(d)), $"{craftableIngredient.Name} in the inventory not badged ({list3.Count} displays)");
yield return Capture("4_inventory");
ui.HideMenu((MenuScreens)2, true);
TrackedRecipes.SetTracked(character, missingTarget, tracked: false);
IngredientBadges.RefreshAll();
Check((Object)(object)dA == (Object)null || !Badged(dA) || (Object)(object)dA.RefItem != (Object)(object)lootA, "badge removed after unticking");
TrackedRecipes.SetTracked(character, craftableTarget, tracked: false);
}
}
private void SaveRequestedIcons()
{
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
string[] commandLineArgs = Environment.GetCommandLineArgs();
int num = Array.IndexOf(commandLineArgs, "--it-save-icons");
if (num < 0 || num + 1 >= commandLineArgs.Length)
{
return;
}
Dictionary<string, Item> dictionary = (Dictionary<string, Item>)AccessTools.Field(typeof(ResourcesPrefabManager), "ITEM_PREFABS").GetValue(null);
Dictionary<string, Recipe> dictionary2 = AccessTools.FieldRefAccess<RecipeManager, Dictionary<string, Recipe>>("m_recipes").Invoke(RecipeManager.Instance);
string[] array = commandLineArgs[num + 1].Split(new char[1] { ';' });
foreach (string name in array)
{
Item item = (from p in dictionary.Values
where (Object)(object)p != (Object)null && p.Name == name
orderby p.ItemID
select p).FirstOrDefault();
if ((Object)(object)item == (Object)null)
{
Log("no item named " + name);
continue;
}
SaveIcon(item.ItemIcon, name.Replace(' ', '_'));
foreach (Recipe item2 in dictionary2.Values.Where((Recipe r) => r.Results.Any((ItemReferenceQuantity x) => (Object)(object)x.RefItem != (Object)null && x.RefItem.ItemID == item.ItemID)))
{
Log($"{name} ({item.ItemID}) made by {item2.Name} [{item2.CraftingStationType}]: " + string.Join(" + ", item2.Ingredients.Select((RecipeIngredient g) => (!((Object)(object)g.AddedIngredient != (Object)null)) ? ((object)g.AddedIngredientType).ToString() : g.AddedIngredient.Name)));
}
}
}
private void SaveIcon(Sprite sprite, string name)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
Texture2D texture = sprite.texture;
RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
Graphics.Blit((Texture)(object)texture, temporary);
RenderTexture active = RenderTexture.active;
RenderTexture.active = temporary;
Rect textureRect = sprite.textureRect;
Texture2D val = new Texture2D((int)((Rect)(ref textureRect)).width, (int)((Rect)(ref textureRect)).height, (TextureFormat)5, false);
val.ReadPixels(textureRect, 0, 0);
val.Apply();
RenderTexture.active = active;
RenderTexture.ReleaseTemporary(temporary);
File.WriteAllBytes(Path.Combine(m_dir, name + ".png"), ImageConversion.EncodeToPNG(val));
Object.Destroy((Object)(object)val);
Log($"icon {((Object)sprite).name} {((Rect)(ref textureRect)).width}x{((Rect)(ref textureRect)).height} saved as {name}.png");
}
private static Bag MakeBag(Character character, Item prefab, float side)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
Bag val = (Bag)ItemManager.Instance.GenerateItemNetwork(prefab.ItemID);
((Component)val).transform.position = ((Component)character).transform.position + ((Component)character).transform.right * side + Vector3.up * 0.3f;
return val;
}
private static Item Put(Bag bag, Item prefab)
{
Item val = ItemManager.Instance.GenerateItemNetwork(prefab.ItemID);
((ItemContainer)bag.Container).AddItem(val);
return val;
}
}
internal static class TrackedRecipes
{
private static readonly FieldRef<RecipeManager, Dictionary<string, Recipe>> s_recipes = AccessTools.FieldRefAccess<RecipeManager, Dictionary<string, Recipe>>("m_recipes");
private static readonly Dictionary<string, List<string>> s_tracked = new Dictionary<string, List<string>>();
private static readonly Dictionary<string, Dictionary<int, List<Recipe>>> s_byIngredient = new Dictionary<string, Dictionary<int, List<Recipe>>>();
private static readonly List<Recipe> s_none = new List<Recipe>();
private static string Folder => Path.Combine(Paths.ConfigPath, "IngredientTracker");
private static List<string> For(Character character)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
UID uID = character.UID;
string value = ((UID)(ref uID)).Value;
if (!s_tracked.TryGetValue(value, out var value2))
{
value2 = new List<string>();
string text = Path.Combine(Folder, value + ".txt");
try
{
if (File.Exists(text))
{
string[] array = File.ReadAllLines(text);
foreach (string text2 in array)
{
if (text2.Trim().Length > 0 && !value2.Contains(text2.Trim()))
{
value2.Add(text2.Trim());
}
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("could not read " + text + ": " + ex.Message));
}
s_tracked[value] = value2;
}
return value2;
}
public static bool IsTracked(Character character, Recipe recipe)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character != (Object)null && (Object)(object)recipe != (Object)null)
{
List<string> list = For(character);
UID uID = recipe.UID;
return list.Contains(((UID)(ref uID)).Value);
}
return false;
}
public static void SetTracked(Character character, Recipe recipe, bool tracked)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
List<string> list = For(character);
UID uID = recipe.UID;
string value = ((UID)(ref uID)).Value;
if (list.Contains(value) == tracked)
{
return;
}
if (tracked)
{
list.Add(value);
}
else
{
list.Remove(value);
}
Dictionary<string, Dictionary<int, List<Recipe>>> dictionary = s_byIngredient;
uID = character.UID;
dictionary.Remove(((UID)(ref uID)).Value);
try
{
Directory.CreateDirectory(Folder);
string folder = Folder;
uID = character.UID;
File.WriteAllLines(Path.Combine(folder, ((UID)(ref uID)).Value + ".txt"), list.ToArray());
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("could not save the tracked recipes: " + ex.Message));
}
}
public static List<Recipe> UsingIngredient(Character character, Item item)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
List<string> list = For(character);
if (list.Count == 0)
{
return s_none;
}
UID uID = character.UID;
string value = ((UID)(ref uID)).Value;
if (!s_byIngredient.TryGetValue(value, out var value2))
{
value2 = (s_byIngredient[value] = new Dictionary<int, List<Recipe>>());
}
if (value2.TryGetValue(item.ItemID, out var value3))
{
return value3;
}
value3 = new List<Recipe>();
Dictionary<string, Recipe> dictionary2 = ((RecipeManager.Instance != null) ? s_recipes.Invoke(RecipeManager.Instance) : null);
foreach (string item2 in list)
{
if (dictionary2 != null && dictionary2.TryGetValue(item2, out var value4) && Uses(value4, item))
{
value3.Add(value4);
}
}
if (!(item is WaterContainer))
{
value2[item.ItemID] = value3;
}
return value3;
}
private static bool Uses(Recipe recipe, Item item)
{
if (recipe.Ingredients == null)
{
return false;
}
RecipeIngredient[] ingredients = recipe.Ingredients;
foreach (RecipeIngredient val in ingredients)
{
if (val != null && val.Match(item))
{
return true;
}
}
return false;
}
}