Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RestlessCook v0.5.5
RestlessCook.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using RestlessQoL.Api; using RestlessQoL.Core; using RestlessQoL.HudTweaks; using RestlessQoL.Storage; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RestlessCook")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.5.0")] [assembly: AssemblyInformationalVersion("0.5.5+11d2e243c950fa4b191334e2cf91604fb183fa49")] [assembly: AssemblyProduct("RestlessCook")] [assembly: AssemblyTitle("RestlessCook")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RestlessCook { internal sealed class CookbookWindow : MonoBehaviour { [HarmonyPatch(typeof(Menu), "Update")] private static class MenuInput { private static bool Prefix() { if ((Object)(object)_current == (Object)null) { return Time.frameCount != _closedFrame; } return false; } } private sealed class Card { internal readonly GameObject Root; private readonly Button _button; private readonly Image _icon; private readonly Text _name; private readonly Text _state; private readonly Text _expand; private readonly UiKitProgress _progress; private readonly Image _statusDiamond; private Action? _clicked; internal Card(Transform parent) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown Root = RestlessUi.Chip(parent, "recipe"); RestlessUi.PaperControl(Root, (Color?)null); _button = Root.AddComponent<Button>(); ((Selectable)_button).targetGraphic = (Graphic)(object)Root.GetComponent<Image>(); RestlessUi.PaperSelectable((Selectable)(object)_button); _icon = RestlessUi.Graphic(Root.transform, "icon", Color.white, false).GetComponent<Image>(); _icon.preserveAspect = true; _name = Label(Root.transform, "", 18, 0f, 0f, 100f, 40f); _name.alignment = (TextAnchor)3; RestlessUi.BoundedLabel(_name, 18, 15); _expand = Label(Root.transform, "›", 24, 0f, 0f, 20f, 28f); ((Graphic)_expand).color = RestlessUi.PaperMuted; ((Graphic)_expand).raycastTarget = false; _statusDiamond = RestlessUi.Graphic(Root.transform, "status-diamond", Color.white, false).GetComponent<Image>(); ((Transform)((Graphic)_statusDiamond).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 45f); _progress = UiKitApi.Progress(Root.transform, "preparation-track"); _state = Label(Root.transform, "", 15, 0f, 0f, 100f, 30f); _state.alignment = (TextAnchor)3; RestlessUi.BoundedLabel(_state, 15, 13); ((UnityEvent)_button.onClick).AddListener((UnityAction)delegate { _clicked?.Invoke(); }); } internal void Progress(KitchenStep step) { //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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Rect rect = ((RectTransform)Root.transform).rect; Vector2 size = ((Rect)(ref rect)).size; float num = ((step.State == KitchenStepState.Prepared) ? 1f : ((step.DurationSeconds > 0f) ? Mathf.Clamp01(step.ElapsedSeconds / step.DurationSeconds) : 0f)); _progress.Set(new Rect(20f, size.y - (float)(((Component)_statusDiamond).gameObject.activeSelf ? 34 : 10), size.x - 40f, 4f), 0f, num, Tint(step.State), Tint(step.State), step.State == KitchenStepState.Cooking && step.DurationSeconds > 0f); } internal void Set(string name, string state, Sprite? icon, Color tint, Action action, bool selected = false, bool featured = false, bool listEntry = false, bool expandable = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: 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) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) _clicked = action; Rect rect = ((RectTransform)Root.transform).rect; Vector2 size = ((Rect)(ref rect)).size; ((Component)_statusDiamond).gameObject.SetActive(featured); ((Component)_state).gameObject.SetActive(!listEntry); ((Component)_expand).gameObject.SetActive(expandable); Position(((Component)_expand).gameObject, size.x - 24f, 14f, 16f, 28f); if (featured) { Portrait(((Component)_icon).gameObject, 26f, (size.y - 96f) / 2f, 96f, 96f); Position(((Component)_name).gameObject, 136f, 26f, size.x - 242f, 50f); Portrait(((Component)_statusDiamond).gameObject, 138f, 93f, 7f, 7f); Position(((Component)_state).gameObject, 156f, 80f, size.x - 194f, 34f); } else if (listEntry) { Portrait(((Component)_icon).gameObject, 10f, (size.y - 44f) / 2f, 44f, 44f); Position(((Component)_name).gameObject, 64f, (size.y - 44f) / 2f, size.x - 76f, 44f); } else if (size.y <= 64f) { Portrait(((Component)_icon).gameObject, 6f, (size.y - 36f) / 2f, 36f, 36f); Position(((Component)_name).gameObject, 50f, 4f, size.x - 188f, size.y - 8f); Position(((Component)_state).gameObject, size.x - 132f, 4f, 124f, size.y - 8f); } else { Portrait(((Component)_icon).gameObject, 10f, 12f, 48f, 48f); Position(((Component)_name).gameObject, 68f, 6f, size.x - (float)(expandable ? 98 : 80), 50f); Position(((Component)_state).gameObject, 12f, 62f, size.x - 24f, size.y - 76f); } _name.alignment = (TextAnchor)3; _state.alignment = (TextAnchor)((size.y <= 64f) ? 5 : 3); _icon.sprite = icon; ((Behaviour)_icon).enabled = (Object)(object)icon != (Object)null; _name.text = name; _state.text = state; ((Graphic)_state).color = tint; _progress.Hide(); ((Graphic)_statusDiamond).color = tint; if (featured) { RestlessUi.CookHeroSurface(Root); return; } Transform val = Root.transform.Find("cookHeroFrame"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } RestlessUi.PaperControl(Root, (Color?)(Color)(selected ? RestlessUi.Accent : new Color(0.37f, 0.33f, 0.27f))); Transform val2 = Root.transform.Find("paperAccent"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(true); } } } private static CookbookWindow? _current; private static int _closedFrame = -1; private CraftingStation _table; private UiKitWindow _frame; private string _stationSelection = ""; private RectTransform _sheet; private RestlessScrollRect _recipes; private RestlessScrollRect _tree; private RestlessScrollRect _details; private readonly List<Card> _recipeCards = new List<Card>(); private readonly List<Card> _nodes = new List<Card>(); private readonly List<UiKitMaterialCard> _requirementCards = new List<UiKitMaterialCard>(); private readonly List<GameObject> _lines = new List<GameObject>(); private readonly List<Button> _tabs = new List<Button>(); private readonly Dictionary<string, Sprite?> _icons = new Dictionary<string, Sprite>(); private readonly List<int> _trail = new List<int>(); private IReadOnlyList<KitchenStep> _steps = Array.Empty<KitchenStep>(); private IReadOnlyList<KitchenOrder> _orders = Array.Empty<KitchenOrder>(); private string _recipe = ""; private string _query = ""; private string _stamp = ""; private int _tab; private int _count = 1; private int _focus; private int _order; private int _detailFocus = -1; private bool _blocked; private bool _confirmCancel; private string _category = "Feasts"; private readonly List<Button> _filters = new List<Button>(); private readonly List<GameObject> _quantityControls = new List<GameObject>(); private Text _detailTitle; private Image _dish; private GameObject _dishFrame; private Text _dishName; private Text _dishKind; private Text _station; private Text _requirementsLabel; private float _next; private float _messageUntil; private Text _heading; private Text _copy; private Text _status; private Text _quantity; private Text _actionText; private Text _actionHint; private Button _action; private Button _collect; private Button _back; private Vector2 _canvas; private string _pantrySelection = ""; internal static void Open(CraftingStation table) { //IL_0072: 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_0083: 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) if (!Plugin.CookbookEnabled.Value) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Enable Cookbook in Restless settings.", 0, (Sprite)null, false); } } else if (!((Object)(object)table == (Object)null) && !((Object)(object)GUIManager.CustomGUIFront == (Object)null) && !SettingsUi.IsOpen && !InventoryGui.IsVisible()) { Close(); GameObject obj = RestlessUi.Graphic(GUIManager.CustomGUIFront.transform, "RestlessCookbook", new Color(0f, 0f, 0f, 0.28f), true); RestlessUi.Stretch(obj, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); CookbookWindow cookbookWindow = (_current = obj.AddComponent<CookbookWindow>()); cookbookWindow._table = table; try { cookbookWindow.Build(); LookHints.SetSuppressed((object)cookbookWindow, true); cookbookWindow._blocked = true; GUIManager.BlockInput(true); cookbookWindow.RecipeList(); cookbookWindow.Refresh(force: true); } catch (Exception ex) { Debug.LogException(ex); Close(); } } } internal static void Close() { if (!((Object)(object)_current == (Object)null)) { CookbookWindow? current = _current; _current = null; _closedFrame = Time.frameCount; ((Component)current).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)current).gameObject); } } private void OnDisable() { LookHints.SetSuppressed((object)this, false); if ((Object)(object)_current == (Object)(object)this) { _current = null; } if (_blocked && !SettingsUi.IsOpen) { GUIManager.BlockInput(false); } _blocked = false; } private void Update() { //IL_0053: 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_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) Player localPlayer = Player.m_localPlayer; if (!Input.GetKeyDown((KeyCode)27) && Plugin.CookbookEnabled.Value && !((Object)(object)_table == (Object)null) && !((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && !SettingsUi.IsOpen && !InventoryGui.IsVisible()) { Vector3 val = ((Component)_table).transform.position - ((Component)localPlayer).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 25f)) { Fit(); if (Time.unscaledTime >= _next) { Refresh(force: false); } return; } } Close(); } private void Refresh(bool force) { _next = Time.unscaledTime + 1f; try { _orders = Kitchen.Orders(_table); if (_order != 0 && !_orders.Any((KitchenOrder o) => o.Id == _order)) { _order = 0; _trail.Clear(); _focus = 0; _detailFocus = -1; } if (_tab == 2) { PaintStations(force); return; } if (_tab == 3) { PaintPantry(force); return; } IReadOnlyList<KitchenStep> steps; if (_order == 0) { if (_tab != 1) { steps = Kitchen.Plan(_table, _recipe, _count); } else { IReadOnlyList<KitchenStep> readOnlyList = Array.Empty<KitchenStep>(); steps = readOnlyList; } } else { steps = Kitchen.Live(_table, _order); } _steps = steps; StringBuilder stringBuilder = new StringBuilder().Append(_tab).Append('|').Append(_order) .Append('|') .Append(_recipe) .Append('|') .Append(_count); foreach (KitchenStep step in _steps) { stringBuilder.Append('|').Append(step.Output).Append(':') .Append(step.Parent) .Append(':') .Append(step.Depth) .Append(':') .Append(step.Need) .Append(':') .Append(step.Have) .Append(':') .Append(step.Available) .Append(':') .Append(step.Cooking) .Append(':') .Append(step.State) .Append(':') .Append(step.Note) .Append(':') .Append(step.ElapsedSeconds) .Append(':') .Append(step.DurationSeconds); } foreach (KitchenOrder order in _orders) { stringBuilder.Append('|').Append(order.Id).Append(':') .Append(order.Ready) .Append(':') .Append(order.Count); } string text = stringBuilder.ToString(); if (force || text != _stamp) { if (_detailFocus >= _steps.Count) { _detailFocus = -1; } _stamp = text; if (_tab == 1) { OrderList(); } if (_focus >= _steps.Count) { _focus = 0; _trail.Clear(); } if (_tab == 1) { PaintOrderSteps(); } else { PaintTree(); } PaintDetails(); } if (Time.unscaledTime >= _messageUntil) { _status.text = ((_order == 0) ? "Queue an order · missing ingredients can be supplied while it waits" : OrderStatus()); } } catch (Exception ex) { Debug.LogException(ex); _status.text = "Kitchen data unavailable. Close and try again."; } } private string OrderStatus() { KitchenStep kitchenStep = _steps.FirstOrDefault((KitchenStep s) => s.State == KitchenStepState.Cooking && !Covered(s)); if (kitchenStep != null) { return "Preparing " + Local(kitchenStep.Name) + " · " + State(kitchenStep); } KitchenStep kitchenStep2 = _steps.FirstOrDefault((KitchenStep s) => s.State == KitchenStepState.Blocked && !Covered(s)); if (kitchenStep2 != null) { return Local(kitchenStep2.Name) + " · " + kitchenStep2.Note; } KitchenStep kitchenStep3 = _steps.FirstOrDefault((KitchenStep s) => s.State == KitchenStepState.Missing && s.Uses.Count == 0 && !Covered(s)); if (kitchenStep3 != null) { return "Waiting for " + Local(kitchenStep3.Name) + " · " + KitchenStock.Count(kitchenStep3.Available, kitchenStep3.Need) + " available"; } return "Order queued · waiting for the next preparation step"; } private void Tab(int tab) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) _detailFocus = -1; _tab = tab; _stamp = ""; _confirmCancel = false; for (int i = 0; i < _tabs.Count; i++) { UiKitApi.Tab(_tabs[i], i == tab); } foreach (Button filter in _filters) { ((Component)filter).gameObject.SetActive(tab == 0); } foreach (GameObject quantityControl in _quantityControls) { quantityControl.SetActive(tab == 0); } _detailTitle.text = ((tab == 2) ? "STATION DETAILS" : "SELECTED STEP"); if (tab == 0) { _order = 0; RecipeList(); } if (tab == 1) { OrderList(); } _trail.Clear(); _focus = 0; Refresh(force: true); RestlessScrollRect tree = _tree; Rect rect = ((ScrollRect)_tree).content.rect; Size(tree, ((Rect)(ref rect)).height, reset: true); RestlessScrollRect details = _details; rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); RestlessScrollRect recipes = _recipes; rect = ((ScrollRect)_recipes).content.rect; Size(recipes, ((Rect)(ref rect)).height, reset: true); } private void RecipeList() { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) List<CookRow> list = (from cookRow in Kitchen.Rows where Matches(cookRow) && (string.IsNullOrWhiteSpace(_query) || cookRow.Name.IndexOf(_query.Trim(), StringComparison.CurrentCultureIgnoreCase) >= 0) orderby TierOrder(cookRow.Tier), cookRow.Name select cookRow).ToList(); if (!list.Any((CookRow cookRow) => cookRow.Id == _recipe)) { _recipe = ((list.Count > 0) ? list[0].Id : ""); _detailFocus = -1; _focus = 0; _trail.Clear(); } for (int num = 0; num < list.Count; num++) { CookRow r = list[num]; Card card = GetCard(_recipeCards, num, (Transform)(object)((ScrollRect)_recipes).content); Position(card.Root, 0f, num * 80, 228f, 72f); card.Set(r.Name, TierName(r.Tier) + " · " + r.Kind, Icon(Output(r)), (r.Id == _recipe) ? RestlessUi.Accent : RestlessUi.PaperMuted, delegate { //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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) _detailFocus = -1; _recipe = r.Id; _order = 0; _focus = 0; _trail.Clear(); _confirmCancel = false; RecipeList(); Refresh(force: true); RestlessScrollRect tree = _tree; Rect rect = ((ScrollRect)_tree).content.rect; Size(tree, ((Rect)(ref rect)).height, reset: true); RestlessScrollRect details = _details; rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); }, r.Id == _recipe, featured: false, listEntry: true); } HideAfter(_recipeCards, list.Count); Size(_recipes, list.Count * 80, reset: false); if (list.Count == 0) { Message("No matching recipes."); } } private void OrderList() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _orders.Count; i++) { KitchenOrder o = _orders[i]; Card card = GetCard(_recipeCards, i, (Transform)(object)((ScrollRect)_recipes).content); Position(card.Root, 0f, i * 96, 228f, 90f); card.Set(o.Name, o.Collected + o.Ready + " / " + o.Count + " finished", Icon(o.Feast), (o.Id == _order) ? RestlessUi.Accent : RestlessUi.PaperMuted, delegate { _detailFocus = -1; _order = o.Id; _focus = 0; _trail.Clear(); _confirmCancel = false; Refresh(force: true); }, o.Id == _order); } HideAfter(_recipeCards, _orders.Count); Size(_recipes, _orders.Count * 96, reset: false); } private List<int> Children(int index) { List<int> list = new List<int>(); for (int i = index + 1; i < _steps.Count && _steps[i].Depth > _steps[index].Depth; i++) { if (_steps[i].Depth == _steps[index].Depth + 1) { list.Add(i); } } return list; } private void Focus(int index) { //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_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) _detailFocus = -1; _trail.Add(_focus); _focus = index; if (_tab == 1) { PaintOrderSteps(); } else { PaintTree(); } PaintDetails(); RestlessScrollRect tree = _tree; Rect rect = ((ScrollRect)_tree).content.rect; Size(tree, ((Rect)(ref rect)).height, reset: true); RestlessScrollRect details = _details; rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); } private void Inspect(int index) { //IL_003f: 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) if (_steps[index].Uses.Count > 0) { Focus(index); return; } _detailFocus = index; PaintDetails(); RestlessScrollRect details = _details; Rect rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); } private void PaintTree() { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject line in _lines) { line.SetActive(false); } ((Selectable)_back).interactable = _trail.Count > 0; if (_steps.Count == 0) { HideAfter(_nodes, 0); _heading.text = ((_tab != 1) ? "Choose a recipe" : ((_orders.Count == 0) ? "No kitchen orders" : "Choose an order")); return; } KitchenStep kitchenStep = _steps[_focus]; _heading.text = ((_trail.Count == 0) ? "Preparation plan" : "Ingredient preparation"); Card card = GetCard(_nodes, 0, (Transform)(object)((ScrollRect)_tree).content); Position(card.Root, 18f, 8f, 492f, 152f); card.Set(Local(kitchenStep.Name), State(kitchenStep), Icon(kitchenStep.Output), Tint(kitchenStep.State), delegate { _detailFocus = -1; PaintDetails(); }, selected: true, featured: true); card.Progress(kitchenStep); List<int> list = Children(_focus); int num = 0; for (int num2 = 0; num2 < list.Count; num2++) { int index = list[num2]; KitchenStep kitchenStep2 = _steps[index]; float num3 = ((num2 == list.Count - 1 && list.Count % 2 == 1) ? 138 : (num2 % 2 * 276)); float num4 = 192 + num2 / 2 * 144; Line(num++, 264f, 142f, 2f, num4 - 158f); Line(num++, Math.Min(264f, num3 + 126f), num4 - 16f, Math.Abs(264f - (num3 + 126f)), 2f); Line(num++, num3 + 126f, num4 - 16f, 2f, 16f); Card card2 = GetCard(_nodes, num2 + 1, (Transform)(object)((ScrollRect)_tree).content); Position(card2.Root, num3, num4, 252f, 116f); card2.Set(Local(kitchenStep2.Name), State(kitchenStep2), Icon(kitchenStep2.Output), Tint(kitchenStep2.State), delegate { Inspect(index); }, selected: false, featured: false, listEntry: false, kitchenStep2.Uses.Count > 0); card2.Progress(kitchenStep2); } HideAfter(_nodes, list.Count + 1); Size(_tree, (list.Count == 0) ? 168 : (192 + (list.Count + 1) / 2 * 144), reset: false); } private void PaintDetails() { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Expected O, but got Unknown ShowDish(); int num = ((_detailFocus >= 0 && _detailFocus < _steps.Count) ? _detailFocus : _focus); KitchenStep kitchenStep = ((_steps.Count > num) ? _steps[num] : null); _dish.sprite = ((kitchenStep == null) ? null : Icon(kitchenStep.Output)); ((Behaviour)_dish).enabled = (Object)(object)_dish.sprite != (Object)null; _dishFrame.SetActive(kitchenStep != null); _dishName.text = ((kitchenStep == null) ? "Select a dish" : Local(kitchenStep.Name)); _dishKind.text = ((kitchenStep == null) ? "" : State(kitchenStep)); ((Graphic)_dishKind).color = ((kitchenStep == null) ? RestlessUi.PaperMuted : Tint(kitchenStep.State)); _station.text = ((kitchenStep == null) ? "" : ((kitchenStep.Station == KitchenStationKind.None) ? "Gather from the world" : (StationName(kitchenStep.Station) + ((kitchenStep.Station == KitchenStationKind.Cauldron || kitchenStep.Station == KitchenStationKind.PrepTable || kitchenStep.Station == KitchenStationKind.MeadKettle) ? ("\nRequired level " + kitchenStep.StationLevel) : ((kitchenStep.Station == KitchenStationKind.Fermenter) ? "\nUses native fermentation time" : "\nUses native cooking time"))))); StringBuilder stringBuilder = new StringBuilder(); int num2 = kitchenStep?.Uses.Count ?? 0; List<int> list = ((kitchenStep == null) ? new List<int>() : Children(num)); for (int i = 0; i < num2; i++) { KitchenUse use = kitchenStep.Uses[i]; int index = list.FindIndex((int n) => _steps[n].Output == use.Item); if (index >= 0) { index = list[index]; } KitchenStep kitchenStep2 = ((index >= 0) ? _steps[index] : null); int num3 = kitchenStep2?.Available ?? use.Have; bool flag = kitchenStep2 != null && Covered(kitchenStep2); if (i == _requirementCards.Count) { _requirementCards.Add(new UiKitMaterialCard((Transform)(object)((ScrollRect)_details).content)); } UiKitMaterialCard obj = _requirementCards[i]; string text = KitchenStock.Count(num3, use.Amount); obj.Set(new Rect(0f, (float)(26 + i * 84), 280f, 76f), Local(use.Name), text, flag ? "Covered by another step" : ((num3 >= use.Amount) ? "Available / needed" : "Missing ingredients"), Icon(use.Item), !flag && num3 < use.Amount, (index >= 0) ? ((Action)delegate { Inspect(index); }) : null); } HideAfter(_requirementCards, num2); if (kitchenStep != null) { if ((_order != 0 || num != 0) && !string.IsNullOrWhiteSpace(kitchenStep.Note)) { stringBuilder.AppendLine(kitchenStep.Note).AppendLine(); } IReadOnlyList<CookRow> readOnlyList = Kitchen.OtherUses(kitchenStep.Output); if (readOnlyList.Count > 0) { stringBuilder.AppendLine("ALSO USED IN"); foreach (CookRow item in readOnlyList) { stringBuilder.AppendLine(item.Name); } } } else { stringBuilder.Append((_tab == 1) ? "Select an order on the left to follow its progress." : "Select a recipe to explore its ingredients."); } _requirementsLabel.text = ((num2 > 0) ? "INGREDIENTS · STOCK / NEEDED" : ""); _copy.text = stringBuilder.ToString(); int num4 = ((num2 > 0) ? (34 + num2 * 84) : 0); Position(((Component)_copy).gameObject, 0f, num4, 280f, Mathf.Max(60f, _copy.preferredHeight)); Size(_details, (float)num4 + _copy.preferredHeight + 16f, reset: false); KitchenOrder kitchenOrder = _orders.FirstOrDefault((KitchenOrder o) => o.Id == _order); ((Component)_collect).gameObject.SetActive(kitchenOrder != null); ((Selectable)_collect).interactable = kitchenOrder != null && kitchenOrder.Ready > 0; ((Component)_action).gameObject.SetActive(_tab < 2); ((Selectable)_action).interactable = kitchenOrder != null || (_tab == 0 && _steps.Count > 0 && _steps[0].Uses.Count > 0 && _orders.Count < 8); _actionText.text = ((kitchenOrder == null) ? ("Queue " + _count) : (_confirmCancel ? "Confirm cancellation" : "Cancel order")); ((Component)_actionHint).gameObject.SetActive(_tab == 0); _actionHint.text = ((_steps.Count == 0) ? "Choose a recipe to queue." : QueueReason(_steps[0])); _quantity.text = _count.ToString(); } private void Act() { if (_tab == 3) { TakePantry(); } else { if (!((Selectable)_action).interactable) { return; } try { if (_order != 0) { if (!_confirmCancel) { _confirmCancel = true; PaintDetails(); Message("Cancel this order? Prepared food remains in the kitchen pantry."); return; } Kitchen.Cancel(_table, _order); _order = 0; _confirmCancel = false; Message("Cancellation requested."); } else { HashSet<int> previous = new HashSet<int>(from o in Kitchen.Orders(_table) select o.Id); if (Kitchen.Place(_table, _recipe, _count)) { _order = Kitchen.Orders(_table).FirstOrDefault((KitchenOrder o) => !previous.Contains(o.Id))?.Id ?? 0; Tab(1); Message("Order queued. Each step below shows what happens next."); } else { Message("Order could not be placed. Check ownership or queue capacity."); } } Refresh(force: true); } catch (Exception ex) { Debug.LogException(ex); Message("Action failed. Check Orders before trying again."); } } } private void Collect() { try { Message("Collected " + Kitchen.Collect(_table, _order) + ". Remaining food stays at the table."); Refresh(force: true); } catch (Exception ex) { Debug.LogException(ex); Message("Collection failed. Check your inventory."); } } private void PaintStations(bool force) { //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) HideDish(); _requirementsLabel.text = ""; ((Component)_actionHint).gameObject.SetActive(false); HideAfter(_requirementCards, 0); List<KitchenStationInfo> list = (from s in Kitchen.Stations(_table) where Local(s.Name).IndexOf(_query, StringComparison.OrdinalIgnoreCase) >= 0 select s).ToList(); if (!list.Any((KitchenStationInfo s) => s.Id == _stationSelection)) { _stationSelection = list.FirstOrDefault()?.Id ?? ""; } string text = "stations|" + _stationSelection + "|" + string.Join("|", list.Select((KitchenStationInfo s) => s.Id + ":" + s.Level + ":" + s.Free + ":" + s.Cooking + ":" + s.Ready + ":" + s.Fuel + ":" + s.Block)); if (!force && text == _stamp) { return; } _stamp = text; foreach (GameObject line in _lines) { line.SetActive(false); } for (int num = 0; num < list.Count; num++) { KitchenStationInfo station = list[num]; Card card = GetCard(_recipeCards, num, (Transform)(object)((ScrollRect)_recipes).content); Position(card.Root, 0f, num * 100, 228f, 92f); card.Set(Local(station.Name), UiKitApi.StationState(Local(station.Block)), null, string.IsNullOrEmpty(station.Block) ? RestlessUi.Accent : RestlessUi.HealthTint, delegate { //IL_003d: 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) _stationSelection = station.Id; PaintStations(force: true); RestlessScrollRect details = _details; Rect rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); }, station.Id == _stationSelection); } HideAfter(_recipeCards, list.Count); Size(_recipes, list.Count * 100, reset: false); KitchenStationInfo kitchenStationInfo = list.FirstOrDefault((KitchenStationInfo s) => s.Id == _stationSelection); _heading.text = ((kitchenStationInfo == null) ? "No kitchen stations nearby" : Local(kitchenStationInfo.Name)); Card card2 = GetCard(_nodes, 0, (Transform)(object)((ScrollRect)_tree).content); Position(card2.Root, 24f, 24f, 500f, 128f); card2.Set((kitchenStationInfo == null) ? "Your kitchen" : Local(kitchenStationInfo.Name), (kitchenStationInfo == null) ? "Build a cooking station within the table's reach." : UiKitApi.StationState(Local(kitchenStationInfo.Block)), null, RestlessUi.Accent, delegate { }, selected: false, featured: true); if (kitchenStationInfo != null) { string[] array = new string[3] { (kitchenStationInfo.Kind == KitchenStationKind.Cauldron || kitchenStationInfo.Kind == KitchenStationKind.MeadKettle) ? ("Station level " + kitchenStationInfo.Level) : (kitchenStationInfo.Free + " free slots · " + kitchenStationInfo.Cooking + " cooking · " + kitchenStationInfo.Ready + " ready"), (kitchenStationInfo.FuelMax > 0) ? ("Fuel " + kitchenStationInfo.Fuel + " / " + kitchenStationInfo.FuelMax) : "No fuel required", kitchenStationInfo.Distance.ToString("0.0") + " m from preparation table" }; for (int num2 = 0; num2 < array.Length; num2++) { Card card3 = GetCard(_nodes, num2 + 1, (Transform)(object)((ScrollRect)_tree).content); Position(card3.Root, 24f, 176 + num2 * 96, 500f, 84f); card3.Set(array[num2], "", null, RestlessUi.PaperMuted, delegate { }); } HideAfter(_nodes, 4); Size(_tree, 480f, reset: false); } else { HideAfter(_nodes, 1); Size(_tree, 170f, reset: false); } _copy.text = ((kitchenStationInfo == null) ? "No cooking stations found nearby." : (Local(kitchenStationInfo.Name) + "\n\n" + UiKitApi.StationState(Local(kitchenStationInfo.Block)) + "\n\n" + ((!kitchenStationInfo.NeedsFire) ? "No external fire required." : (kitchenStationInfo.FireLit ? "Required fire is lit." : "A nearby fire is required.")) + "\n\nKitchen orders use existing station reservations and native cooking times.")); Position(((Component)_copy).gameObject, 0f, 0f, 280f, Mathf.Max(60f, _copy.preferredHeight)); Size(_details, _copy.preferredHeight + 16f, reset: false); ((Component)_action).gameObject.SetActive(false); ((Component)_collect).gameObject.SetActive(false); ((Selectable)_back).interactable = false; } private void Message(string message) { _status.text = message; _messageUntil = Time.unscaledTime + 5f; } private static string Local(string text) { if (Localization.instance != null) { return Localization.instance.Localize(text); } return text; } private static string Output(CookRow r) { if (!r.IsFeast || !r.IsAdd || r.Prefab.EndsWith("_Material")) { return r.Prefab; } return r.Prefab + "_Material"; } private Sprite? Icon(string prefab) { if (_icons.TryGetValue(prefab, out Sprite value)) { return value; } ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab(prefab); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } Sprite[] array = ((ItemDrop)(obj?)).m_itemData?.m_shared?.m_icons; value = ((array != null && array.Length != 0) ? array[0] : null); _icons[prefab] = value; return value; } private bool Covered(KitchenStep step) { int parentIndex = step.ParentIndex; int num = 0; while (parentIndex >= 0 && parentIndex < _steps.Count && num < _steps.Count) { KitchenStep kitchenStep = _steps[parentIndex]; if (kitchenStep.Need > 0 && kitchenStep.Have + kitchenStep.Cooking >= kitchenStep.Need) { return true; } parentIndex = kitchenStep.ParentIndex; num++; } return false; } private string State(KitchenStep s) { string text = KitchenStock.Count(s.Available, s.Need); if (Covered(s)) { return "Covered by another step"; } if (s.State == KitchenStepState.Blocked) { return Local(s.Note) + " · " + text; } if (s.Cooking > 0) { string text2 = ((s.DurationSeconds > 0f) ? (" · " + Mathf.CeilToInt(Mathf.Max(0f, s.DurationSeconds - s.ElapsedSeconds)) + "s") : ""); return s.Cooking + " cooking" + text2 + (string.IsNullOrEmpty(s.ActiveStation) ? "" : (" · " + Local(s.ActiveStation))); } if (s.Uses.Count == 0) { return ((s.Available >= s.Need) ? "Available · " : "Missing · ") + text; } if (s.Available >= s.Need) { return "Prepared · " + text; } return s.Available + " prepared · " + Math.Max(0, s.Need - s.Available) + " to make"; } private static string QueueReason(KitchenStep root) { return root.State switch { KitchenStepState.Ready => "Ingredients available · ready to prepare", KitchenStepState.Queued => "Ingredients available · waiting for a station", KitchenStepState.Prepared => "Preparation complete", _ => string.IsNullOrWhiteSpace(root.Note) ? "Queue this dish for preparation" : Local(root.Note), }; } private static Color Tint(KitchenStepState s) { //IL_0022: 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_0007: Unknown result type (might be due to invalid IL or missing references) return (Color)(s switch { KitchenStepState.Blocked => RestlessUi.HealthTint, KitchenStepState.Prepared => new Color(0.58f, 0.76f, 0.56f), _ => RestlessUi.Accent, }); } private static string TierName(string tier) { string text = tier.ToLowerInvariant(); switch (text) { default: if (text.Length != 0) { break; } return "Kitchen"; case "blackforest": return "Black Forest"; case "deepnorth": return "Deep North"; case null: break; } return char.ToUpperInvariant(tier[0]) + tier.Substring(1); } private static int TierOrder(string tier) { return tier.ToLowerInvariant() switch { "meadows" => 0, "blackforest" => 1, "swamp" => 2, "mountains" => 3, "plains" => 4, "mistlands" => 5, "ashlands" => 6, "deepnorth" => 7, _ => 8, }; } private static string StationName(KitchenStationKind s) { return s switch { KitchenStationKind.Rack => "Cooking rack", KitchenStationKind.PrepTable => "Preparation table", KitchenStationKind.MeadKettle => "Mead kettle", _ => s.ToString(), }; } private void Build() { //IL_0023: 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_004d: Expected O, but got Unknown //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) _frame = new UiKitWindow(((Component)this).transform, "Cookbook", new Vector2(1240f, 800f), (Action)Close); _sheet = _frame.Sheet; _frame.Subtitle.text = "Cook the haul. Prepare meals. Share a feast."; string[] array = new string[4] { "Recipes", "Orders", "Kitchen", "Pantry" }; for (int i = 0; i < array.Length; i++) { int tab = i; _tabs.Add(Button((Transform)(object)_sheet, array[i], 570 + i * 124, 34f, 114f, 38f, delegate { Tab(tab); })); } ((UnityEvent<string>)(object)Field((Transform)(object)_sheet, 28f, 132f, 252f, 40f).onValueChanged).AddListener((UnityAction<string>)delegate(string value) { //IL_0066: 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) _query = value; if (_tab == 0) { RecipeList(); } else if (_tab == 1) { OrderList(); } Refresh(force: true); RestlessScrollRect recipes = _recipes; Rect rect = ((ScrollRect)_recipes).content.rect; Size(recipes, ((Rect)(ref rect)).height, reset: true); }); string[] categories = new string[6] { "All", "Feasts", "Meals", "Prep", "Bait", "Meads" }; for (int num = 0; num < categories.Length; num++) { string category = categories[num]; Button val = Button((Transform)(object)_sheet, category, 28 + num % 3 * 84, 182 + num / 3 * 36, 80f, 30f, delegate { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) _category = category; for (int j = 0; j < _filters.Count; j++) { RestlessUi.PaperControl(((Component)_filters[j]).gameObject, (categories[j] == category) ? new Color?(RestlessUi.Accent) : ((Color?)null)); } if (_tab == 0) { RecipeList(); Refresh(force: true); RestlessScrollRect recipes = _recipes; Rect rect = ((ScrollRect)_recipes).content.rect; Size(recipes, ((Rect)(ref rect)).height, reset: true); } }); _filters.Add(val); if (category == _category) { RestlessUi.PaperControl(((Component)val).gameObject, (Color?)RestlessUi.Accent); } } _recipes = Reader((Transform)(object)_sheet, "recipes", 28f, 260f, 252f, 422f, 80f); _quantityControls.Add(((Component)Label((Transform)(object)_sheet, "Order quantity", 18, 28f, 696f, 252f, 26f)).gameObject); _quantityControls.Add(((Component)Button((Transform)(object)_sheet, "−", 28f, 726f, 52f, 36f, delegate { Quantity(-1); })).gameObject); _quantity = Label((Transform)(object)_sheet, "1", 22, 88f, 726f, 132f, 36f); _quantity.alignment = (TextAnchor)4; _quantityControls.Add(((Component)_quantity).gameObject); _quantityControls.Add(((Component)Button((Transform)(object)_sheet, "+", 228f, 726f, 52f, 36f, delegate { Quantity(1); })).gameObject); Rule((Transform)(object)_sheet, 296f, 132f, 1f, 630f); _back = Button((Transform)(object)_sheet, "‹ Back", 316f, 132f, 100f, 34f, delegate { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (_trail.Count != 0) { _detailFocus = -1; _focus = _trail[_trail.Count - 1]; _trail.RemoveAt(_trail.Count - 1); PaintTree(); PaintDetails(); RestlessScrollRect tree = _tree; Rect rect = ((ScrollRect)_tree).content.rect; Size(tree, ((Rect)(ref rect)).height, reset: true); RestlessScrollRect details = _details; rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); } }); _heading = Label((Transform)(object)_sheet, "Choose a recipe", 24, 428f, 130f, 424f, 62f); RestlessUi.BoundedLabel(_heading, 24, 19); _tree = Reader((Transform)(object)_sheet, "recipe-tree", 316f, 206f, 552f, 552f, 112f); Rule((Transform)(object)_sheet, 884f, 132f, 1f, 630f); _detailTitle = Label((Transform)(object)_sheet, "SELECTED STEP", 18, 904f, 136f, 300f, 30f); _dish = RestlessUi.Graphic((Transform)(object)_sheet, "featured-dish", Color.white, false).GetComponent<Image>(); _dish.preserveAspect = true; Portrait(((Component)_dish).gameObject, 916f, 194f, 68f, 52f); _dishFrame = RestlessUi.Picture((Transform)(object)_sheet, "dish-frame", "cook-portrait", false); Portrait(_dishFrame, 904f, 186f, 96f, 64f); _dishName = Label((Transform)(object)_sheet, "", 22, 1012f, 180f, 192f, 78f); RestlessUi.BoundedLabel(_dishName, 22, 18); GameObject val2 = RestlessUi.Node((Transform)(object)_sheet, "dish-state"); Position(val2, 904f, 264f, 304f, 30f); _dishKind = Label(val2.transform, "", 17, 0f, 0f, 304f, 36f); RestlessUi.BoundedLabel(_dishKind, 17, 14); _station = Label((Transform)(object)_sheet, "", 18, 904f, 302f, 300f, 48f); Rule((Transform)(object)_sheet, 904f, 352f, 300f, 1f); _details = Reader((Transform)(object)_sheet, "details", 904f, 358f, 304f, 262f, 64f); _requirementsLabel = Label((Transform)(object)((ScrollRect)_details).content, "", 15, 0f, 0f, 280f, 24f); _copy = Label((Transform)(object)((ScrollRect)_details).content, "", 17, 0f, 0f, 280f, 100f); _copy.alignment = (TextAnchor)0; _copy.verticalOverflow = (VerticalWrapMode)1; _collect = Button((Transform)(object)_sheet, "Collect ready food", 904f, 636f, 304f, 42f, Collect); _actionHint = Label((Transform)(object)_sheet, "", 17, 904f, 630f, 304f, 58f); RestlessUi.BoundedLabel(_actionHint, 17, 14); _action = Button((Transform)(object)_sheet, "Queue 1", 904f, 694f, 304f, 52f, Act); RestlessUi.ForgedSurface(((Component)_action).gameObject, true, true); _actionText = ((Component)_action).GetComponentInChildren<Text>(); _status = Label((Transform)(object)_sheet, "", 16, 316f, 766f, 888f, 26f); RestlessUi.BoundedLabel(_status, 16, 13); UiKitApi.Tab(_tabs[0], true); Fit(); } private void Quantity(int delta) { if (_tab == 0) { _count = Mathf.Clamp(_count + delta, 1, 100); Refresh(force: true); } } private void Fit() { _frame.Fit(); } private void Line(int index, float x, float y, float width, float height) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (index == _lines.Count) { GameObject val = RestlessUi.Graphic((Transform)(object)((ScrollRect)_tree).content, "branch", new Color(0.64f, 0.52f, 0.32f, 0.85f), false); val.transform.SetAsFirstSibling(); _lines.Add(val); } GameObject obj = _lines[index]; obj.SetActive(true); Position(obj, x, y, Mathf.Max(1f, width), height); } private static void Position(GameObject go, float x, float y, float w, float h) { //IL_000b: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) RestlessUi.Pin(go, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, 0f - y), new Vector2(w, h)); } private static void Portrait(GameObject go, float x, float y, float w, float h) { //IL_000b: 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_0033: 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) RestlessUi.Pin(go, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(x + w / 2f, 0f - y - h / 2f), new Vector2(w, h)); } private static Text Label(Transform parent, string text, int size, float x, float y, float w, float h) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) Text obj = RestlessUi.Label(parent, text, size, RestlessUi.Text, (TextAnchor)3); Position(((Component)obj).gameObject, x, y, w, h); obj.horizontalOverflow = (HorizontalWrapMode)0; return obj; } private static Button Button(Transform parent, string text, float x, float y, float w, float h, Action action) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return UiKitApi.Button(parent, text, new Rect(x, y, w, h), action); } private static InputField Field(Transform parent, float x, float y, float w, float h) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return UiKitApi.Field(parent, "Search recipes…", new Rect(x, y, w, h), false, 128); } private static void Rule(Transform parent, float x, float y, float w, float h) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Position(RestlessUi.Graphic(parent, "rule", new Color(0.5f, 0.43f, 0.32f, 0.5f), false), x, y, w, h); } private static RestlessScrollRect Reader(Transform parent, string name, float x, float y, float w, float h, float row) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return UiKitApi.Reader(parent, name, new Rect(x, y, w, h), row, 2f, (Scrollbar)null); } private static void Size(RestlessScrollRect scroll, float height, bool reset) { UiKitApi.SizeReader(scroll, height, reset); } private static Card GetCard(List<Card> cards, int i, Transform parent) { if (i == cards.Count) { cards.Add(new Card(parent)); } cards[i].Root.SetActive(true); return cards[i]; } private static void HideAfter(List<Card> cards, int count) { for (int i = count; i < cards.Count; i++) { cards[i].Root.SetActive(false); } } private static void HideAfter(List<UiKitMaterialCard> cards, int count) { for (int i = count; i < cards.Count; i++) { cards[i].Root.SetActive(false); } } private bool Matches(CookRow row) { bool flag = row.Prefab.StartsWith("Mead", StringComparison.OrdinalIgnoreCase) || row.Kind.Equals("mead", StringComparison.OrdinalIgnoreCase); return _category switch { "Feasts" => row.IsFeast, "Meals" => row.IsMeal && !flag, "Prep" => row.Kind == "ingredient" || row.IsSideboard, "Bait" => row.Kind == "bait", "Meads" => flag, _ => row.IsFeast || row.IsMeal || row.IsSideboard || flag || row.Kind == "ingredient" || row.Kind == "bait", }; } private void HideDish() { ((Component)_actionHint).gameObject.SetActive(false); _station.text = ""; _requirementsLabel.text = ""; HideAfter(_requirementCards, 0); ((Behaviour)_dish).enabled = false; _dishFrame.SetActive(false); _dishName.text = ""; _dishKind.text = ""; ((Component)((Component)_dishKind).transform.parent).gameObject.SetActive(false); Position(((Component)_details).gameObject, 904f, 184f, 304f, 436f); ((ScrollRect)_details).viewport.SetSizeWithCurrentAnchors((Axis)1, 436f); if ((Object)(object)((ScrollRect)_details).verticalScrollbar != (Object)null) { Position(((Component)((ScrollRect)_details).verticalScrollbar).gameObject, 298f, 0f, 6f, 436f); } } private void ShowDish() { ((Component)((Component)_dishKind).transform.parent).gameObject.SetActive(true); Position(((Component)_details).gameObject, 904f, 358f, 304f, 262f); ((ScrollRect)_details).viewport.SetSizeWithCurrentAnchors((Axis)1, 262f); if ((Object)(object)((ScrollRect)_details).verticalScrollbar != (Object)null) { Position(((Component)((ScrollRect)_details).verticalScrollbar).gameObject, 298f, 0f, 6f, 262f); } } private void PaintOrderSteps() { //IL_010f: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject line in _lines) { line.SetActive(false); } ((Selectable)_back).interactable = false; KitchenOrder kitchenOrder = _orders.FirstOrDefault((KitchenOrder o) => o.Id == _order); _heading.text = ((kitchenOrder == null) ? "Select an order" : kitchenOrder.Name); for (int num = 0; num < _steps.Count; num++) { int index = num; KitchenStep kitchenStep = _steps[num]; Card card = GetCard(_nodes, num, (Transform)(object)((ScrollRect)_tree).content); int num2 = Mathf.Min(kitchenStep.Depth, 4) * 12; Position(card.Root, num2, num * 114, 528 - num2, 104f); card.Set(Local(kitchenStep.Name), State(kitchenStep), Icon(kitchenStep.Output), Tint(kitchenStep.State), delegate { //IL_004e: 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) _detailFocus = -1; _focus = index; PaintOrderSteps(); PaintDetails(); RestlessScrollRect details = _details; Rect rect = ((ScrollRect)_details).content.rect; Size(details, ((Rect)(ref rect)).height, reset: true); }, num == _focus); card.Progress(kitchenStep); } HideAfter(_nodes, _steps.Count); Size(_tree, _steps.Count * 114, reset: false); } private void PaintPantry(bool force) { //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) ((Component)_actionHint).gameObject.SetActive(false); IReadOnlyList<KitchenPantryItem> readOnlyList = Kitchen.Pantry(_table); string text = "pantry|" + string.Join("|", readOnlyList.Select((KitchenPantryItem p) => p.Prefab + ":" + p.Count + ":" + p.Reserved)); if (!force && _stamp == text) { return; } _stamp = text; _heading.text = "Kitchen pantry"; ((Selectable)_back).interactable = false; foreach (GameObject line in _lines) { line.SetActive(false); } HideAfter(_recipeCards, 0); if (!readOnlyList.Any((KitchenPantryItem p) => p.Prefab == _pantrySelection)) { _pantrySelection = readOnlyList.FirstOrDefault()?.Prefab ?? ""; } for (int num = 0; num < readOnlyList.Count; num++) { KitchenPantryItem item = readOnlyList[num]; Card card = GetCard(_nodes, num, (Transform)(object)((ScrollRect)_tree).content); Position(card.Root, num % 2 * 276, num / 2 * 128, 252f, 116f); int num2 = Math.Max(0, item.Count - item.Reserved); card.Set(Local(item.Name), num2 + " available · " + item.Reserved + " reserved", Icon(item.Prefab), RestlessUi.Accent, delegate { _pantrySelection = item.Prefab; PaintPantry(force: true); }, item.Prefab == _pantrySelection); } HideAfter(_nodes, readOnlyList.Count); Size(_tree, (readOnlyList.Count + 1) / 2 * 128, reset: false); KitchenPantryItem kitchenPantryItem = readOnlyList.FirstOrDefault((KitchenPantryItem p) => p.Prefab == _pantrySelection); HideAfter(_requirementCards, 0); _requirementsLabel.text = ""; _station.text = ""; ShowDish(); _dish.sprite = ((kitchenPantryItem == null) ? null : Icon(kitchenPantryItem.Prefab)); ((Behaviour)_dish).enabled = (Object)(object)_dish.sprite != (Object)null; _dishFrame.SetActive(kitchenPantryItem != null); _dishName.text = ((kitchenPantryItem == null) ? "Pantry is empty" : Local(kitchenPantryItem.Name)); _dishKind.text = "Stored preparation"; ((Graphic)_dishKind).color = RestlessUi.PaperMuted; _copy.text = "Unreserved food can be collected here. Ready food reserved for active orders stays with its order."; Position(((Component)_copy).gameObject, 0f, 0f, 280f, Mathf.Max(60f, _copy.preferredHeight)); Size(_details, _copy.preferredHeight + 16f, reset: false); ((Component)_collect).gameObject.SetActive(false); ((Component)_action).gameObject.SetActive(true); ((Selectable)_action).interactable = kitchenPantryItem != null && kitchenPantryItem.Count > kitchenPantryItem.Reserved; _actionText.text = "Take a stack"; if (Time.unscaledTime >= _messageUntil) { _status.text = "Prepared food and returned ingredients · order reservations are protected"; } } private void TakePantry() { KitchenPantryItem kitchenPantryItem = Kitchen.Pantry(_table).FirstOrDefault((KitchenPantryItem p) => p.Prefab == _pantrySelection); if (kitchenPantryItem == null) { return; } ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab(kitchenPantryItem.Prefab); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } int val = ((ItemDrop)(obj?)).m_itemData?.m_shared?.m_maxStackSize ?? 1; try { Message("Collected " + Kitchen.Take(_table, kitchenPantryItem.Prefab, Math.Min(val, Math.Max(0, kitchenPantryItem.Count - kitchenPantryItem.Reserved))) + "."); PaintPantry(force: true); } catch (Exception ex) { Debug.LogException(ex); Message("Could not collect. Check your inventory before retrying."); } } } internal static class CookIcons { private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>(); private static MethodInfo? _loadImage; private static bool _searched; public static Sprite? Sprite(string id) { //IL_0050: 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) string text = id.Replace('_', '-'); if (Cache.TryGetValue(text, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Texture2D val = Texture(text); if ((Object)(object)val == (Object)null) { return null; } value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0); ((Object)value).name = text; Cache[text] = value; return value; } private static Texture2D? Texture(string key) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown Stream manifestResourceStream = typeof(CookIcons).Assembly.GetManifestResourceStream("RestlessCook.Assets." + key + ".png"); if (manifestResourceStream == null) { Plugin.Log.LogWarning((object)("cook icon missing " + key)); return null; } using (manifestResourceStream) { byte[] array = new byte[manifestResourceStream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = manifestResourceStream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); MethodInfo methodInfo = LoadImage(); if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, array })) { Object.Destroy((Object)(object)val); Plugin.Log.LogWarning((object)("cook icon decode failed " + key)); return null; } ((Object)val).name = key; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } } private static MethodInfo? LoadImage() { if (_searched) { return _loadImage; } _searched = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (!(type == null)) { _loadImage = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (_loadImage != null) { return _loadImage; } } } return null; } } internal static class CookMesh { private static readonly Dictionary<string, Mesh> Meshes = new Dictionary<string, Mesh>(); private static readonly Dictionary<string, Texture2D> Albedos = new Dictionary<string, Texture2D>(); private static string? _folder; private static MethodInfo? _loadImage; private static bool _searched; public static string Folder() { if (_folder != null) { return _folder; } string[] array = PluginRoots(); string[] array2 = array; foreach (string text in array2) { string dir = Path.Combine(text, "mesh"); if (HasRcm(dir)) { return Remember(dir); } if (HasRcm(text)) { return Remember(text); } } _folder = Path.Combine((array.Length != 0) ? array[0] : ".", "mesh"); Plugin.Log.LogWarning((object)("cook mesh folder missing, looking in " + _folder)); return _folder; } private static string[] PluginRoots() { List<string> list = new List<string>(); Plugin instance = Plugin.Instance; object obj; if (instance == null) { obj = null; } else { PluginInfo info = ((BaseUnityPlugin)instance).Info; obj = ((info != null) ? info.Location : null); } string text = (string)obj; if (!string.IsNullOrEmpty(text)) { AddRoot(list, Path.GetDirectoryName(text)); } string location = typeof(CookMesh).Assembly.Location; if (!string.IsNullOrEmpty(location)) { AddRoot(list, Path.GetDirectoryName(location)); } return list.ToArray(); } private static void AddRoot(List<string> roots, string? root) { if (string.IsNullOrEmpty(root)) { return; } foreach (string root2 in roots) { if (string.Equals(root2, root, StringComparison.OrdinalIgnoreCase)) { return; } } roots.Add(root); } private static string Remember(string dir) { _folder = dir; Plugin.Log.LogInfo((object)("cook mesh folder " + dir)); return dir; } private static bool HasRcm(string dir) { if (Directory.Exists(dir)) { return Directory.GetFiles(dir, "*.rcm").Length != 0; } return false; } public static Mesh? Mesh(string id) { string text = id.Replace('_', '-'); if (Meshes.TryGetValue(text, out Mesh value) && (Object)(object)value != (Object)null) { return value; } string path = Path.Combine(Folder(), text + ".rcm"); if (!File.Exists(path)) { Plugin.Log.LogWarning((object)("cook mesh missing " + text)); return null; } value = ReadRcm(File.ReadAllBytes(path), text); if ((Object)(object)value != (Object)null) { Meshes[text] = value; } return value; } public static Texture2D? Albedo(string id) { string text = id.Replace('_', '-'); if (Albedos.TryGetValue(text, out Texture2D value) && (Object)(object)value != (Object)null) { return value; } string path = Path.Combine(Folder(), text + ".png"); if (!File.Exists(path)) { Plugin.Log.LogWarning((object)("cook albedo missing " + text)); return null; } value = DecodePng(File.ReadAllBytes(path), text); if ((Object)(object)value != (Object)null) { Albedos[text] = value; } return value; } private static Mesh? ReadRcm(byte[] data, string name) { //IL_00ce: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown if (data.Length < 12 || data[0] != 82 || data[1] != 67 || data[2] != 77 || (data[3] != 49 && data[3] != 50)) { Plugin.Log.LogWarning((object)("cook mesh bad header " + name)); return null; } bool flag = data[3] == 49; int num = 4; int num2 = BitConverter.ToInt32(data, num); num += 4; int num3 = BitConverter.ToInt32(data, num); num += 4; if (num2 <= 0 || num3 <= 0 || num + num2 * 32 + num3 * 4 > data.Length) { Plugin.Log.LogWarning((object)("cook mesh truncated " + name)); return null; } Vector3[] array = (Vector3[])(object)new Vector3[num2]; Vector3[] array2 = (Vector3[])(object)new Vector3[num2]; Vector2[] array3 = (Vector2[])(object)new Vector2[num2]; for (int i = 0; i < num2; i++) { array[i] = new Vector3(BitConverter.ToSingle(data, num), BitConverter.ToSingle(data, num + 4), BitConverter.ToSingle(data, num + 8)); array2[i] = new Vector3(BitConverter.ToSingle(data, num + 12), BitConverter.ToSingle(data, num + 16), BitConverter.ToSingle(data, num + 20)); float num4 = BitConverter.ToSingle(data, num + 28); array3[i] = new Vector2(BitConverter.ToSingle(data, num + 24), flag ? (1f - num4) : num4); num += 32; } int[] array4 = new int[num3]; for (int j = 0; j < num3; j++) { array4[j] = BitConverter.ToInt32(data, num); num += 4; } Mesh val = new Mesh { name = name, indexFormat = (IndexFormat)(num2 > 65000) }; val.SetVertices(array); val.SetNormals(array2); val.SetUVs(0, array3); val.SetTriangles(array4, 0); val.RecalculateBounds(); return val; } private static Texture2D? DecodePng(byte[] bytes, string name) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); MethodInfo methodInfo = LoadImage(); if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, bytes })) { Object.Destroy((Object)(object)val); Plugin.Log.LogWarning((object)("cook albedo decode failed " + name)); return null; } ((Object)val).name = name; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).anisoLevel = 4; val.Apply(true, false); return val; } private static MethodInfo? LoadImage() { if (_searched) { return _loadImage; } _searched = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (!(type == null)) { _loadImage = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (_loadImage != null) { return _loadImage; } } } return null; } } public sealed class CookUse { public string Item { get; set; } = ""; public int Amount { get; set; } } public sealed class CookRow { public string Id { get; set; } = ""; public string Name { get; set; } = ""; public string Kind { get; set; } = ""; public string Source { get; set; } = ""; public string Operation { get; set; } = ""; public string Tier { get; set; } = ""; public string Prefab { get; set; } = ""; public string RecipeId { get; set; } = ""; public string CloneFrom { get; set; } = ""; public int Food { get; set; } public int FoodStamina { get; set; } public int FoodEitr { get; set; } public float FoodRegen { get; set; } public int FoodMinutes { get; set; } public List<string> Feeds { get; } = new List<string>(); public List<CookUse> Uses { get; } = new List<CookUse>(); public int OutputAmount { get; set; } = 1; public bool AnyOne { get; set; } public string Station { get; set; } = ""; public int StationLevel { get; set; } = 1; public float PreparationSeconds { get; set; } public bool IsAdd => Operation == "add"; public bool IsRewrite => Operation == "rewrite"; public bool IsReference => Operation == "reference"; public bool IsMeal => Kind == "meal"; public bool IsFeast => Kind == "feast"; public bool IsSideboard => Kind == "sideboard"; public bool IsStation => Kind == "station"; public bool IsTool => Kind == "tool"; } public sealed class CookBook { public List<CookRow> Items { get; } = new List<CookRow>(); public List<CookRow> Kit { get; } = new List<CookRow>(); } internal static class CookVisual { private const string ChildName = "RestlessCookMesh"; private const float FeastMeshScale = 3f; private static readonly Vector3 ModelScale = Vector3.one * 2.5f; public static void Apply(CustomItem item, CookRow row) { if ((Object)(object)((item != null) ? item.ItemPrefab : null) != (Object)null) { Apply(item.ItemPrefab, row); } } public static void Apply(GameObject prefab, CookRow row) { if (!((Object)(object)prefab == (Object)null)) { Mesh val = CookMesh.Mesh(row.Id); Texture2D albedo = CookMesh.Albedo(row.Id); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("RestlessCook: no custom model for '" + row.Id + "', using vanilla appearance.")); return; } GameObject val2 = FindOrCreate(prefab); (val2.GetComponent<MeshFilter>() ?? val2.AddComponent<MeshFilter>()).sharedMesh = val; MeshRenderer obj = val2.GetComponent<MeshRenderer>() ?? val2.AddComponent<MeshRenderer>(); ((Renderer)obj).enabled = true; Paint((Renderer)(object)obj, albedo, prefab); KeepPlate(prefab); } } public static void KeepPlate(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return; } Transform obj = prefab.transform.Find("RestlessCookMesh"); Renderer val = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null); if ((Object)(object)val == (Object)null) { return; } val.enabled = true; ((Component)val).gameObject.SetActive(true); Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && (val2 is MeshRenderer || val2 is SkinnedMeshRenderer)) { val2.enabled = false; } } EnsureHit(prefab); } public static void EnsureHit(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return; } Transform val = prefab.transform.Find("RestlessCookMesh"); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)prefab.GetComponent<Feast>() == (Object)null) { Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider obj in componentsInChildren) { MeshCollider val2 = (MeshCollider)(object)((obj is MeshCollider) ? obj : null); if (val2 != null) { Object.DestroyImmediate((Object)(object)val2); } } if ((Object)(object)prefab.GetComponentInChildren<Collider>(true) == (Object)null) { SitOnGround(val); } } else { DressFeast(prefab, val); } } private static void DressFeast(GameObject prefab, Transform keep) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) keep.localScale = Vector3.one * 3f; keep.localPosition = new Vector3(0f, 0.02f, 0f); FeastColliderState feastColliderState = prefab.GetComponent<FeastColliderState>() ?? prefab.AddComponent<FeastColliderState>(); if (feastColliderState.Colliders == null) { List<Collider> list = new List<Collider>(); Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform != (Object)(object)keep && !((Component)val).transform.IsChildOf(keep)) { list.Add(val); } } feastColliderState.Colliders = list.ToArray(); feastColliderState.Enabled = Array.ConvertAll(feastColliderState.Colliders, (Collider col) => col.enabled); } Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_clipGround = true; component.m_noInWater = true; component.m_cultivatedGroundOnly = false; component.m_groundOnly = false; } MeshFilter component2 = ((Component)keep).GetComponent<MeshFilter>(); if (!((Object)(object)((component2 != null) ? component2.sharedMesh : null) == (Object)null)) { MeshCollider val2 = ((Component)keep).GetComponent<MeshCollider>() ?? ((Component)keep).gameObject.AddComponent<MeshCollider>(); val2.sharedMesh = component2.sharedMesh; val2.convex = true; ZNetView component3 = prefab.GetComponent<ZNetView>(); FeastColliderState.Apply(feastColliderState.Colliders, feastColliderState.Enabled, (Collider?)(object)val2, (Object)(object)component3 != (Object)null && component3.IsValid()); } } public static void RestoreSupport(GameObject placed) { if (!((Object)(object)placed == (Object)null)) { FeastColliderState component = placed.GetComponent<FeastColliderState>(); if (component?.Colliders != null) { Transform obj = placed.transform.Find("RestlessCookMesh"); MeshCollider plate = ((obj != null) ? ((Component)obj).GetComponent<MeshCollider>() : null); FeastColliderState.Apply(component.Colliders, component.Enabled, (Collider?)(object)plate, placed: true); } } } private static void SitOnGround(Transform keep) { //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_0040: 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_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) MeshFilter component = ((Component)keep).GetComponent<MeshFilter>(); if (!((Object)(object)((component != null) ? component.sharedMesh : null) == (Object)null)) { BoxCollider obj = ((Component)keep).GetComponent<BoxCollider>() ?? ((Component)keep).gameObject.AddComponent<BoxCollider>(); Bounds bounds = component.sharedMesh.bounds; obj.center = ((Bounds)(ref bounds)).center; obj.size = Vector3.Max(((Bounds)(ref bounds)).size, new Vector3(0.08f, 0.04f, 0.08f)); ((Collider)obj).enabled = true; } } private static GameObject FindOrCreate(GameObject prefab) { //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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0028: 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_003e: Unknown result type (might be due to invalid IL or missing references) Transform val = prefab.transform.Find("RestlessCookMesh"); if ((Object)(object)val != (Object)null) { val.SetParent(prefab.transform, false); val.localPosition = Vector3.zero; val.localRotation = Quaternion.identity; val.localScale = ModelScale; ((Component)val).gameObject.layer = prefab.layer; ((Component)val).gameObject.SetActive(true); return ((Component)val).gameObject; } GameObject val2 = new GameObject("RestlessCookMesh") { layer = prefab.layer }; val2.transform.SetParent(prefab.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = ModelScale; return val2; } private static void Paint(Renderer renderer, Texture2D? albedo, GameObject prefab) { //IL_0012: 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) //IL_0032: 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) Material val = CopyLit(prefab); if ((Object)(object)val == (Object)null) { return; } val.color = Color.white; SetColor(val, "_Color", Color.white); SetColor(val, "_BaseColor", Color.white); SetColor(val, "_Tint", Color.white); SetFloat(val, "_Metallic", 0f); SetFloat(val, "_Glossiness", 0.12f); SetFloat(val, "_Smoothness", 0.12f); SetFloat(val, "_GlossMapScale", 0.12f); MuteGlow(val); if ((Object)(object)albedo != (Object)null) { if (val.HasProperty("_MainTex")) { val.SetTexture("_MainTex", (Texture)(object)albedo); } if (val.HasProperty("_BaseMap")) { val.SetTexture("_BaseMap", (Texture)(object)albedo); } if (val.HasProperty("_Diffuse")) { val.SetTexture("_Diffuse", (Texture)(object)albedo); } } renderer.sharedMaterial = val; } private static Material? CopyLit(GameObject prefab) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown Material val = QuietMat(prefab) ?? QuietFeast(); if ((Object)(object)val != (Object)null) { return new Material(val); } Shader val2 = Shader.Find("Standard") ?? Shader.Find("Diffuse") ?? Shader.Find("Legacy Shaders/Diffuse"); if (!((Object)(object)val2 != (Object)null)) { return null; } return new Material(val2); } private static Material? QuietFeast() { string[] array = new string[2] { "FeastMeadows", "FeastBlackforest" }; foreach (string text in array) { PrefabManager instance = PrefabManager.Instance; Material val = QuietMat((instance != null) ? instance.GetPrefab(text) : null); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Material? QuietMat(GameObject? prefab) { if ((Object)(object)prefab == (Object)null) { return null; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).transform).name == "RestlessCookMesh") && val is MeshRenderer && !Garnish(((Component)val).transform)) { Material sharedMaterial = val.sharedMaterial; if (!((Object)(object)((sharedMaterial != null) ? sharedMaterial.shader : null) == (Object)null) && !Glows(sharedMaterial)) { return sharedMaterial; } } } return null; } private static bool Garnish(Transform node) { Transform val = node; while ((Object)(object)val != (Object)null) { string name = ((Object)val).name; if (Has(name, "thistle") || Has(name, "spice") || Has(name, "eitr") || Has(name, "glow") || Has(name, "garnish") || Has(name, "magecap") || Has(name, "jotun") || Has(name, "wisp") || Has(name, "mist")) { return true; } val = val.parent; } return false; } private static bool Glows(Material mat) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) string text = ((Object)mat).name + " " + ((Object)mat.shader).name; if (Has(text, "thistle") || Has(text, "spice") || Has(text, "eitr") || Has(text, "glow")) { return true; } if (mat.IsKeywordEnabled("_EMISSION") || mat.IsKeywordEnabled("EMISSION")) { return true; } if (mat.HasProperty("_EmissionMap") && (Object)(object)mat.GetTexture("_EmissionMap") != (Object)null) { return true; } if (mat.HasProperty("_EmissionColorMap") && (Object)(object)mat.GetTexture("_EmissionColorMap") != (Object)null) { return true; } Color color; if (mat.HasProperty("_EmissionColor")) { color = mat.GetColor("_EmissionColor"); if (((Color)(ref color)).maxColorComponent > 0.02f) { return true; } } if (mat.HasProperty("_EmissiveColor")) { color = mat.GetColor("_EmissiveColor"); if (((Color)(ref color)).maxColorComponent > 0.02f) { return true; } } if (mat.HasProperty("_EnableEmission") && mat.GetFloat("_EnableEmission") > 0.5f) { return true; } return false; } private static void MuteGlow(Material mat) { //IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references) SetColor(mat, "_EmissionColor", Color.black); SetColor(mat, "_EmissiveColor", Color.black); SetColor(mat, "_GlowColor", Color.black); SetFloat(mat, "_EnableEmission", 0f); SetFloat(mat, "_EmissionIntensity", 0f); if (mat.HasProperty("_EmissionMap")) { mat.SetTexture("_EmissionMap", (Texture)null); } if (mat.HasProperty("_EmissionColorMap")) { mat.SetTexture("_EmissionColorMap", (Texture)null); } mat.DisableKeyword("_EMISSION"); mat.DisableKeyword("EMISSION"); } private static bool Has(string text, string token) { return text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; } private static void SetColor(Material mat, string prop, Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(prop)) { mat.SetColor(prop, color); } } private static void SetFloat(Material mat, string prop, float value) { if (mat.HasProperty(prop)) { mat.SetFloat(prop, value); } } } public static class CookYaml { public static CookBook LoadEmbedded() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("RestlessCook.cook.yaml") ?? throw new InvalidOperationException("Missing embedded cook.yaml"); using StreamReader streamReader = new StreamReader(stream); return Parse(streamReader.ReadToEnd()); } public static CookBook Parse(string text) { CookBook book = new CookBook(); CookRow cur = null; CookUse cookUse = null; string text2 = null; string section = null; string[] array = text.Split(new string[2] { "\r\n", "\n" }, StringSplitOptions.None); for (int i = 0; i < array.Length; i++) { string text3 = array[i].TrimEnd(Array.Empty<char>()); if (text3 == "kit:" || text3 == "items:") { Flush(); section = text3.TrimEnd(new char[1] { ':' }); cookUse = null; text2 = null; } else { if (section == null) { continue; } if (text3.StartsWith(" - id:", StringComparison.Ordinal)) { Flush(); cur = new CookRow { Id = Value(text3) }; cookUse = null; text2 = null; } else { if (cur == null) { continue; } if (text3.StartsWith(" feeds:", StringComparison.Ordinal)) { text2 = "feeds"; if (text3.Contains("[]")) { text2 = null; } } else if (text3.StartsWith(" uses:", StringComparison.Ordinal)) { text2 = "uses"; } else if (text2 == "feeds" && text3.StartsWith(" - ", StringComparison.Ordinal)) { cur.Feeds.Add(text3.Substring(text3.IndexOf('-') + 1).Trim()); } else if (text2 == "uses" && text3.StartsWith(" - item:", StringComparison.Ordinal)) { cookUse = new CookUse { Item = Value(text3) }; cur.Uses.Add(cookUse); } else if (text2 == "uses" && cookUse != null && text3.StartsWith(" amount:", StringComparison.Ordinal)) { cookUse.Amount = int.Parse(Value(text3)); } else if (text3.StartsWith(" ", StringComparison.Ordinal) && text3.Contains(":") && !text3.StartsWith(" ", StringComparison.Ordinal)) { text2 = null; int num = text3.IndexOf(':'); string text4 = text3.Substring(0, num).Trim(); string text5 = Unquote(text3.Substring(num + 1).Trim()); switch (text4) { case "name": cur.Name = text5; break; case "kind": cur.Kind = text5; break; case "source": cur.Source = text5; break; case "operation": cur.Operation = text5; break; case "tier": cur.Tier = text5; break; case "prefab": cur.Prefab = text5; break; case "recipe_id": cur.RecipeId = text5; break; case "clone_from": cur.CloneFrom = text5; break; case "food": cur.Food = int.Parse(text5); break; case "food_stamina": cur.FoodStamina = int.Parse(text5); break; case "food_eitr": cur.FoodEitr = int.Parse(text5); break; case "food_regen": cur.FoodRegen = float.Parse(text5, CultureInfo.InvariantCulture); break; case "food_minutes": cur.FoodMinutes = int.Parse(text5); break; case "output_amount": cur.OutputAmount = int.Parse(text5); break; case "station": cur.Station = text5; break; case "station_level": cur.StationLevel = int.Parse(text5); break; case "preparation_seconds": cur.PreparationSeconds = float.Parse(text5, CultureInfo.InvariantCulture); break; } } } } } Flush(); Validate(book.Items); ValidateKit(book.Kit); return book; void Flush() { if (cur != null) { if (section == "kit") { book.Kit.Add(cur); } else if (section == "items") { book.Items.Add(cur); } cur = null; } } } public static void Validate(IReadOnlyList<CookRow> items) { if (items.Count != 81) { throw new InvalidOperationException($"cook.yaml must have 81 rows, got {items.Count}"); } HashSet<string> hashSet = new HashSet<string>(items.Select((CookRow i) => i.Id), StringComparer.Ordinal); if (hashSet.Count != 81) { throw new InvalidOperationException("cook.yaml has duplicate ids"); } foreach (CookRow item in items) { if (item.PreparationSeconds < 0f || float.IsNaN(item.PreparationSeconds) || float.IsInfinity(item.PreparationSeconds)) { throw new InvalidOperationException(item.Id + ": invalid preparation_seconds"); } if (item.Uses.Count == 0) { throw new InvalidOperationException(item.Id + ": empty uses[]"); } foreach (string feed in item.Feeds) { if (!hashSet.Contains(feed)) { throw new InvalidOperationException(item.Id + ": feeds unknown id " + feed); } } } Require(Count((CookRow i) => i.IsAdd) == 35, "35 add rows"); Require(Count((CookRow i) => i.IsRewrite) == 16, "16 rewrite rows"); Require(Count((CookRow i) => i.IsReference) == 30, "30 reference rows"); Require(Count((CookRow i) => i.IsAdd || i.IsRewrite) == 51, "51 recipe operations"); Require(Count((CookRow i) => i.IsMeal && i.Source == "custom" && i.IsAdd) == 17, "17 custom meals"); Require(Count((CookRow i) => i.IsFeast && i.Source == "custom" && i.IsAdd) == 16, "16 custom feasts"); Require(Count((CookRow i) => i.IsSideboard && i.IsAdd) == 2, "2 sideboards"); Require(Count((CookRow i) => i.IsMeal && i.IsRewrite) == 14, "14 cooked-first rewrites"); Require(Count((CookRow i) => i.IsFeast && i.IsRewrite) == 2, "2 feast reroutes"); Require(Count((CookRow i) => i.IsMeal && i.IsReference) == 24, "24 meal references"); Require(Count((CookRow i) => i.IsFeast && i.IsReference) == 6, "6 feast references"); foreach (CookRow item2 in items.Where((CookRow i) => i.IsAdd)) { if (string.IsNullOrEmpty(item2.CloneFrom)) { throw new InvalidOperationException(item2.Id + ": add requires clone_from"); } if (string.IsNullOrEmpty(item2.Prefab)) { throw new InvalidOperationException(item2.Id + ": add requires prefab"); } } foreach (CookRow item3 in items.Where((CookRow i) => i.IsAdd && (i.IsMeal || i.IsFeast))) { if (item3.Food == 0 && item3.FoodStamina == 0 && item3.FoodEitr == 0) { throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food stats"); } if (item3.FoodMinutes <= 0) { throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food_minutes"); } if (item3.FoodRegen <= 0f) { throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food_regen"); } } foreach (CookRow item4 in items.Where((CookRow i) => i.IsSideboard)) { if (item4.Food != 0 || item4.FoodStamina != 0 || item4.FoodEitr != 0 || item4.FoodMinutes != 0) { throw new InvalidOperationException(item4.Id + ": sideboard is not edible"); } } foreach (CookRow item5 in items.Where((CookRow i) => i.IsRewrite)) { if (string.IsNullOrEmpty(item5.RecipeId)) { throw new InvalidOperationException(item5.Id + ": rewrite requires recipe_id"); } } Dictionary<string, CookRow> byId = items.ToDictionary<CookRow, string>((CookRow i) => i.Id, StringComparer.Ordinal); foreach (CookRow item6 in items.Where((CookRow i) => i.IsMeal)) { if (!ReachesFeast(item6, byId)) { throw new InvalidOperationException(item6.Id + ": meal has no path to a feast"); } } foreach (CookRow item7 in items.Where((CookRow i) => i.IsFeast && i.Source == "custom" && i.IsAdd && (i.Tier == "meadows" || i.Tier == "blackforest"))) { if (item7.Uses.Any((CookUse u) => u.Item == "SpiceForests")) { throw new InvalidOperationException(item7.Id + ": early custom feast cannot require Bog Witch spices"); } } int Count(Func<CookRow, bool> pred) { return items.Count(pred); } } private static void ValidateKit(IReadOnlyList<CookRow> kit) { if (kit.Count != 2) { throw new InvalidOperationException($"cook.yaml kit must have 2 rows, got {kit.Count}"); } CookRow cookRow = kit.FirstOrDefault((CookRow i) => i.Id == "food_preparation_table"); CookRow cookRow2 = kit.FirstOrDefault((CookRow i) => i.Id == "serving_tray"); if (cookRow == null || !cookRow.IsStation || !cookRow.IsRewrite || cookRow.Prefab != "piece_preptable" || cookRow.Uses.Count == 0) { throw new InvalidOperationException("kit: food_preparation_table must rewrite piece_preptable"); } if (cookRow2 == null || !cookRow2.IsTool || !cookRow2.IsAdd || cookRow2.Prefab != "Feaster" || cookRow2.Uses.Count == 0) { throw new InvalidOperationException("kit: serving_tray must add a Feaster recipe"); } } private static bool ReachesFeast(CookRow start, IReadOnlyDictionary<string, CookRow> byId) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Stack<string> stack = new Stack<string>(); stack.Push(start.Id); while (stack.Count > 0) { string text = stack.Pop(); if (!hashSet.Add(text) || !byId.TryGetValue(text, out CookRow value)) { continue; } if (value.IsFeast && text != start.Id) { return true; } foreach (string feed in value.Feeds) { stack.Push(feed); } } return start.IsFeast; } private static void Require(bool ok, string label) { if (!ok) { throw new InvalidOperationException("cook.yaml failed check: " + label); } } private static string Value(string line) { int num = line.IndexOf(':'); return Unquote(line.Substring(num + 1).Trim()); } private static string Unquote(string val) { if (val.Length >= 2 && ((val[0] == '"' && val[val.Length - 1] == '"') || (val[0] == '\'' && val[val.Length - 1] == '\''))) { return val.Substring(1, val.Length - 2); } return val; } } internal sealed class FeastColliderState : MonoBehaviour { public Collider[]? Colliders; public bool[] Enabled = Array.Empty<bool>(); internal static void Apply(Collider[] colliders, bool[] enabled, Collider? plate, bool placed) { for (int i = 0; i < colliders.Length; i++) { if ((Object)(object)colliders[i] != (Object)null) { colliders[i].enabled = placed && i < enabled.Length && enabled[i]; } } if ((Object)(object)plate != (Object)null) { plate.enabled = !placed; } } } public static class Kitchen { public static IReadOnlyList<CookRow> Rows => KitchenRun.Rows; public static event Action<CraftingStation>? Opened; public static void Load(CookBook book) { KitchenRun.Load(book); } public static CookRow? Find(string idOrPrefab) { return KitchenRun.Find(idOrPrefab); } public static IReadOnlyList<CookRow> OtherUses(string prefab) { return KitchenRun.OtherUses(prefab); } public static IReadOnlyList<KitchenStep> Plan(CraftingStation table, string idOrPrefab, int count) { return KitchenRun.Plan(table, idOrPrefab, count); } public static IReadOnlyList<KitchenOrder> Orders(CraftingStation table) { return KitchenRun.ReadOrders(table); } public static IReadOnlyList<KitchenStationInfo> Stations(CraftingStation table) { return KitchenRun.Describe(table); } public static IReadOnlyList<KitchenStep> Live(CraftingStation table, int orderId) { return KitchenRun.Live(table, orderId); } public static bool Place(CraftingStation table, string idOrPrefab, int count) { return KitchenRun.Place(table, idOrPrefab, count); } public static void Cancel(CraftingStation table, int orderId) { KitchenRun.Cancel(table, orderId); } public static int Collect(CraftingStation table, int orderId) { return KitchenRun.Collect(table, orderId); } public static IReadOnlyList<KitchenPantryItem> Pantry(CraftingStation table) { return KitchenRun.Pantry(table); } public static int Take(CraftingStation table, string prefab, int count) { return KitchenRun.Take(table, prefab, count); } internal static void Raise(CraftingStation table) { if (Kitchen.Opened != null) { Kitchen.Opened(table); return; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Kitchen board is not in yet.", 0, (Sprite)null, false); } } } public enum KitchenStationKind { None, Cauldron, PrepTable, Rack, Oven, MeadKettle, Fermenter } public enum KitchenStepState { Prepared, Ready, Queued, Cooking, Missing, Blocked } public sealed class KitchenUse { public string Item = ""; public string Name = ""; public int Amount; public int Have; internal int UnitAmount; } public sealed class KitchenStep { public string Id = ""; public string Name = ""; public string Output = ""; public string Parent = ""; public int Depth; public int Need; public int Have; public int Available; public int Cooking; internal bool CoveredByParent; public KitchenStepState State; public KitchenStationKind Station; public string StationPrefab = ""; public int StationLevel = 1; public string Note = ""; public int ParentIndex = -1; public float ElapsedSeconds; public float DurationSeconds; public string ActiveStation = ""; public readonly List<KitchenUse> Uses = new List<KitchenUse>(); } public sealed class KitchenOrder { public int Id; public string Feast = ""; public string Name = ""; public int Count; public long PlayerId; public int Ready; public int Collected; } public sealed class KitchenPantryItem { public string Prefab = ""; public string Name = ""; public int Count; public int Reserved; } public sealed class KitchenStationInfo { public string Id = ""; public float Distance; public string Name = ""; public KitchenStationKind Kind; public int Free; public int Cooking; public int Ready; public int Fuel; public int FuelMax; public bool NeedsFire; public bool FireLit = true; public int Level; public string Block = ""; } internal static class KitchenRun { private sealed class Conversion { public string From = ""; public KitchenStationKind Kind; public int Amount = 1; } private sealed class Ledger { public int NextOrder; public readonly Dictionary<string, int> Pantry = new Dictionary<string, int>(StringComparer.Ordinal); public readonly List<KitchenOrder> Orders = new List<KitchenOrder>(); public readonly List<Work> Work = new List<Work>(); public readonl