Decompiled source of Custom Recept v2.2.1

CustomRecipes.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 CustomRecipes
{
	[BepInPlugin("user.valheim.customrecipes", "Custom Recipes", "2.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class CustomRecipesPlugin : BaseUnityPlugin
	{
		private class Ing
		{
			public string Name = "";

			public int Amount = 1;

			public int PerLevel = 0;
		}

		private class RecipeDef
		{
			public bool Enabled = true;

			public string Item = "";

			public int Amount = 1;

			public string Station = "forge";

			public int MinLevel = 1;

			public bool Replace = false;

			public List<Ing> Ings = new List<Ing>();

			public bool Expanded = false;
		}

		private class ItemEntry
		{
			public string Prefab;

			public string Display;

			public string Search;

			public Sprite Icon;
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Postfix()
			{
				Apply();
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB_Patch
		{
			private static void Postfix()
			{
				Apply();
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class Player_OnSpawned_Patch
		{
			private static void Postfix()
			{
				DiscoverMaterials();
				RefreshUi();
			}
		}

		public enum LangSetting
		{
			Auto,
			English,
			Russian,
			Ukrainian
		}

		private enum Lang
		{
			English,
			Russian,
			Ukrainian
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static EventHandler <0>__OnRecipesChanged;

			public static Action<long, string> <1>__RPC_Submit;

			public static Action<long, string> <2>__RPC_Apply;

			public static WindowFunction <3>__DrawWindow;

			public static Action <4>__CycleLanguage;

			public static Action <5>__LoadWorking;

			public static Action <6>__Save;
		}

		public const string Guid = "user.valheim.customrecipes";

		public const string ModName = "Custom Recipes";

		public const string Version = "2.2.0";

		private static readonly string[][] StationPresets = new string[8][]
		{
			new string[2] { "none", "Руки" },
			new string[2] { "workbench", "Верстак" },
			new string[2] { "forge", "Кузница" },
			new string[2] { "cauldron", "Котёл" },
			new string[2] { "artisan", "Ремесленник" },
			new string[2] { "stonecutter", "Камнерез" },
			new string[2] { "blackforge", "Чёрная кузница" },
			new string[2] { "magetable", "Стол мага" }
		};

		private static ConfigEntry<string> RecipesData;

		private static ConfigEntry<KeyboardShortcut> MenuKey;

		private static ConfigEntry<float> UiScale;

		private static ConfigEntry<bool> AutoDiscover;

		private static ConfigEntry<LangSetting> LanguageSetting;

		private static ManualLogSource Log;

		private static readonly List<Recipe> AddedRecipes = new List<Recipe>();

		private static readonly List<Recipe> RemovedOriginals = new List<Recipe>();

		private static ObjectDB lastDb;

		private static string lastAppliedData;

		private static string overrideData;

		private const string RpcSubmit = "CustomRecept_Submit";

		private const string RpcApply = "CustomRecept_Apply";

		private static float pollTimer;

		private static bool refreshWarned;

		private static List<string> status = new List<string>();

		private static bool MenuOpen;

		private static Rect windowRect = new Rect(0f, 0f, 0f, 0f);

		private static Vector2 scroll;

		private static List<RecipeDef> working = new List<RecipeDef>();

		private static bool dirty;

		private static readonly Queue<Action> pending = new Queue<Action>();

		private static string activeField;

		private static string suggKey;

		private static string suggText;

		private static List<ItemEntry> suggList = new List<ItemEntry>();

		private static readonly Dictionary<string, string> rawInts = new Dictionary<string, string>();

		private static List<ItemEntry> itemIndex;

		private static Dictionary<string, ItemEntry> itemByPrefab;

		private static ObjectDB indexDb;

		private const int WindowId = 7771234;

		private static bool locResolved;

		private static PropertyInfo locProp;

		private static FieldInfo locField;

		private static MethodInfo locLocalize;

		private static bool adminCheckWarned;

		private static Lang curLang = Lang.English;

		private static readonly Dictionary<string, string[]> Tr = new Dictionary<string, string[]>
		{
			{
				"title",
				new string[3] { "RECIPES", "РЕЦЕПТЫ", "РЕЦЕПТИ" }
			},
			{
				"new_recipe",
				new string[3] { "+ New recipe", "+ Новый рецепт", "+ Новий рецепт" }
			},
			{
				"collapse_all",
				new string[3] { "Collapse all", "Свернуть все", "Згорнути все" }
			},
			{
				"revert",
				new string[3] { "Revert changes", "Отменить правки", "Скасувати зміни" }
			},
			{
				"save",
				new string[3] { "Save and apply", "Сохранить и применить", "Зберегти та застосувати" }
			},
			{
				"close",
				new string[3] { "Close", "Закрыть", "Закрити" }
			},
			{
				"lang",
				new string[3] { "Language: {0}", "Язык: {0}", "Мова: {0}" }
			},
			{
				"hint_edit",
				new string[3] { "Click a card to edit it. Start typing an item name (game language or English) and pick it from the list with pictures. After saving, recipes are sent to all players on the server at once.", "Нажми на карточку, чтобы править. Начни вводить название предмета (на языке игры или по-английски) и выбери его из списка с картинками. После сохранения рецепты сразу приходят всем игрокам сервера.", "Натисни на картку, щоб редагувати. Почни вводити назву предмета (мовою гри або англійською) і вибери його зі списку з картинками. Після збереження рецепти одразу надходять усім гравцям сервера." }
			},
			{
				"hint_noadmin",
				new string[3] { "You are not a server admin - recipes are read-only. Only an admin can change them.", "Ты не админ сервера — рецепты можно только смотреть. Менять их может админ.", "Ти не адмін сервера — рецепти можна лише переглядати. Змінювати їх може адмін." }
			},
			{
				"empty_list",
				new string[3] { "No recipes yet. Press \"+ New recipe\".", "Рецептов пока нет. Нажми «+ Новый рецепт».", "Рецептів поки немає. Натисни «+ Новий рецепт»." }
			},
			{
				"new_title",
				new string[3] { "New recipe - choose an item", "Новый рецепт — выбери предмет", "Новий рецепт — вибери предмет" }
			},
			{
				"level_word",
				new string[3] { "level", "уровень", "рівень" }
			},
			{
				"click_collapse",
				new string[3] { "click to collapse", "нажми, чтобы свернуть", "натисни, щоб згорнути" }
			},
			{
				"click_edit",
				new string[3] { "click to edit", "нажми, чтобы править", "натисни, щоб редагувати" }
			},
			{
				"stat_off",
				new string[3] { "disabled", "выключен", "вимкнено" }
			},
			{
				"stat_ok",
				new string[3] { "working", "работает", "працює" }
			},
			{
				"stat_unsaved",
				new string[3] { "not saved", "не сохранён", "не збережено" }
			},
			{
				"on",
				new string[3] { "ON", "ВКЛ", "УВІМК" }
			},
			{
				"off",
				new string[3] { "OFF", "ВЫКЛ", "ВИМК" }
			},
			{
				"yes",
				new string[3] { "YES", "ДА", "ТАК" }
			},
			{
				"no",
				new string[3] { "NO", "НЕТ", "НІ" }
			},
			{
				"sec_what",
				new string[3] { "WHAT TO CRAFT", "ЧТО КРАФТИМ", "ЩО КРАФТИМО" }
			},
			{
				"sec_where",
				new string[3] { "WHERE TO CRAFT", "ГДЕ КРАФТИМ", "ДЕ КРАФТИМО" }
			},
			{
				"sec_from",
				new string[3] { "INGREDIENTS", "ИЗ ЧЕГО КРАФТИМ", "З ЧОГО КРАФТИМО" }
			},
			{
				"lbl_amount",
				new string[3] { "Amount per craft:", "Сколько за раз:", "Скільки за раз:" }
			},
			{
				"lbl_custom_station",
				new string[3] { "Station from another mod:", "Станция из другого мода:", "Станція з іншого моду:" }
			},
			{
				"lbl_level",
				new string[3] { "Station level:", "Уровень станции:", "Рівень станції:" }
			},
			{
				"lbl_replace",
				new string[3] { "Remove the original recipes of this item: {0}", "Убрать оригинальные рецепты этого предмета: {0}", "Прибрати оригінальні рецепти цього предмета: {0}" }
			},
			{
				"lbl_pcs",
				new string[3] { "Qty:", "Штук:", "Штук:" }
			},
			{
				"lbl_perlevel",
				new string[3] { "+/lvl:", "+за ур.:", "+за рів.:" }
			},
			{
				"add_ing",
				new string[3] { "+ Ingredient", "+ Ингредиент", "+ Інгредієнт" }
			},
			{
				"hint_perlevel",
				new string[3] { "\"+/lvl\" - extra cost for each item upgrade level (usually 0).", "«+за ур.» — сколько добавлять к цене за каждый уровень улучшения (обычно 0).", "«+за рів.» — скільки додавати до ціни за кожен рівень покращення (зазвичай 0)." }
			},
			{
				"copy",
				new string[3] { "Copy", "Копия", "Копія" }
			},
			{
				"up",
				new string[3] { "Up", "Вверх", "Вгору" }
			},
			{
				"down",
				new string[3] { "Down", "Вниз", "Вниз" }
			},
			{
				"delete",
				new string[3] { "Delete", "Удалить", "Видалити" }
			},
			{
				"no_such_item",
				new string[3] { "no such item", "такого предмета нет", "такого предмета немає" }
			},
			{
				"nothing_found",
				new string[3] { "Nothing found", "Ничего не найдено", "Нічого не знайдено" }
			},
			{
				"st_none",
				new string[3] { "Hands", "Руки", "Руки" }
			},
			{
				"st_workbench",
				new string[3] { "Workbench", "Верстак", "Верстак" }
			},
			{
				"st_forge",
				new string[3] { "Forge", "Кузница", "Кузня" }
			},
			{
				"st_cauldron",
				new string[3] { "Cauldron", "Котёл", "Казан" }
			},
			{
				"st_artisan",
				new string[3] { "Artisan table", "Ремесленник", "Ремісник" }
			},
			{
				"st_stonecutter",
				new string[3] { "Stonecutter", "Камнерез", "Каменяр" }
			},
			{
				"st_blackforge",
				new string[3] { "Black forge", "Чёрная кузница", "Чорна кузня" }
			},
			{
				"st_magetable",
				new string[3] { "Mage table", "Стол мага", "Стіл мага" }
			},
			{
				"err_no_item",
				new string[3] { "no item selected", "не выбран предмет", "не вибрано предмет" }
			},
			{
				"err_item",
				new string[3] { "item '{0}' not found", "предмет '{0}' не найден", "предмет '{0}' не знайдено" }
			},
			{
				"err_station",
				new string[3] { "station '{0}' not found", "станция '{0}' не найдена", "станцію '{0}' не знайдено" }
			},
			{
				"err_ing",
				new string[3] { "ingredient '{0}' not found", "ингредиент '{0}' не найден", "інгредієнт '{0}' не знайдено" }
			},
			{
				"err_no_ings",
				new string[3] { "no ingredients", "нет ингредиентов", "немає інгредієнтів" }
			}
		};

		private static readonly Color GoldColor = new Color(0.8f, 0.66f, 0.4f);

		private static readonly Color GoldDim = new Color(0.5f, 0.41f, 0.26f);

		private static readonly Color TextColor = new Color(0.9f, 0.84f, 0.7f);

		private static readonly Color TextDimColor = new Color(0.62f, 0.57f, 0.47f);

		private static readonly Color GreenColor = new Color(0.5f, 0.88f, 0.52f);

		private static readonly Color RedColor = new Color(0.96f, 0.47f, 0.42f);

		private static GUISkin skin;

		private static GUIStyle windowStyle;

		private static GUIStyle cardStyle;

		private static GUIStyle slotStyle;

		private static GUIStyle slotGoldStyle;

		private static GUIStyle buttonStyle;

		private static GUIStyle primaryStyle;

		private static GUIStyle dangerStyle;

		private static GUIStyle chipOnStyle;

		private static GUIStyle flatStyle;

		private static GUIStyle cardBtnStyle;

		private static GUIStyle fieldStyle;

		private static GUIStyle greenLabel;

		private static GUIStyle redLabel;

		private static GUIStyle grayLabel;

		private static GUIStyle boldLabel;

		private static GUIStyle hintLabel;

		private static GUIStyle headStyle;

		private static GUIStyle titleStyle;

		private static GUIStyle badgeStyle;

		private static GUIStyle badgeShadowStyle;

		private static GUIStyle cardTextStyle;

		private static GUIStyle centerLabel;

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "MenuHotkey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Key that opens and closes the recipe menu.");
			UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "UiScale", 1f, new ConfigDescription("Menu size (increase it if everything looks small on a big monitor).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 3f), Array.Empty<object>()));
			LanguageSetting = ((BaseUnityPlugin)this).Config.Bind<LangSetting>("General", "Language", LangSetting.Auto, "Menu language: Auto (follows the game language), English, Russian or Ukrainian. You can also switch it with the language button inside the menu.");
			LanguageSetting.SettingChanged += delegate
			{
				RefreshLang();
			};
			RefreshLang();
			AutoDiscover = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoDiscoverIngredients", true, "Treat the ingredients of custom recipes as already discovered. Without this the game hides a recipe until you have picked up every ingredient at least once.");
			RecipesData = ((BaseUnityPlugin)this).Config.Bind<string>("Recipes", "RecipesData", "", new ConfigDescription("All recipes in one line. Do not edit by hand - use the menu.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Browsable = false
			} }));
			RecipesData.SettingChanged += OnRecipesChanged;
			working = Parse(RecipesData.Value);
			Harmony val = new Harmony("user.valheim.customrecipes");
			val.PatchAll(typeof(CustomRecipesPlugin).Assembly);
			PatchInputBlockers(val);
		}

		private static string CurrentData()
		{
			return overrideData ?? RecipesData.Value;
		}

		private static void OnRecipesChanged(object sender, EventArgs e)
		{
			overrideData = null;
			ApplyAll();
		}

		private static void ApplyAll()
		{
			Apply();
			DiscoverMaterials();
			RefreshUi();
			if (!dirty)
			{
				LoadWorking();
			}
		}

		private static void PatchInputBlockers(Harmony h)
		{
			TryPatch(h, typeof(TextInput), "IsVisible", null, "TextInputPostfix");
			TryPatch(h, typeof(Player), "TakeInput", null, "TakeInputPostfix");
			TryPatch(h, typeof(GameCamera), "UpdateMouseCapture", "MouseCapturePrefix", null);
			TryPatch(h, typeof(ZNet), "Awake", null, "ZNetAwakePostfix");
			TryPatch(h, typeof(ZNet), "OnDestroy", null, "ZNetDestroyPostfix");
		}

		private static void TryPatch(Harmony h, Type type, string method, string prefix, string postfix)
		{
			//IL_006e: 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)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Log.LogWarning((object)("Method " + type.Name + "." + method + " not found (input blocking may work worse)."));
				}
				else
				{
					Type typeFromHandle = typeof(CustomRecipesPlugin);
					h.Patch((MethodBase)methodInfo, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeFromHandle, prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeFromHandle, postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not patch " + type.Name + "." + method + ": " + ex.Message));
			}
		}

		private static void TextInputPostfix(ref bool __result)
		{
			if (MenuOpen)
			{
				__result = true;
			}
		}

		private static void TakeInputPostfix(ref bool __result)
		{
			if (MenuOpen)
			{
				__result = false;
			}
		}

		private static bool MouseCapturePrefix()
		{
			if (!MenuOpen)
			{
				return true;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			return false;
		}

		private void Update()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			pollTimer += Time.unscaledDeltaTime;
			if (pollTimer >= 0.5f)
			{
				pollTimer = 0f;
				ObjectDB instance = ObjectDB.instance;
				if ((Object)(object)instance != (Object)null && instance.m_items != null && instance.m_items.Count > 0 && CurrentData() != lastAppliedData)
				{
					ApplyAll();
				}
			}
			KeyboardShortcut value = MenuKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				if (MenuOpen)
				{
					CloseMenu();
				}
				else if ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus())
				{
					OpenMenu();
				}
			}
			else if (MenuOpen && Input.GetKeyDown((KeyCode)27))
			{
				CloseMenu();
			}
		}

		private void LateUpdate()
		{
			if (MenuOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private static void OpenMenu()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			RefreshLang();
			if (!dirty)
			{
				LoadWorking();
			}
			float num = Mathf.Max(0.1f, UiScale.Value);
			float num2 = Mathf.Min(1120f, (float)Screen.width / num - 20f);
			float num3 = Mathf.Min(800f, (float)Screen.height / num - 40f);
			windowRect = new Rect(((float)Screen.width / num - num2) / 2f, ((float)Screen.height / num - num3) / 2f, num2, num3);
			pending.Clear();
			activeField = null;
			suggKey = null;
			suggList = new List<ItemEntry>();
			MenuOpen = true;
		}

		private static void CloseMenu()
		{
			MenuOpen = false;
			activeField = null;
			GUI.FocusControl("");
		}

		private static void LoadWorking()
		{
			List<RecipeDef> list = working;
			List<RecipeDef> list2 = Parse(CurrentData());
			if (list != null)
			{
				for (int i = 0; i < list2.Count && i < list.Count; i++)
				{
					list2[i].Expanded = list[i].Expanded;
				}
			}
			working = list2;
			dirty = false;
			rawInts.Clear();
		}

		private static bool CanEdit()
		{
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return true;
				}
				if (ZNet.instance.IsServer())
				{
					return true;
				}
				return SynchronizationManager.Instance.PlayerIsAdmin;
			}
			catch
			{
				return true;
			}
		}

		private static string Clean(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return "";
			}
			return new string(s.Where((char c) => !char.IsWhiteSpace(c) && "|#,:;".IndexOf(c) < 0).ToArray());
		}

		private static int ParseInt(string s, int fallback)
		{
			int result;
			return int.TryParse(s, out result) ? result : fallback;
		}

		private static string Serialize(List<RecipeDef> list)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < list.Count; i++)
			{
				RecipeDef recipeDef = list[i];
				if (i > 0)
				{
					stringBuilder.Append('#');
				}
				stringBuilder.Append(recipeDef.Enabled ? 1 : 0).Append('|');
				stringBuilder.Append(Clean(recipeDef.Item)).Append('|');
				stringBuilder.Append(recipeDef.Amount).Append('|');
				stringBuilder.Append(Clean(recipeDef.Station)).Append('|');
				stringBuilder.Append(recipeDef.MinLevel).Append('|');
				stringBuilder.Append(recipeDef.Replace ? 1 : 0).Append('|');
				stringBuilder.Append(string.Join(",", (from g in recipeDef.Ings
					where !string.IsNullOrEmpty(Clean(g.Name))
					select Clean(g.Name) + ":" + g.Amount + ":" + g.PerLevel).ToArray()));
			}
			return stringBuilder.ToString();
		}

		private static List<RecipeDef> Parse(string data)
		{
			List<RecipeDef> list = new List<RecipeDef>();
			if (string.IsNullOrWhiteSpace(data))
			{
				return list;
			}
			string[] array = data.Split(new char[1] { '#' });
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { '|' });
				if (array2.Length >= 7)
				{
					RecipeDef recipeDef = new RecipeDef
					{
						Enabled = (array2[0] == "1"),
						Item = array2[1],
						Amount = Mathf.Clamp(ParseInt(array2[2], 1), 1, 999),
						Station = array2[3],
						MinLevel = Mathf.Clamp(ParseInt(array2[4], 1), 1, 10),
						Replace = (array2[5] == "1")
					};
					string[] array3 = array2[6].Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
					foreach (string text2 in array3)
					{
						string[] array4 = text2.Split(new char[1] { ':' });
						recipeDef.Ings.Add(new Ing
						{
							Name = array4[0],
							Amount = Mathf.Clamp((array4.Length <= 1) ? 1 : ParseInt(array4[1], 1), 1, 999),
							PerLevel = Mathf.Clamp((array4.Length > 2) ? ParseInt(array4[2], 0) : 0, 0, 999)
						});
					}
					list.Add(recipeDef);
				}
			}
			return list;
		}

		private static void Apply()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0)
			{
				return;
			}
			if ((Object)(object)instance != (Object)(object)lastDb)
			{
				AddedRecipes.Clear();
				RemovedOriginals.Clear();
				lastDb = instance;
			}
			foreach (Recipe addedRecipe in AddedRecipes)
			{
				instance.m_recipes.Remove(addedRecipe);
			}
			AddedRecipes.Clear();
			foreach (Recipe removedOriginal in RemovedOriginals)
			{
				if ((Object)(object)removedOriginal != (Object)null && !instance.m_recipes.Contains(removedOriginal))
				{
					instance.m_recipes.Add(removedOriginal);
				}
			}
			RemovedOriginals.Clear();
			List<RecipeDef> list = Parse(CurrentData());
			status = new List<string>();
			for (int i = 0; i < list.Count; i++)
			{
				RecipeDef recipeDef = list[i];
				status.Add(null);
				if (!recipeDef.Enabled)
				{
					continue;
				}
				string text = "Recipe #" + (i + 1);
				string text2 = Clean(recipeDef.Item);
				if (text2.Length == 0)
				{
					status[i] = "err_no_item";
					continue;
				}
				GameObject itemPrefab = instance.GetItemPrefab(text2);
				ItemDrop itemDrop = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)itemDrop == (Object)null)
				{
					status[i] = "err_item|" + text2;
					Log.LogWarning((object)(text + ": " + StatusText(status[i], Lang.English)));
					continue;
				}
				if (!TryFindStation(instance, recipeDef.Station, out var station))
				{
					status[i] = "err_station|" + recipeDef.Station;
					Log.LogWarning((object)(text + ": " + StatusText(status[i], Lang.English) + ". Available: " + string.Join(", ", GetStationNames(instance).ToArray())));
					continue;
				}
				List<Requirement> result;
				string text3 = BuildRequirements(instance, recipeDef.Ings, out result);
				if (text3 != null)
				{
					status[i] = text3;
					Log.LogWarning((object)(text + ": " + StatusText(text3, Lang.English)));
					continue;
				}
				if (recipeDef.Replace)
				{
					List<Recipe> list2 = instance.m_recipes.Where((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_item == (Object)(object)itemDrop && !AddedRecipes.Contains(r)).ToList();
					foreach (Recipe item in list2)
					{
						instance.m_recipes.Remove(item);
						RemovedOriginals.Add(item);
					}
				}
				Recipe val = ScriptableObject.CreateInstance<Recipe>();
				((Object)val).name = "Recipe_Custom_" + (i + 1) + "_" + text2;
				val.m_item = itemDrop;
				val.m_amount = Mathf.Max(1, recipeDef.Amount);
				val.m_craftingStation = station;
				val.m_minStationLevel = Mathf.Max(1, recipeDef.MinLevel);
				val.m_resources = result.ToArray();
				val.m_enabled = true;
				instance.m_recipes.Add(val);
				AddedRecipes.Add(val);
				status[i] = "OK";
			}
			lastAppliedData = CurrentData();
			Log.LogInfo((object)("Custom recipes applied: " + AddedRecipes.Count + " of " + list.Count));
		}

		private static string BuildRequirements(ObjectDB db, List<Ing> ings, out List<Requirement> result)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			result = new List<Requirement>();
			foreach (Ing ing in ings)
			{
				string text = Clean(ing.Name);
				if (text.Length != 0)
				{
					GameObject itemPrefab = db.GetItemPrefab(text);
					ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					if ((Object)(object)val == (Object)null)
					{
						return "err_ing|" + text;
					}
					result.Add(new Requirement
					{
						m_resItem = val,
						m_amount = Mathf.Max(1, ing.Amount),
						m_amountPerLevel = Mathf.Max(0, ing.PerLevel),
						m_recover = true
					});
				}
			}
			return (result.Count == 0) ? "err_no_ings" : null;
		}

		private static string Normalize(string name)
		{
			name = (name ?? "").Trim().ToLowerInvariant();
			if (name.EndsWith("(clone)"))
			{
				name = name.Substring(0, name.Length - 7).Trim();
			}
			if (name.StartsWith("piece_"))
			{
				name = name.Substring(6);
			}
			return name;
		}

		private static string CanonStation(string value)
		{
			string text = Normalize(value);
			if (text.Length == 0 || text == "none" || text == "hand" || text == "inventory")
			{
				return "none";
			}
			if (text == "artisantable" || text == "artisanstation")
			{
				return "artisan";
			}
			return text;
		}

		private static IEnumerable<CraftingStation> AllStations(ObjectDB db)
		{
			Dictionary<string, CraftingStation> dictionary = new Dictionary<string, CraftingStation>();
			foreach (Recipe recipe in db.m_recipes)
			{
				if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_craftingStation != (Object)null && !dictionary.ContainsKey(((Object)recipe.m_craftingStation).name))
				{
					dictionary[((Object)recipe.m_craftingStation).name] = recipe.m_craftingStation;
				}
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if (!((Object)(object)prefab == (Object)null))
					{
						CraftingStation component = prefab.GetComponent<CraftingStation>();
						if ((Object)(object)component != (Object)null && !dictionary.ContainsKey(((Object)prefab).name))
						{
							dictionary[((Object)prefab).name] = component;
						}
					}
				}
			}
			return dictionary.Values;
		}

		private static IEnumerable<string> GetStationNames(ObjectDB db)
		{
			return (from cs in AllStations(db)
				select ((Object)cs).name).Distinct();
		}

		private static bool TryFindStation(ObjectDB db, string value, out CraftingStation station)
		{
			station = null;
			string text = CanonStation(value);
			if (text == "none")
			{
				return true;
			}
			if (text == "artisan")
			{
				text = "artisanstation";
			}
			foreach (CraftingStation item in AllStations(db))
			{
				if (Normalize(((Object)item).name) == text)
				{
					station = item;
					return true;
				}
			}
			return false;
		}

		private static void DiscoverMaterials()
		{
			if (AutoDiscover == null || !AutoDiscover.Value || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				HashSet<string> value = Traverse.Create((object)Player.m_localPlayer).Field("m_knownMaterial").GetValue<HashSet<string>>();
				if (value == null)
				{
					return;
				}
				foreach (Recipe addedRecipe in AddedRecipes)
				{
					if ((Object)(object)addedRecipe == (Object)null || addedRecipe.m_resources == null)
					{
						continue;
					}
					Requirement[] resources = addedRecipe.m_resources;
					foreach (Requirement val in resources)
					{
						if (!((Object)(object)val.m_resItem == (Object)null))
						{
							string name = val.m_resItem.m_itemData.m_shared.m_name;
							if (!string.IsNullOrEmpty(name))
							{
								value.Add(name);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("DiscoverMaterials: " + ex.Message));
			}
		}

		private static void RefreshUi()
		{
			try
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					Traverse.Create((object)Player.m_localPlayer).Method("UpdateKnownRecipesList", Array.Empty<object>()).GetValue();
				}
				if ((Object)(object)InventoryGui.instance != (Object)null)
				{
					Traverse.Create((object)InventoryGui.instance).Method("UpdateCraftingPanel", new object[1] { false }).GetValue();
				}
			}
			catch (Exception ex)
			{
				if (!refreshWarned)
				{
					refreshWarned = true;
					Log.LogWarning((object)("Could not refresh the crafting UI: " + ex.Message));
				}
			}
		}

		private static void ResolveLoc()
		{
			if (locResolved)
			{
				return;
			}
			locResolved = true;
			try
			{
				Type type = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					try
					{
						type = assembly.GetType("Localization");
					}
					catch
					{
					}
					if (type != null)
					{
						break;
					}
				}
				if (type == null)
				{
					Log.LogWarning((object)"Localization class not found - item names will not be translated.");
					return;
				}
				locProp = type.GetProperty("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				locField = type.GetField("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				locLocalize = type.GetMethod("Localize", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not prepare localization: " + ex.Message));
			}
		}

		private static object GetLoc()
		{
			ResolveLoc();
			try
			{
				if (locProp != null)
				{
					return locProp.GetValue(null, null);
				}
				if (locField != null)
				{
					return locField.GetValue(null);
				}
			}
			catch
			{
			}
			return null;
		}

		private static string Localize(string token)
		{
			try
			{
				object loc = GetLoc();
				if (loc == null || locLocalize == null)
				{
					return token;
				}
				return (string)locLocalize.Invoke(loc, new object[1] { token });
			}
			catch
			{
				return token;
			}
		}

		private static void EnsureIndex()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0 || GetLoc() == null || (itemIndex != null && (Object)(object)indexDb == (Object)(object)instance && itemIndex.Count > 0))
			{
				return;
			}
			indexDb = instance;
			itemIndex = new List<ItemEntry>();
			itemByPrefab = new Dictionary<string, ItemEntry>();
			foreach (GameObject item in instance.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null))
				{
					string name = ((Object)item).name;
					if (component.m_itemData != null && component.m_itemData.m_shared != null && !string.IsNullOrEmpty(component.m_itemData.m_shared.m_name))
					{
						name = component.m_itemData.m_shared.m_name;
					}
					string text = Localize(name);
					Sprite icon = null;
					if (component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_icons != null && component.m_itemData.m_shared.m_icons.Length != 0)
					{
						icon = component.m_itemData.m_shared.m_icons[0];
					}
					if (!itemByPrefab.ContainsKey(((Object)item).name))
					{
						ItemEntry itemEntry = new ItemEntry
						{
							Prefab = ((Object)item).name,
							Display = text,
							Search = (((Object)item).name + " " + text).ToLowerInvariant(),
							Icon = icon
						};
						itemIndex.Add(itemEntry);
						itemByPrefab[((Object)item).name] = itemEntry;
					}
				}
			}
			itemIndex.Sort((ItemEntry a, ItemEntry b) => string.CompareOrdinal(a.Prefab, b.Prefab));
		}

		private static List<ItemEntry> Query(string text)
		{
			List<ItemEntry> list = new List<ItemEntry>();
			if (itemIndex == null || string.IsNullOrEmpty(text))
			{
				return list;
			}
			string value = text.ToLowerInvariant();
			foreach (ItemEntry item in itemIndex)
			{
				if (item.Prefab.StartsWith(text, StringComparison.OrdinalIgnoreCase) || item.Display.StartsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(item);
					if (list.Count >= 12)
					{
						return list;
					}
				}
			}
			foreach (ItemEntry item2 in itemIndex)
			{
				if (!list.Contains(item2) && item2.Search.Contains(value))
				{
					list.Add(item2);
					if (list.Count >= 12)
					{
						break;
					}
				}
			}
			return list;
		}

		private static string DisplayFor(string prefab)
		{
			if (itemByPrefab != null && !string.IsNullOrEmpty(prefab) && itemByPrefab.TryGetValue(prefab, out var value))
			{
				return value.Display;
			}
			return null;
		}

		private static void ZNetAwakePostfix()
		{
			try
			{
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.Register<string>("CustomRecept_Submit", (Action<long, string>)RPC_Submit);
					ZRoutedRpc.instance.Register<string>("CustomRecept_Apply", (Action<long, string>)RPC_Apply);
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not register network calls: " + ex.Message));
			}
		}

		private static void ZNetDestroyPostfix()
		{
			overrideData = null;
		}

		private static long ServerPeerId()
		{
			try
			{
				ZNet instance = ZNet.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return 0L;
				}
				if (instance.IsServer())
				{
					ZRoutedRpc instance2 = ZRoutedRpc.instance;
					if (instance2 == null)
					{
						return 0L;
					}
					Traverse val = Traverse.Create((object)instance2);
					if (!(val.Method("GetUID", Array.Empty<object>()).GetValue() is long result))
					{
						return val.Field("m_id").GetValue<long>();
					}
					return result;
				}
				return instance.GetServerPeer()?.m_uid ?? 0;
			}
			catch
			{
				return 0L;
			}
		}

		private static void BroadcastRecipes(string data)
		{
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null)
				{
					return;
				}
				if (ZNet.instance.IsServer())
				{
					ServerPublish(data);
					return;
				}
				long num = ServerPeerId();
				if (num == 0)
				{
					Log.LogWarning((object)"Could not find the server to send recipes to.");
					return;
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(num, "CustomRecept_Submit", new object[1] { data });
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not send recipes to other players: " + ex.Message));
			}
		}

		private static void ServerPublish(string data)
		{
			if (RecipesData.Value != data)
			{
				RecipesData.Value = data;
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "CustomRecept_Apply", new object[1] { data });
		}

		private static void RPC_Submit(long sender, string data)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (!string.IsNullOrEmpty(data) || !(data != "")) && (data == null || data.Length <= 500000))
			{
				if (!IsSenderAdmin(sender))
				{
					Log.LogWarning((object)("Ignored a recipe update from a player who is not an admin (id " + sender + ")."));
				}
				else
				{
					ServerPublish(data ?? "");
				}
			}
		}

		private static void RPC_Apply(long sender, string data)
		{
			if (ZRoutedRpc.instance != null && sender == ServerPeerId())
			{
				overrideData = data ?? "";
				Log.LogInfo((object)"Received a recipe update from the server.");
				ApplyAll();
			}
		}

		private static bool IsSenderAdmin(long sender)
		{
			try
			{
				ZNet instance = ZNet.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				ZNetPeer peer = instance.GetPeer(sender);
				if (peer == null)
				{
					return sender == ServerPeerId();
				}
				string hostName = peer.m_socket.GetHostName();
				object value = Traverse.Create((object)instance).Field("m_adminList").GetValue();
				MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
				if (value != null && methodInfo != null && hostName != null)
				{
					return (bool)methodInfo.Invoke(instance, new object[2] { value, hostName });
				}
			}
			catch (Exception ex)
			{
				if (!adminCheckWarned)
				{
					adminCheckWarned = true;
					Log.LogWarning((object)("Admin check failed: " + ex.Message));
				}
				return true;
			}
			if (!adminCheckWarned)
			{
				adminCheckWarned = true;
				Log.LogWarning((object)"Could not verify admin status of the sender; accepting the update.");
			}
			return true;
		}

		private static string LangName(Lang l)
		{
			return l switch
			{
				Lang.Russian => "Русский", 
				Lang.Ukrainian => "Українська", 
				_ => "English", 
			};
		}

		private static void RefreshLang()
		{
			if (LanguageSetting != null)
			{
				switch (LanguageSetting.Value)
				{
				case LangSetting.English:
					curLang = Lang.English;
					break;
				case LangSetting.Russian:
					curLang = Lang.Russian;
					break;
				case LangSetting.Ukrainian:
					curLang = Lang.Ukrainian;
					break;
				default:
					curLang = DetectGameLang();
					break;
				}
			}
		}

		private static Lang DetectGameLang()
		{
			try
			{
				object loc = GetLoc();
				if (loc == null)
				{
					return Lang.English;
				}
				MethodInfo method = loc.GetType().GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				string a = ((method != null) ? (method.Invoke(loc, null) as string) : null);
				if (string.Equals(a, "Russian", StringComparison.OrdinalIgnoreCase))
				{
					return Lang.Russian;
				}
				if (string.Equals(a, "Ukrainian", StringComparison.OrdinalIgnoreCase))
				{
					return Lang.Ukrainian;
				}
			}
			catch
			{
			}
			return Lang.English;
		}

		private static void CycleLanguage()
		{
			Lang lang = (Lang)((int)(curLang + 1) % 3);
			LanguageSetting.Value = lang switch
			{
				Lang.Ukrainian => LangSetting.Ukrainian, 
				Lang.Russian => LangSetting.Russian, 
				_ => LangSetting.English, 
			};
		}

		private static string Tx(Lang lang, string key, params object[] args)
		{
			string[] value;
			string text = (Tr.TryGetValue(key, out value) ? value[(int)lang] : key);
			return (args != null && args.Length != 0) ? string.Format(text, args) : text;
		}

		private static string T(string key, params object[] args)
		{
			return Tx(curLang, key, args);
		}

		private static string StatusText(string st, Lang lang)
		{
			if (string.IsNullOrEmpty(st))
			{
				return "";
			}
			int num = st.IndexOf('|');
			return (num < 0) ? Tx(lang, st) : Tx(lang, st.Substring(0, num), st.Substring(num + 1));
		}

		private static Texture2D RoundedTex(int size, int radius, Color fill, Color border, float borderWidth)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)5, false);
			((Object)val).hideFlags = (HideFlags)61;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			Color[] array = (Color[])(object)new Color[size * size];
			float num = radius;
			float num2 = size - radius;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num3 = (float)j + 0.5f;
					float num4 = (float)i + 0.5f;
					float num5 = Mathf.Clamp(num3, num, num2);
					float num6 = Mathf.Clamp(num4, num, num2);
					float num7 = Mathf.Sqrt((num3 - num5) * (num3 - num5) + (num4 - num6) * (num4 - num6));
					float num8 = Mathf.Clamp01((float)radius - num7 + 0.5f);
					float num9 = Mathf.Clamp01(num7 - ((float)radius - borderWidth) + 0.5f);
					Color val2 = Color.Lerp(fill, border, num9);
					val2.a = Mathf.Lerp(fill.a, border.a, num9) * num8;
					array[i * size + j] = val2;
				}
			}
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private static Texture2D Rounded(Color fill, Color border, float bw)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return RoundedTex(32, 8, fill, border, bw);
		}

		private static GUIStyle MakeButton(Texture2D n, Texture2D h, Texture2D a, Color text, Color hoverText)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0075: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			GUIStyle val = new GUIStyle();
			val.normal.background = n;
			val.hover.background = h;
			val.active.background = a;
			val.focused.background = n;
			val.onNormal.background = n;
			val.onHover.background = h;
			val.onActive.background = a;
			val.onFocused.background = n;
			val.normal.textColor = text;
			val.hover.textColor = hoverText;
			val.active.textColor = text;
			val.focused.textColor = text;
			val.onNormal.textColor = text;
			val.onHover.textColor = hoverText;
			val.onActive.textColor = text;
			val.onFocused.textColor = text;
			val.border = new RectOffset(8, 8, 8, 8);
			val.padding = new RectOffset(10, 10, 4, 4);
			val.margin = new RectOffset(3, 3, 3, 3);
			val.alignment = (TextAnchor)4;
			val.fontSize = 13;
			val.clipping = (TextClipping)1;
			val.wordWrap = false;
			val.richText = true;
			return val;
		}

		private static GUIStyle MakeLabel(Color c, int size, bool bold, TextAnchor anchor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			GUIStyle val = new GUIStyle();
			val.normal.textColor = c;
			val.fontSize = size;
			val.fontStyle = (FontStyle)(bold ? 1 : 0);
			val.alignment = anchor;
			val.wordWrap = false;
			val.clipping = (TextClipping)1;
			val.richText = true;
			val.margin = new RectOffset(3, 3, 3, 3);
			val.padding = new RectOffset(2, 2, 2, 2);
			return val;
		}

		private static void EnsureStyles()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_016f: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_022c: 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_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: 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_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_051b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_0599: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05df: Expected O, but got Unknown
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_0658: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_0689: Unknown result type (might be due to invalid IL or missing references)
			//IL_0693: Expected O, but got Unknown
			//IL_0694: Unknown result type (might be due to invalid IL or missing references)
			//IL_069e: Expected O, but got Unknown
			//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0777: Unknown result type (might be due to invalid IL or missing references)
			//IL_078c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fe: Expected O, but got Unknown
			//IL_0808: Unknown result type (might be due to invalid IL or missing references)
			//IL_0812: Expected O, but got Unknown
			//IL_081c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0826: Expected O, but got Unknown
			//IL_085c: Unknown result type (might be due to invalid IL or missing references)
			//IL_086f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0882: Unknown result type (might be due to invalid IL or missing references)
			//IL_0895: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_08bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08da: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0900: Expected O, but got Unknown
			//IL_0901: Unknown result type (might be due to invalid IL or missing references)
			//IL_093b: Unknown result type (might be due to invalid IL or missing references)
			//IL_094e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0961: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ef: Expected O, but got Unknown
			//IL_0a07: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a20: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a34: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a39: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a4a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a51: Expected O, but got Unknown
			//IL_0a66: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a70: Expected O, but got Unknown
			//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a92: Expected O, but got Unknown
			//IL_0ac5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0acf: Expected O, but got Unknown
			//IL_0aea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af1: Expected O, but got Unknown
			//IL_0b25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b2c: Expected O, but got Unknown
			//IL_0b77: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)skin != (Object)null) || windowStyle == null || !((Object)(object)windowStyle.normal.background != (Object)null))
			{
				Font val = null;
				try
				{
					val = Font.CreateDynamicFontFromOSFont(new string[4] { "Georgia", "Palatino Linotype", "Book Antiqua", "Times New Roman" }, 20);
				}
				catch
				{
				}
				windowStyle = new GUIStyle();
				windowStyle.normal.background = RoundedTex(64, 16, new Color(0.075f, 0.07f, 0.065f, 0.985f), GoldDim, 2f);
				windowStyle.onNormal.background = windowStyle.normal.background;
				windowStyle.border = new RectOffset(16, 16, 16, 16);
				windowStyle.padding = new RectOffset(18, 18, 14, 14);
				cardStyle = new GUIStyle();
				cardStyle.normal.background = Rounded(new Color(0.115f, 0.105f, 0.095f, 1f), new Color(0.27f, 0.23f, 0.17f, 1f), 1f);
				cardStyle.border = new RectOffset(8, 8, 8, 8);
				cardStyle.padding = new RectOffset(10, 10, 8, 8);
				cardStyle.margin = new RectOffset(2, 2, 4, 4);
				slotStyle = new GUIStyle();
				slotStyle.normal.background = Rounded(new Color(0.14f, 0.125f, 0.11f, 1f), new Color(0.33f, 0.27f, 0.19f, 1f), 1f);
				slotStyle.border = new RectOffset(8, 8, 8, 8);
				slotGoldStyle = new GUIStyle();
				slotGoldStyle.normal.background = Rounded(new Color(0.16f, 0.14f, 0.11f, 1f), GoldColor, 2f);
				slotGoldStyle.border = new RectOffset(8, 8, 8, 8);
				buttonStyle = MakeButton(Rounded(new Color(0.15f, 0.13f, 0.11f, 1f), new Color(0.4f, 0.33f, 0.22f, 1f), 1f), Rounded(new Color(0.21f, 0.18f, 0.14f, 1f), GoldColor, 1f), Rounded(new Color(0.1f, 0.09f, 0.08f, 1f), GoldColor, 1f), TextColor, Color.white);
				primaryStyle = MakeButton(Rounded(new Color(0.42f, 0.32f, 0.14f, 1f), GoldColor, 1.5f), Rounded(new Color(0.55f, 0.42f, 0.18f, 1f), new Color(1f, 0.85f, 0.5f, 1f), 1.5f), Rounded(new Color(0.32f, 0.24f, 0.1f, 1f), GoldColor, 1.5f), new Color(1f, 0.93f, 0.75f), Color.white);
				dangerStyle = MakeButton(Rounded(new Color(0.17f, 0.11f, 0.1f, 1f), new Color(0.55f, 0.25f, 0.22f, 1f), 1f), Rounded(new Color(0.27f, 0.13f, 0.12f, 1f), new Color(0.92f, 0.4f, 0.35f, 1f), 1f), Rounded(new Color(0.12f, 0.07f, 0.06f, 1f), new Color(0.92f, 0.4f, 0.35f, 1f), 1f), new Color(0.95f, 0.65f, 0.6f), Color.white);
				chipOnStyle = MakeButton(Rounded(new Color(0.3f, 0.24f, 0.12f, 1f), GoldColor, 1.5f), Rounded(new Color(0.38f, 0.3f, 0.15f, 1f), new Color(1f, 0.85f, 0.5f, 1f), 1.5f), Rounded(new Color(0.24f, 0.19f, 0.09f, 1f), GoldColor, 1.5f), new Color(1f, 0.92f, 0.72f), Color.white);
				Texture2D n = Rounded(new Color(1f, 1f, 1f, 0f), new Color(1f, 1f, 1f, 0f), 0f);
				Texture2D val2 = Rounded(new Color(1f, 1f, 1f, 0.06f), new Color(1f, 1f, 1f, 0f), 0f);
				flatStyle = MakeButton(n, val2, val2, TextColor, Color.white);
				flatStyle.alignment = (TextAnchor)3;
				flatStyle.padding = new RectOffset(8, 8, 2, 2);
				cardBtnStyle = MakeButton(Rounded(new Color(0.13f, 0.115f, 0.1f, 1f), new Color(0.3f, 0.25f, 0.18f, 1f), 1f), Rounded(new Color(0.2f, 0.17f, 0.13f, 1f), GoldColor, 1.5f), Rounded(new Color(0.1f, 0.09f, 0.08f, 1f), GoldColor, 1.5f), TextColor, Color.white);
				cardBtnStyle.margin = new RectOffset(0, 0, 0, 0);
				fieldStyle = new GUIStyle();
				Texture2D background = Rounded(new Color(0.06f, 0.055f, 0.05f, 1f), new Color(0.3f, 0.26f, 0.19f, 1f), 1f);
				Texture2D background2 = Rounded(new Color(0.08f, 0.07f, 0.06f, 1f), GoldColor, 1.5f);
				fieldStyle.normal.background = background;
				fieldStyle.hover.background = background;
				fieldStyle.focused.background = background2;
				fieldStyle.onNormal.background = background;
				fieldStyle.onHover.background = background;
				fieldStyle.onFocused.background = background2;
				fieldStyle.normal.textColor = TextColor;
				fieldStyle.hover.textColor = TextColor;
				fieldStyle.focused.textColor = Color.white;
				fieldStyle.onNormal.textColor = TextColor;
				fieldStyle.onHover.textColor = TextColor;
				fieldStyle.onFocused.textColor = Color.white;
				fieldStyle.border = new RectOffset(8, 8, 8, 8);
				fieldStyle.padding = new RectOffset(8, 8, 4, 4);
				fieldStyle.margin = new RectOffset(3, 3, 3, 3);
				fieldStyle.alignment = (TextAnchor)3;
				fieldStyle.fontSize = 13;
				fieldStyle.clipping = (TextClipping)1;
				fieldStyle.fixedHeight = 28f;
				grayLabel = MakeLabel(TextDimColor, 13, bold: false, (TextAnchor)3);
				greenLabel = MakeLabel(GreenColor, 13, bold: false, (TextAnchor)3);
				redLabel = MakeLabel(RedColor, 13, bold: false, (TextAnchor)3);
				boldLabel = MakeLabel(TextColor, 14, bold: true, (TextAnchor)3);
				centerLabel = MakeLabel(TextDimColor, 18, bold: true, (TextAnchor)4);
				hintLabel = MakeLabel(TextDimColor, 12, bold: false, (TextAnchor)0);
				hintLabel.wordWrap = true;
				headStyle = MakeLabel(GoldColor, 12, bold: false, (TextAnchor)3);
				headStyle.margin = new RectOffset(3, 3, 8, 2);
				titleStyle = MakeLabel(GoldColor, 22, bold: false, (TextAnchor)3);
				if ((Object)(object)val != (Object)null)
				{
					headStyle.font = val;
					titleStyle.font = val;
				}
				badgeStyle = MakeLabel(Color.white, 13, bold: true, (TextAnchor)8);
				badgeShadowStyle = MakeLabel(Color.black, 13, bold: true, (TextAnchor)8);
				cardTextStyle = MakeLabel(TextColor, 13, bold: false, (TextAnchor)0);
				skin = Object.Instantiate<GUISkin>(GUI.skin);
				((Object)skin).hideFlags = (HideFlags)61;
				skin.window = windowStyle;
				skin.box = cardStyle;
				skin.button = buttonStyle;
				skin.textField = fieldStyle;
				skin.label = grayLabel;
				skin.scrollView = new GUIStyle();
				Texture2D background3 = RoundedTex(16, 4, new Color(0.05f, 0.045f, 0.04f, 1f), new Color(0.05f, 0.045f, 0.04f, 1f), 0f);
				Texture2D background4 = RoundedTex(16, 4, GoldDim, GoldDim, 0f);
				GUIStyle val3 = new GUIStyle();
				val3.normal.background = background3;
				val3.border = new RectOffset(4, 4, 4, 4);
				val3.fixedWidth = 10f;
				skin.verticalScrollbar = val3;
				GUIStyle val4 = new GUIStyle();
				val4.normal.background = background4;
				val4.hover.background = background4;
				val4.active.background = background4;
				val4.border = new RectOffset(4, 4, 4, 4);
				val4.fixedWidth = 10f;
				skin.verticalScrollbarThumb = val4;
				GUIStyle val5 = new GUIStyle();
				val5.fixedWidth = 0f;
				val5.fixedHeight = 0f;
				skin.verticalScrollbarUpButton = val5;
				skin.verticalScrollbarDownButton = val5;
				GUIStyle val6 = new GUIStyle();
				val6.fixedHeight = 0f;
				skin.horizontalScrollbar = val6;
				skin.horizontalScrollbarThumb = val6;
				skin.horizontalScrollbarLeftButton = val5;
				skin.horizontalScrollbarRightButton = val5;
				skin.settings.cursorColor = GoldColor;
				skin.settings.selectionColor = new Color(0.8f, 0.66f, 0.4f, 0.35f);
			}
		}

		private static void Enqueue(Action a)
		{
			pending.Enqueue(a);
		}

		private void OnGUI()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0095: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			if (MenuOpen)
			{
				EnsureStyles();
				EnsureIndex();
				GUISkin val = GUI.skin;
				Matrix4x4 matrix = GUI.matrix;
				float num = Mathf.Max(0.1f, UiScale.Value);
				GUI.skin = skin;
				GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f));
				Rect val2 = windowRect;
				object obj = <>O.<3>__DrawWindow;
				if (obj == null)
				{
					WindowFunction val3 = DrawWindow;
					<>O.<3>__DrawWindow = val3;
					obj = (object)val3;
				}
				windowRect = GUI.Window(7771234, val2, (WindowFunction)obj, "", windowStyle);
				GUI.matrix = matrix;
				GUI.skin = val;
			}
		}

		private static void DrawWindow(int id)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type == 8)
			{
				while (pending.Count > 0)
				{
					pending.Dequeue()();
				}
			}
			GUI.changed = false;
			bool flag = CanEdit();
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(T("title"), titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(32f),
				GUILayout.Width(130f)
			});
			if (GUILayout.Button(T("new_recipe"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(140f),
				GUILayout.Height(30f)
			}))
			{
				Enqueue(delegate
				{
					working.Add(new RecipeDef
					{
						Expanded = true
					});
					dirty = true;
				});
			}
			if (GUILayout.Button(T("collapse_all"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(110f),
				GUILayout.Height(30f)
			}))
			{
				Enqueue(delegate
				{
					foreach (RecipeDef item in working)
					{
						item.Expanded = false;
					}
				});
			}
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("A-", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(34f),
				GUILayout.Height(30f)
			}))
			{
				UiScale.Value = Mathf.Clamp(UiScale.Value - 0.1f, 0.6f, 3f);
			}
			if (GUILayout.Button("A+", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(34f),
				GUILayout.Height(30f)
			}))
			{
				UiScale.Value = Mathf.Clamp(UiScale.Value + 0.1f, 0.6f, 3f);
			}
			string text = T("lang", LangName(curLang) + ((LanguageSetting.Value == LangSetting.Auto) ? " (auto)" : ""));
			if (GUILayout.Button(text, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(150f),
				GUILayout.Height(30f)
			}))
			{
				Enqueue(CycleLanguage);
			}
			if (GUILayout.Button(T("revert"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(130f),
				GUILayout.Height(30f)
			}))
			{
				Enqueue(LoadWorking);
			}
			GUI.enabled = flag;
			if (GUILayout.Button(dirty ? (T("save") + " *") : T("save"), primaryStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(210f),
				GUILayout.Height(30f)
			}))
			{
				Enqueue(Save);
			}
			GUI.enabled = true;
			if (GUILayout.Button(T("close"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(90f),
				GUILayout.Height(30f)
			}))
			{
				CloseMenu();
			}
			GUILayout.EndHorizontal();
			if (flag)
			{
				GUILayout.Label(T("hint_edit"), hintLabel, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label(T("hint_noadmin"), redLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(4f);
			scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			if (working.Count == 0)
			{
				GUILayout.Label(T("empty_list"), grayLabel, Array.Empty<GUILayoutOption>());
			}
			for (int num = 0; num < working.Count; num++)
			{
				DrawRecipe(num);
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			if (GUI.changed)
			{
				dirty = true;
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 46f));
		}

		private static void Save()
		{
			string text = Serialize(working);
			dirty = false;
			if (RecipesData.Value != text)
			{
				RecipesData.Value = text;
			}
			else
			{
				Apply();
			}
			BroadcastRecipes(text);
		}

		private static void DrawRecipe(int i)
		{
			RecipeDef d = working[i];
			int idx = i;
			string text = Clean(d.Item);
			GUILayout.BeginVertical(cardStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(54f) });
			GUILayout.Space(13f);
			d.Enabled = Switch(d.Enabled, 54f);
			GUILayout.EndVertical();
			GUILayout.Space(4f);
			SlotIcon(54f, text, d.Amount, d.Expanded);
			string text2 = DisplayFor(text);
			string text3 = ((text.Length == 0) ? T("new_title") : (text2 ?? text));
			string text4 = StationLabel(d.Station) + "  ·  " + T("level_word") + " " + d.MinLevel + "  ·  " + (d.Expanded ? T("click_collapse") : T("click_edit"));
			string text5 = "<size=16><b>" + text3 + "</b></size>\n<color=#9a8f7a>" + text4 + "</color>";
			if (GUILayout.Button(text5, flatStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.Height(54f)
			}))
			{
				bool value = !d.Expanded;
				Enqueue(delegate
				{
					d.Expanded = value;
				});
			}
			string text6 = ((idx < status.Count) ? status[idx] : null);
			string text7;
			GUIStyle val;
			if (!d.Enabled)
			{
				text7 = T("stat_off");
				val = grayLabel;
			}
			else if (text6 == "OK")
			{
				text7 = T("stat_ok");
				val = greenLabel;
			}
			else if (text6 != null)
			{
				text7 = StatusText(text6, curLang);
				val = redLabel;
			}
			else
			{
				text7 = T("stat_unsaved");
				val = grayLabel;
			}
			GUILayout.Label(text7, val, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(150f),
				GUILayout.Height(54f)
			});
			int num = Mathf.Min(d.Ings.Count, 5);
			for (int num2 = 0; num2 < num; num2++)
			{
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) });
				GUILayout.Space(4f);
				SlotIcon(46f, Clean(d.Ings[num2].Name), d.Ings[num2].Amount, gold: false);
				GUILayout.EndVertical();
			}
			if (d.Ings.Count > num)
			{
				GUILayout.Label("+" + (d.Ings.Count - num), boldLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(30f),
					GUILayout.Height(54f)
				});
			}
			GUILayout.EndHorizontal();
			if (d.Expanded)
			{
				GUILayout.Space(6f);
				GUILayout.Label(T("sec_what"), headStyle, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				SlotIcon(34f, text, 0, gold: false);
				d.Item = NameField("item_" + idx, d.Item, 280f);
				InfoLabel(d.Item);
				GUILayout.Label(T("lbl_amount"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(100f),
					GUILayout.Height(28f)
				});
				d.Amount = IntField("amount_" + idx, d.Amount, 1, 999, 56f);
				GUILayout.EndHorizontal();
				Suggestions("item_" + idx, d.Item, delegate(string s)
				{
					d.Item = s;
				});
				GUILayout.Label(T("sec_where"), headStyle, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				string text8 = CanonStation(d.Station);
				string[][] stationPresets = StationPresets;
				foreach (string[] array in stationPresets)
				{
					if (GUILayout.Button(T("st_" + array[0]), (text8 == array[0]) ? chipOnStyle : buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
					{
						d.Station = array[0];
						GUI.changed = true;
					}
				}
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(T("lbl_custom_station"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(170f),
					GUILayout.Height(28f)
				});
				d.Station = SimpleField("station_" + idx, d.Station, 170f);
				GUILayout.Space(16f);
				GUILayout.Label(T("lbl_level"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(115f),
					GUILayout.Height(28f)
				});
				d.MinLevel = IntField("level_" + idx, d.MinLevel, 1, 10, 44f);
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(T("lbl_replace", d.Replace ? T("yes") : T("no")), d.Replace ? chipOnStyle : buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					d.Replace = !d.Replace;
					GUI.changed = true;
				}
				GUILayout.EndHorizontal();
				GUILayout.Label(T("sec_from"), headStyle, Array.Empty<GUILayoutOption>());
				for (int num4 = 0; num4 < d.Ings.Count; num4++)
				{
					Ing g = d.Ings[num4];
					int jdx = num4;
					string text9 = "ing_" + idx + "_" + jdx;
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					SlotIcon(34f, Clean(g.Name), 0, gold: false);
					g.Name = NameField(text9, g.Name, 250f);
					InfoLabel(g.Name);
					GUILayout.Label(T("lbl_pcs"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(42f),
						GUILayout.Height(28f)
					});
					g.Amount = IntField(text9 + "_a", g.Amount, 1, 999, 52f);
					GUILayout.Label(T("lbl_perlevel"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(52f),
						GUILayout.Height(28f)
					});
					g.PerLevel = IntField(text9 + "_p", g.PerLevel, 0, 999, 46f);
					if (GUILayout.Button("X", dangerStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(30f),
						GUILayout.Height(28f)
					}))
					{
						Enqueue(delegate
						{
							if (jdx < d.Ings.Count)
							{
								d.Ings.RemoveAt(jdx);
								dirty = true;
							}
						});
					}
					GUILayout.EndHorizontal();
					Suggestions(text9, g.Name, delegate(string s)
					{
						g.Name = s;
					});
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(T("add_ing"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(130f),
					GUILayout.Height(28f)
				}))
				{
					Enqueue(delegate
					{
						d.Ings.Add(new Ing());
						dirty = true;
					});
				}
				GUILayout.Label(T("hint_perlevel"), grayLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
				GUILayout.EndHorizontal();
				GUILayout.Space(6f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (GUILayout.Button(T("copy"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(80f),
					GUILayout.Height(28f)
				}))
				{
					Enqueue(delegate
					{
						DuplicateRecipe(idx);
					});
				}
				if (GUILayout.Button(T("up"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(80f),
					GUILayout.Height(28f)
				}))
				{
					Enqueue(delegate
					{
						MoveRecipe(idx, -1);
					});
				}
				if (GUILayout.Button(T("down"), buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(80f),
					GUILayout.Height(28f)
				}))
				{
					Enqueue(delegate
					{
						MoveRecipe(idx, 1);
					});
				}
				if (GUILayout.Button(T("delete"), dangerStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(90f),
					GUILayout.Height(28f)
				}))
				{
					Enqueue(delegate
					{
						if (idx < working.Count)
						{
							working.RemoveAt(idx);
							dirty = true;
						}
					});
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
		}

		private static string StationLabel(string station)
		{
			string text = CanonStation(station);
			string[][] stationPresets = StationPresets;
			foreach (string[] array in stationPresets)
			{
				if (array[0] == text)
				{
					return T("st_" + array[0]);
				}
			}
			return station;
		}

		private static void DuplicateRecipe(int idx)
		{
			if (idx >= 0 && idx < working.Count)
			{
				RecipeDef recipeDef = working[idx];
				RecipeDef item = new RecipeDef
				{
					Enabled = recipeDef.Enabled,
					Item = recipeDef.Item,
					Amount = recipeDef.Amount,
					Station = recipeDef.Station,
					MinLevel = recipeDef.MinLevel,
					Replace = recipeDef.Replace,
					Expanded = true,
					Ings = recipeDef.Ings.Select((Ing g) => new Ing
					{
						Name = g.Name,
						Amount = g.Amount,
						PerLevel = g.PerLevel
					}).ToList()
				};
				working.Insert(idx + 1, item);
				dirty = true;
			}
		}

		private static void MoveRecipe(int idx, int delta)
		{
			int num = idx + delta;
			if (idx >= 0 && idx < working.Count && num >= 0 && num < working.Count)
			{
				RecipeDef item = working[idx];
				working.RemoveAt(idx);
				working.Insert(num, item);
				dirty = true;
			}
		}

		private static ItemEntry EntryFor(string prefab)
		{
			if (itemByPrefab != null && !string.IsNullOrEmpty(prefab) && itemByPrefab.TryGetValue(prefab, out var value))
			{
				return value;
			}
			return null;
		}

		private static void DrawIcon(Rect r, Sprite sprite)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sprite == (Object)null))
			{
				Texture2D texture = sprite.texture;
				if (!((Object)(object)texture == (Object)null))
				{
					Rect textureRect = sprite.textureRect;
					Rect val = default(Rect);
					((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height);
					GUI.DrawTextureWithTexCoords(r, (Texture)(object)texture, val, true);
				}
			}
		}

		private static void SlotIcon(float size, string prefab, int count, bool gold)
		{
			//IL_001b: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(size, size, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(size),
				GUILayout.Height(size)
			});
			if ((int)Event.current.type == 7)
			{
				(gold ? slotGoldStyle : slotStyle).Draw(rect, false, false, false, false);
				ItemEntry itemEntry = EntryFor(prefab);
				if (itemEntry != null && (Object)(object)itemEntry.Icon != (Object)null)
				{
					DrawIcon(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 4f, ((Rect)(ref rect)).width - 8f, ((Rect)(ref rect)).height - 8f), itemEntry.Icon);
				}
				else if (!string.IsNullOrEmpty(prefab))
				{
					centerLabel.Draw(rect, new GUIContent("?"), false, false, false, false);
				}
				if (count > 1)
				{
					GUIContent val = new GUIContent(count.ToString());
					badgeShadowStyle.Draw(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width - 4f, ((Rect)(ref rect)).height - 2f), val, false, false, false, false);
					badgeStyle.Draw(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 4f, ((Rect)(ref rect)).height - 2f), val, false, false, false, false);
				}
			}
		}

		private static bool Switch(bool value, float width)
		{
			if (GUILayout.Button(value ? T("on") : T("off"), value ? chipOnStyle : buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.Height(28f)
			}))
			{
				GUI.changed = true;
				return !value;
			}
			return value;
		}

		private static void InfoLabel(string prefab)
		{
			string text = "";
			GUIStyle val = grayLabel;
			string text2 = Clean(prefab);
			if (text2.Length > 0 && itemByPrefab != null)
			{
				string text3 = DisplayFor(text2);
				if (text3 != null)
				{
					text = text3;
					val = greenLabel;
				}
				else
				{
					text = T("no_such_item");
					val = redLabel;
				}
			}
			GUILayout.Label(text, val, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(170f),
				GUILayout.Height(28f)
			});
		}

		private static string NameField(string key, string value, float width)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			string text = "f_" + key;
			GUI.SetNextControlName(text);
			string result = Clean(GUILayout.TextField(value ?? "", 64, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) }));
			if ((int)Event.current.type == 8 && GUI.GetNameOfFocusedControl() == text)
			{
				activeField = text;
			}
			return result;
		}

		private static string SimpleField(string key, string value, float width)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			string text = "f_" + key;
			GUI.SetNextControlName(text);
			string result = Clean(GUILayout.TextField(value ?? "", 64, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) }));
			if ((int)Event.current.type == 8 && GUI.GetNameOfFocusedControl() == text)
			{
				activeField = null;
			}
			return result;
		}

		private static int IntField(string key, int value, int min, int max, float width)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			string text = "f_" + key;
			bool flag = GUI.GetNameOfFocusedControl() == text;
			if (!flag || !rawInts.TryGetValue(text, out var value2))
			{
				value2 = value.ToString();
			}
			GUI.SetNextControlName(text);
			string text2 = GUILayout.TextField(value2, 5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) });
			if ((int)Event.current.type == 8 && flag)
			{
				activeField = null;
			}
			if (flag)
			{
				rawInts[text] = text2;
				if (int.TryParse(text2, out var result))
				{
					value = Mathf.Clamp(result, min, max);
				}
			}
			else
			{
				rawInts.Remove(text);
			}
			return value;
		}

		private static void Suggestions(string key, string current, Action<string> setter)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Invalid comparison between Unknown and I4
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			string text = "f_" + key;
			if ((int)Event.current.type == 8)
			{
				if (activeField == text && !string.IsNullOrEmpty(current))
				{
					if (suggKey != text || suggText != current)
					{
						suggKey = text;
						suggText = current;
						suggList = Query(current);
					}
				}
				else if (suggKey == text)
				{
					suggKey = null;
					suggText = null;
					suggList = new List<ItemEntry>();
				}
			}
			if (suggKey != text)
			{
				return;
			}
			if (suggList.Count == 0)
			{
				GUILayout.Label(T("nothing_found"), grayLabel, Array.Empty<GUILayoutOption>());
			}
			else
			{
				if (suggList.Count == 1 && suggList[0].Prefab == suggText)
				{
					return;
				}
				int count = suggList.Count;
				int num = (count + 3 - 1) / 3;
				GUILayout.Space(2f);
				Rect rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(true),
					GUILayout.Height((float)num * 50f + 4f)
				});
				float num2 = ((Rect)(ref rect)).width / 3f;
				Rect val = default(Rect);
				for (int i = 0; i < count; i++)
				{
					ItemEntry itemEntry = suggList[i];
					((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (float)(i % 3) * num2 + 2f, ((Rect)(ref rect)).y + (float)(i / 3) * 50f + 2f, num2 - 4f, 46f);
					if (GUI.Button(val, GUIContent.none, cardBtnStyle))
					{
						ItemEntry chosen = itemEntry;
						Enqueue(delegate
						{
							setter(chosen.Prefab);
							dirty = true;
							activeField = null;
							suggKey = null;
							suggText = null;
							suggList = new List<ItemEntry>();
							GUI.FocusControl("");
						});
					}
					if ((int)Event.current.type == 7)
					{
						slotStyle.Draw(new Rect(((Rect)(ref val)).x + 5f, ((Rect)(ref val)).y + 5f, 36f, 36f), false, false, false, false);
						DrawIcon(new Rect(((Rect)(ref val)).x + 8f, ((Rect)(ref val)).y + 8f, 30f, 30f), itemEntry.Icon);
					}
					GUI.Label(new Rect(((Rect)(ref val)).x + 48f, ((Rect)(ref val)).y + 5f, ((Rect)(ref val)).width - 52f, ((Rect)(ref val)).height - 8f), "<b>" + itemEntry.Display + "</b>\n<color=#9a8f7a>" + itemEntry.Prefab + "</color>", cardTextStyle);
				}
			}
		}
	}
}