Decompiled source of Kindle v0.1.25

plugins/Kindle/Kindle.Core.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using ExtraPotions.Kindle.Recipes;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ExtraPotions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")]
[assembly: AssemblyFileVersion("0.1.25.0")]
[assembly: AssemblyInformationalVersion("0.1.25")]
[assembly: AssemblyProduct("Kindle.Core")]
[assembly: AssemblyTitle("Kindle.Core")]
[assembly: AssemblyVersion("0.1.25.0")]
[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 ExtraPotions.Kindle
{
	public static class KindleCore
	{
		public const string ProductId = "com.meadworks.kindle";

		public const string CharacterDataPrefix = "Kindle.";
	}
}
namespace ExtraPotions.Kindle.Salvage
{
	public static class ChestTakeCodes
	{
		public const int Taken = 0;

		public const int Pending = 1;

		public const int Changed = 2;

		public const int Unavailable = 3;
	}
	public enum ChestTakeStep
	{
		Done,
		Retry,
		Changed,
		Busy
	}
	public sealed class ChestTakeRetry
	{
		public const double WaitSeconds = 5.0;

		private readonly double deadline;

		public ChestTakeRetry(double now)
		{
			deadline = now + 5.0;
		}

		public ChestTakeStep Next(int code, bool delivered, double now)
		{
			if (delivered)
			{
				return ChestTakeStep.Done;
			}
			switch (code)
			{
			case 0:
				return ChestTakeStep.Busy;
			case 1:
				if (!(now < deadline))
				{
					return ChestTakeStep.Busy;
				}
				return ChestTakeStep.Retry;
			default:
				return ChestTakeStep.Busy;
			case 2:
				return ChestTakeStep.Changed;
			}
		}
	}
	public static class SalvageDelivery
	{
		public static int Deliver<T>(IEnumerable<(T Material, int Amount, int MaxStack)> returns, Func<T, int, int> add, Action<T, int> drop, Func<T, int>? stock = null)
		{
			if (returns == null)
			{
				throw new ArgumentNullException("returns");
			}
			if (add == null)
			{
				throw new ArgumentNullException("add");
			}
			if (drop == null)
			{
				throw new ArgumentNullException("drop");
			}
			int num = 0;
			foreach (var @return in returns)
			{
				T item = @return.Material;
				int item2 = @return.Amount;
				int item3 = @return.MaxStack;
				int val = Math.Max(1, item3);
				int num2 = item2;
				while (num2 > 0)
				{
					int num3 = Math.Min(val, num2);
					int num4 = ReadStock(stock, item);
					int num5;
					try
					{
						num5 = Math.Max(0, Math.Min(num3, add(item, num3)));
					}
					catch (Exception)
					{
						int num6 = ReadStock(stock, item);
						num5 = ((stock != null) ? Math.Max(0, Math.Min(num3, num6 - num4)) : 0);
					}
					if (num5 < num3)
					{
						drop(item, num3 - num5);
						num += num3 - num5;
					}
					num2 -= num3;
				}
			}
			return num;
		}

		private static int ReadStock<T>(Func<T, int>? stock, T material)
		{
			if (stock == null)
			{
				return 0;
			}
			try
			{
				return Math.Max(0, stock(material));
			}
			catch (Exception)
			{
				return 0;
			}
		}
	}
}
namespace ExtraPotions.Kindle.Repair
{
	public struct RepairFacts
	{
		public bool CanBeRepaired;

		public bool NoCost;

		public string? Station;

		public int StationLevel;

		public bool HasRecipe;

		public string? CraftingStation;

		public string? RepairStation;

		public int MinStationLevel;

		public int ItemWorldLevel;

		public int GameWorldLevel;
	}
	public static class RepairRule
	{
		public const int LevelCap = 4;

		public static bool Qualifies(in RepairFacts item)
		{
			if (!item.CanBeRepaired)
			{
				return false;
			}
			if (item.NoCost)
			{
				return true;
			}
			if (item.Station == null || !item.HasRecipe)
			{
				return false;
			}
			if (item.CraftingStation == null && item.RepairStation == null)
			{
				return false;
			}
			if (item.RepairStation == item.Station || item.CraftingStation == item.Station || item.ItemWorldLevel < item.GameWorldLevel)
			{
				return Math.Min(item.StationLevel, 4) >= item.MinStationLevel;
			}
			return false;
		}
	}
	public static class StationStack
	{
		public const float Gap = 6f;

		public const float FallbackHeight = 44f;

		public const int SalvageSlot = 2;

		public const float BackingMargin = 8f;

		public static float Y(float repairY, float repairHeight, int stepsBelow)
		{
			return repairY - (float)stepsBelow * (((repairHeight > 1f) ? repairHeight : 44f) + 6f);
		}

		public static (float Width, float Height) Backing(float repairWidth, float repairHeight)
		{
			return (Width: repairWidth + 16f, Height: repairHeight + 16f);
		}
	}
}
namespace ExtraPotions.Kindle.Recipes
{
	public enum OnlyToggle
	{
		On,
		Off,
		RefusedNoFavourites
	}
	public sealed class FavouriteRecipes
	{
		public const string SetKey = "Kindle.favoriteRecipes";

		public const string OnlyKey = "Kindle.favoriteRecipesOnly";

		public const string OpenKeepSetKey = "OpenKeep.favouriteRecipes";

		public const string OpenKeepOnlyKey = "OpenKeep.favouriteRecipesOnly";

		private readonly List<string> order = new List<string>();

		private readonly HashSet<string> keys = new HashSet<string>(StringComparer.Ordinal);

		public IReadOnlyList<string> Keys => order;

		public int Count => order.Count;

		public bool OnlyFlag { get; private set; }

		private FavouriteRecipes()
		{
		}

		public static FavouriteRecipes Parse(string? set, string? onlyFlag)
		{
			FavouriteRecipes favouriteRecipes = new FavouriteRecipes();
			if (!string.IsNullOrEmpty(set))
			{
				string[] array = set.Split(',');
				foreach (string key in array)
				{
					favouriteRecipes.Add(Clean(key));
				}
			}
			favouriteRecipes.OnlyFlag = onlyFlag == "1" || string.Equals(onlyFlag, "true", StringComparison.OrdinalIgnoreCase);
			return favouriteRecipes;
		}

		public bool Contains(string? key)
		{
			if (key != null)
			{
				return keys.Contains(key);
			}
			return false;
		}

		public bool Is(string? key, bool enabled)
		{
			if (enabled)
			{
				return Contains(key);
			}
			return false;
		}

		public bool OnlyFavourites(bool enabled)
		{
			if (enabled)
			{
				return OnlyFlag;
			}
			return false;
		}

		public bool Toggle(string? key)
		{
			string text = Clean(key);
			if (text.Length == 0)
			{
				return false;
			}
			if (keys.Remove(text))
			{
				order.Remove(text);
				if (order.Count == 0)
				{
					OnlyFlag = false;
				}
				return false;
			}
			Add(text);
			return true;
		}

		public OnlyToggle ToggleOnly()
		{
			if (OnlyFlag)
			{
				OnlyFlag = false;
				return OnlyToggle.Off;
			}
			if (order.Count == 0)
			{
				return OnlyToggle.RefusedNoFavourites;
			}
			OnlyFlag = true;
			return OnlyToggle.On;
		}

		public int Clear()
		{
			int count = order.Count;
			order.Clear();
			keys.Clear();
			OnlyFlag = false;
			return count;
		}

		public string? SerializeSet()
		{
			if (order.Count <= 0)
			{
				return null;
			}
			return string.Join(",", order);
		}

		public string? SerializeOnly()
		{
			if (!OnlyFlag)
			{
				return null;
			}
			return "1";
		}

		private void Add(string key)
		{
			if (key.Length > 0 && keys.Add(key))
			{
				order.Add(key);
			}
		}

		private static string Clean(string? key)
		{
			return (key ?? "").Replace(",", "").Replace("|", "").Trim();
		}
	}
	[Flags]
	public enum RecipeCategory
	{
		None = 0,
		Ammo = 1,
		Weapons = 2,
		Bows = 4,
		Armor = 8,
		Shields = 0x10,
		Tools = 0x20,
		Food = 0x40,
		Materials = 0x80
	}
	public static class RecipeCategories
	{
		public static IReadOnlyList<RecipeCategory> All { get; } = new RecipeCategory[8]
		{
			RecipeCategory.Ammo,
			RecipeCategory.Weapons,
			RecipeCategory.Bows,
			RecipeCategory.Armor,
			RecipeCategory.Shields,
			RecipeCategory.Tools,
			RecipeCategory.Food,
			RecipeCategory.Materials
		};

		public static RecipeCategory Toggle(RecipeCategory picked, RecipeCategory category)
		{
			return picked ^ category;
		}

		public static bool IsPicked(RecipeCategory picked, RecipeCategory category)
		{
			return (picked & category) != 0;
		}

		public static bool Shows(RecipeCategory picked, RecipeCategory category)
		{
			if (picked != RecipeCategory.None)
			{
				return (picked & category) != 0;
			}
			return true;
		}
	}
	public sealed class RecipeMaterial
	{
		public string Name { get; }

		public string PrefabName { get; }

		public int Amount { get; }

		public bool UpgraderResource { get; }

		public RecipeMaterial(string? name, string? prefabName, int amount, bool upgraderResource)
		{
			Name = name ?? "";
			PrefabName = prefabName ?? "";
			Amount = amount;
			UpgraderResource = upgraderResource;
		}
	}
	public sealed class RecipeFacts
	{
		private readonly string?[] searchText = new string[2];

		public string Key { get; }

		public string Name { get; }

		public string PrefabName { get; }

		public IReadOnlyList<RecipeMaterial> Materials { get; }

		public bool CanCraft { get; }

		public int SortWeight { get; }

		public int ItemQuality { get; }

		public RecipeCategory Category { get; }

		public RecipeFacts(string key, string? name, string? prefabName, IReadOnlyList<RecipeMaterial>? materials, bool canCraft = true, int sortWeight = 0, int itemQuality = 0, RecipeCategory category = RecipeCategory.None)
		{
			Key = key ?? "";
			Name = name ?? "";
			PrefabName = prefabName ?? "";
			Materials = materials ?? Array.Empty<RecipeMaterial>();
			CanCraft = canCraft;
			SortWeight = sortWeight;
			ItemQuality = itemQuality;
			Category = category;
		}

		internal string SearchText(bool ignoreAccents)
		{
			int num = (ignoreAccents ? 1 : 0);
			ref string reference = ref searchText[num];
			return reference ?? (reference = RecipeText.ItemText(Name, PrefabName, ignoreAccents));
		}

		public override string ToString()
		{
			return Key;
		}
	}
	public static class RecipeKeys
	{
		public static string Of(string? recipeName, string? itemPrefabName)
		{
			return ((!string.IsNullOrEmpty(recipeName)) ? recipeName : (itemPrefabName ?? "")).Replace(",", "").Replace("|", "").Trim();
		}
	}
	public sealed class RecipeKeyIndex<T> where T : class
	{
		private readonly Dictionary<string, T> byKey = new Dictionary<string, T>(StringComparer.Ordinal);

		private readonly Func<T, string?> keyOf;

		private readonly Func<T, bool> usable;

		private object? indexed;

		private int indexedCount = -1;

		public int Rebuilds { get; private set; }

		public RecipeKeyIndex(Func<T, string?> keyOf, Func<T, bool> usable)
		{
			this.keyOf = keyOf ?? throw new ArgumentNullException("keyOf");
			this.usable = usable ?? throw new ArgumentNullException("usable");
		}

		public T? Find(object? database, IReadOnlyList<T>? recipes, string? key)
		{
			if (database == null || recipes == null || string.IsNullOrEmpty(key))
			{
				return null;
			}
			if (database != indexed || recipes.Count != indexedCount)
			{
				Index(database, recipes);
			}
			if (!byKey.TryGetValue(key, out var value) || value == null || !usable(value))
			{
				return null;
			}
			return value;
		}

		private void Index(object database, IReadOnlyList<T> recipes)
		{
			byKey.Clear();
			indexed = database;
			indexedCount = recipes.Count;
			Rebuilds++;
			foreach (T recipe in recipes)
			{
				if (recipe != null && usable(recipe))
				{
					string text = keyOf(recipe) ?? "";
					if (text.Length > 0 && !byKey.ContainsKey(text))
					{
						byKey[text] = recipe;
					}
				}
			}
		}
	}
	public static class RecipeNeeds
	{
		public static bool Counts(RecipeMaterial? material, bool atUpgrader)
		{
			if (material != null && material.PrefabName.Length > 0 && material.UpgraderResource == atUpgrader)
			{
				return material.Amount > 0;
			}
			return false;
		}
	}
	public sealed class RecipeListState
	{
		public RecipeQuery Query { get; }

		public FavouriteRecipes Favourites { get; }

		public RecipeSort Sort { get; }

		public bool FavouritesEnabled { get; }

		public bool FavouritesFirst { get; }

		public bool AtUpgrader { get; }

		public CultureInfo? NameCulture { get; }

		public RecipeCategory Categories { get; }

		public RecipeListState(RecipeQuery query, FavouriteRecipes favourites, RecipeSort sort, bool favouritesEnabled, bool favouritesFirst, bool atUpgrader, CultureInfo? nameCulture = null, RecipeCategory categories = RecipeCategory.None)
		{
			Query = query ?? throw new ArgumentNullException("query");
			Favourites = favourites ?? throw new ArgumentNullException("favourites");
			Sort = sort;
			FavouritesEnabled = favouritesEnabled;
			FavouritesFirst = favouritesFirst;
			AtUpgrader = atUpgrader;
			NameCulture = nameCulture;
			Categories = categories;
		}
	}
	public readonly struct PipelineResult
	{
		public int Dropped { get; }

		public bool Reordered { get; }

		public PipelineResult(int dropped, bool reordered)
		{
			Dropped = dropped;
			Reordered = reordered;
		}
	}
	public static class RecipePipeline
	{
		public static PipelineResult Apply<T>(IList<T> rows, Func<T, RecipeFacts?> describe, RecipeListState state, Action<T>? dropped)
		{
			if (rows == null)
			{
				throw new ArgumentNullException("rows");
			}
			if (describe == null)
			{
				throw new ArgumentNullException("describe");
			}
			if (state == null)
			{
				throw new ArgumentNullException("state");
			}
			int dropped2 = Filter(rows, describe, state, dropped);
			bool flag = false;
			if (state.Sort == RecipeSort.NameDescending)
			{
				CultureInfo culture = state.NameCulture ?? CultureInfo.CurrentCulture;
				flag |= Reorder(rows, describe, Comparer<RecipeFacts>.Create((RecipeFacts? a, RecipeFacts? b) => RecipeSorts.CompareDescending(a, b, culture)));
			}
			if (state.FavouritesEnabled && state.FavouritesFirst)
			{
				FavouriteRecipes favourites = state.Favourites;
				flag |= Reorder(rows, describe, Comparer<RecipeFacts>.Create((RecipeFacts? a, RecipeFacts? b) => Rank(favourites, a).CompareTo(Rank(favourites, b))));
			}
			return new PipelineResult(dropped2, flag);
		}

		private static int Filter<T>(IList<T> rows, Func<T, RecipeFacts?> describe, RecipeListState state, Action<T>? dropped)
		{
			bool flag = state.Favourites.OnlyFavourites(state.FavouritesEnabled);
			if (state.Query.Empty && !flag && state.Categories == RecipeCategory.None)
			{
				return 0;
			}
			int num = 0;
			for (int num2 = rows.Count - 1; num2 >= 0; num2--)
			{
				T val = rows[num2];
				RecipeFacts recipeFacts = describe(val);
				if ((flag && !state.Favourites.Contains(recipeFacts?.Key)) || !RecipeCategories.Shows(state.Categories, recipeFacts?.Category ?? RecipeCategory.None) || !state.Query.Matches(recipeFacts, state.AtUpgrader))
				{
					dropped?.Invoke(val);
					rows.RemoveAt(num2);
					num++;
				}
			}
			return num;
		}

		private static int Rank(FavouriteRecipes favourites, RecipeFacts? facts)
		{
			return (!favourites.Contains(facts?.Key)) ? 1 : 0;
		}

		private static bool Reorder<T>(IList<T> rows, Func<T, RecipeFacts?> describe, IComparer<RecipeFacts?> comparer)
		{
			if (rows.Count < 2)
			{
				return false;
			}
			List<T> list = rows.ToList();
			List<RecipeFacts?> facts = list.Select(describe).ToList();
			int[] array = Enumerable.Range(0, list.Count).OrderBy<int, RecipeFacts>((int i) => facts[i], comparer).ToArray();
			bool result = false;
			for (int num = 0; num < array.Length; num++)
			{
				if (array[num] != num)
				{
					result = true;
				}
				rows[num] = list[array[num]];
			}
			return result;
		}
	}
	public sealed class RecipeQuery
	{
		public static readonly RecipeQuery All = new RecipeQuery(ignoreAccents: true);

		private readonly List<string> names = new List<string>();

		private readonly List<string> materials = new List<string>();

		private readonly List<string> notNames = new List<string>();

		private readonly List<string> notMaterials = new List<string>();

		public bool IgnoreAccents { get; }

		public bool Empty => names.Count + materials.Count + notNames.Count + notMaterials.Count == 0;

		public IReadOnlyList<string> Names => names;

		public IReadOnlyList<string> Materials => materials;

		public IReadOnlyList<string> NotNames => notNames;

		public IReadOnlyList<string> NotMaterials => notMaterials;

		private RecipeQuery(bool ignoreAccents)
		{
			IgnoreAccents = ignoreAccents;
		}

		public static RecipeQuery Parse(string? text, bool ignoreAccents = true)
		{
			RecipeQuery recipeQuery = new RecipeQuery(ignoreAccents);
			if (string.IsNullOrEmpty(text))
			{
				return recipeQuery;
			}
			string[] array = text.Split(' ', '\t');
			foreach (string text2 in array)
			{
				recipeQuery.Add(text2.Trim());
			}
			return recipeQuery;
		}

		private void Add(string word)
		{
			bool flag = word.StartsWith("-");
			if (flag)
			{
				word = word.Substring(1);
			}
			bool flag2 = word.StartsWith("@");
			if (flag2)
			{
				word = word.Substring(1);
			}
			word = RecipeText.Fold(word, IgnoreAccents);
			if (word.Length != 0)
			{
				((!flag2) ? (flag ? notNames : names) : (flag ? notMaterials : materials)).Add(word);
			}
		}

		public bool Matches(RecipeFacts? recipe, bool atUpgrader)
		{
			if (Empty)
			{
				return true;
			}
			if (recipe == null)
			{
				return false;
			}
			string text = recipe.SearchText(IgnoreAccents);
			if (!AllIn(names, text) || AnyIn(notNames, text))
			{
				return false;
			}
			if (materials.Count == 0 && notMaterials.Count == 0)
			{
				return true;
			}
			List<string> held = MaterialTexts(recipe, atUpgrader);
			foreach (string word in materials)
			{
				if (!held.Exists((string text2) => text2.Contains(word)))
				{
					return false;
				}
			}
			return !notMaterials.Exists((string value) => held.Exists((string text2) => text2.Contains(value)));
		}

		private static bool AllIn(List<string> words, string text)
		{
			return words.TrueForAll(text.Contains);
		}

		private static bool AnyIn(List<string> words, string text)
		{
			return words.Exists(text.Contains);
		}

		private List<string> MaterialTexts(RecipeFacts recipe, bool atUpgrader)
		{
			List<string> list = new List<string>();
			foreach (RecipeMaterial material in recipe.Materials)
			{
				if (RecipeNeeds.Counts(material, atUpgrader))
				{
					list.Add(RecipeText.ItemText(material.Name, material.PrefabName, IgnoreAccents));
				}
			}
			return list;
		}
	}
	public enum RecipeSort
	{
		Default,
		NameAscending,
		NameDescending,
		Type,
		Weight
	}
	public static class RecipeSorts
	{
		public const string GameKey = "sortcraft";

		public const string DescendingKey = "kindle_sort_desc";

		public const string CraftingSearchDescendingKey = "craftingsearch_desc";

		private static readonly RecipeSort[] cycle = new RecipeSort[5]
		{
			RecipeSort.Default,
			RecipeSort.NameAscending,
			RecipeSort.NameDescending,
			RecipeSort.Type,
			RecipeSort.Weight
		};

		public static IReadOnlyList<RecipeSort> Cycle => cycle;

		public static RecipeSort Next(RecipeSort mode)
		{
			return cycle[(Index(mode) + 1) % cycle.Length];
		}

		public static RecipeSort Previous(RecipeSort mode)
		{
			return cycle[(Index(mode) + cycle.Length - 1) % cycle.Length];
		}

		private static int Index(RecipeSort mode)
		{
			return Math.Max(0, Array.IndexOf(cycle, mode));
		}

		public static RecipeSort FromStored(string? gameMethod, bool descending)
		{
			if (string.IsNullOrEmpty(gameMethod))
			{
				return RecipeSort.Default;
			}
			if (string.Equals(gameMethod, "Name", StringComparison.OrdinalIgnoreCase))
			{
				if (!descending)
				{
					return RecipeSort.NameAscending;
				}
				return RecipeSort.NameDescending;
			}
			if (string.Equals(gameMethod, "Type", StringComparison.OrdinalIgnoreCase))
			{
				return RecipeSort.Type;
			}
			if (string.Equals(gameMethod, "Weight", StringComparison.OrdinalIgnoreCase))
			{
				return RecipeSort.Weight;
			}
			return RecipeSort.Default;
		}

		public static (string? Game, bool Descending) ToStored(RecipeSort mode)
		{
			return mode switch
			{
				RecipeSort.NameAscending => (Game: "Name", Descending: false), 
				RecipeSort.NameDescending => (Game: "Name", Descending: true), 
				RecipeSort.Type => (Game: "Type", Descending: false), 
				RecipeSort.Weight => (Game: "Weight", Descending: false), 
				_ => (Game: null, Descending: false), 
			};
		}

		public static string Label(RecipeSort mode)
		{
			return mode switch
			{
				RecipeSort.NameAscending => "Sort: A-Z", 
				RecipeSort.NameDescending => "Sort: Z-A", 
				RecipeSort.Type => "Sort: Type", 
				RecipeSort.Weight => "Sort: Weight", 
				_ => "Sort: Default", 
			};
		}

		public static int CompareDescending(RecipeFacts? a, RecipeFacts? b, CultureInfo? culture = null)
		{
			if (a == null || b == null)
			{
				if (a != null)
				{
					return -1;
				}
				return (b != null) ? 1 : 0;
			}
			int num = b.CanCraft.CompareTo(a.CanCraft);
			if (num == 0)
			{
				num = a.SortWeight.CompareTo(b.SortWeight);
			}
			if (num == 0)
			{
				num = (culture ?? CultureInfo.CurrentCulture).CompareInfo.Compare(b.Name, a.Name, CompareOptions.None);
			}
			if (num == 0)
			{
				num = b.ItemQuality.CompareTo(a.ItemQuality);
			}
			return num;
		}

		public static List<RecipeFacts> SortDescending(IEnumerable<RecipeFacts> rows, CultureInfo? culture = null)
		{
			CultureInfo used = culture ?? CultureInfo.CurrentCulture;
			return rows.OrderBy((RecipeFacts row) => row, Comparer<RecipeFacts>.Create((RecipeFacts a, RecipeFacts b) => CompareDescending(a, b, used))).ToList();
		}
	}
	public static class RecipeText
	{
		public static string Fold(string? text, bool ignoreAccents)
		{
			if (string.IsNullOrEmpty(text))
			{
				return "";
			}
			string text2 = text.ToLowerInvariant();
			if (!ignoreAccents)
			{
				return text2;
			}
			string text3 = text2.Normalize(NormalizationForm.FormD);
			StringBuilder stringBuilder = new StringBuilder(text3.Length);
			string text4 = text3;
			foreach (char c in text4)
			{
				if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
		}

		public static string ItemText(string? name, string? prefabName, bool ignoreAccents)
		{
			return Fold(name, ignoreAccents) + "\n" + Fold(prefabName, ignoreAccents);
		}
	}
	public readonly struct SearchButtonsState : IEquatable<SearchButtonsState>
	{
		public object? Row { get; }

		public bool Only { get; }

		public int View { get; }

		public bool ViewLocked { get; }

		public int Sort { get; }

		public long Revision { get; }

		public SearchButtonsState(object? row, bool only, int view, bool viewLocked, int sort, long revision)
		{
			Row = row;
			Only = only;
			View = view;
			ViewLocked = viewLocked;
			Sort = sort;
			Revision = revision;
		}

		public bool Equals(SearchButtonsState other)
		{
			if (Row != null && Row == other.Row && Only == other.Only && View == other.View && ViewLocked == other.ViewLocked && Sort == other.Sort)
			{
				return Revision == other.Revision;
			}
			return false;
		}

		public override bool Equals(object? obj)
		{
			if (obj is SearchButtonsState other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return HashCode.Combine(Row, Only, View, ViewLocked, Sort, Revision);
		}
	}
	public readonly struct TrackLabelState : IEquatable<TrackLabelState>
	{
		public object? Button { get; }

		public bool Tracked { get; }

		public long Revision { get; }

		public TrackLabelState(object? button, bool tracked, long revision)
		{
			Button = button;
			Tracked = tracked;
			Revision = revision;
		}

		public bool Equals(TrackLabelState other)
		{
			if (Button != null && Button == other.Button && Tracked == other.Tracked)
			{
				return Revision == other.Revision;
			}
			return false;
		}

		public override bool Equals(object? obj)
		{
			if (obj is TrackLabelState other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return HashCode.Combine(Button, Tracked, Revision);
		}
	}
	public enum RecipeView
	{
		List,
		CompactList,
		SmallGrid,
		MediumGrid,
		LargeGrid
	}
	public static class RecipeViews
	{
		private static readonly RecipeView[] cycle = new RecipeView[5]
		{
			RecipeView.List,
			RecipeView.CompactList,
			RecipeView.SmallGrid,
			RecipeView.MediumGrid,
			RecipeView.LargeGrid
		};

		public static IReadOnlyList<RecipeView> Cycle => cycle;

		public static RecipeView Next(RecipeView view)
		{
			return cycle[(Index(view) + 1) % cycle.Length];
		}

		public static RecipeView Previous(RecipeView view)
		{
			return cycle[(Index(view) + cycle.Length - 1) % cycle.Length];
		}

		private static int Index(RecipeView view)
		{
			return Math.Max(0, Array.IndexOf(cycle, view));
		}

		public static RecipeView Parse(string? text)
		{
			RecipeView[] array = cycle;
			for (int i = 0; i < array.Length; i++)
			{
				RecipeView result = array[i];
				if (string.Equals(result.ToString(), text?.Trim(), StringComparison.OrdinalIgnoreCase))
				{
					return result;
				}
			}
			return RecipeView.List;
		}

		public static bool IsGrid(RecipeView view)
		{
			if (view != RecipeView.SmallGrid && view != RecipeView.MediumGrid)
			{
				return view == RecipeView.LargeGrid;
			}
			return true;
		}
	}
}
namespace ExtraPotions.Kindle.Config
{
	public static class KindleCheats
	{
		public static T Effective<T>(KindleSetting<T> setting, bool locked, T value)
		{
			if (setting == null)
			{
				throw new ArgumentNullException("setting");
			}
			if (setting.Scope != SettingScope.Cheat)
			{
				throw new ArgumentException(setting.Id + " is not a cheat.", "setting");
			}
			if (!locked)
			{
				return setting.Normalize(value);
			}
			return setting.Safe;
		}

		public static float CraftSpeed(bool locked, float value)
		{
			return Effective(KindleSettings.Batch.CraftSpeed, locked, value);
		}

		public static bool InstantCrafting(bool locked, bool value)
		{
			return Effective(KindleSettings.Batch.InstantCrafting, locked, value);
		}

		public static float CraftDuration(float gameSeconds, float speed, bool instant)
		{
			if (!instant)
			{
				return CraftDuration(gameSeconds, speed);
			}
			return 0f;
		}

		public static float CraftDuration(float gameSeconds, float speed)
		{
			if (!(gameSeconds > 0f) || float.IsInfinity(gameSeconds))
			{
				if (!(gameSeconds > 0f))
				{
					return 0f;
				}
				return gameSeconds;
			}
			return gameSeconds / CraftSpeed(locked: false, speed);
		}
	}
	public static class KindleDefaultsMigration
	{
		public const int Schema = 1;

		public static readonly IReadOnlyList<KeyValuePair<KindleSetting<string>, string>> Changes = new KeyValuePair<KindleSetting<string>, string>[3]
		{
			new KeyValuePair<KindleSetting<string>, string>(KindleSettings.RecipeList.FavouriteRecipeKey, "F"),
			new KeyValuePair<KindleSetting<string>, string>(KindleSettings.Salvage.SalvageKey, "Backspace"),
			new KeyValuePair<KindleSetting<string>, string>(KindleSettings.RecipeList.GamepadSortButton, "JoyLStick")
		};

		public static string? Migrate(KindleSetting<string> setting, string? stored)
		{
			if (setting == null)
			{
				throw new ArgumentNullException("setting");
			}
			foreach (KeyValuePair<KindleSetting<string>, string> change in Changes)
			{
				if (change.Key == setting)
				{
					return string.Equals(stored, change.Value, StringComparison.Ordinal) ? setting.Default : null;
				}
			}
			return null;
		}
	}
	public enum SettingScope
	{
		Local,
		ServerAuthoritative,
		Cheat
	}
	public enum SalvageRounding
	{
		Floor,
		Round,
		Ceil
	}
	public enum TrackerFont
	{
		Sans,
		Serif,
		Norse
	}
	public abstract class KindleSetting
	{
		private static readonly IReadOnlyList<string> NoChoices = Array.Empty<string>();

		public string Section { get; }

		public string Key { get; }

		public string Id => Section + "." + Key;

		public SettingScope Scope { get; }

		public string Description { get; }

		public bool Lockable => false;

		public IReadOnlyList<string> Choices { get; }

		public abstract Type ValueType { get; }

		public abstract object DefaultValue { get; }

		public abstract object? SafeValue { get; }

		public abstract object? Minimum { get; }

		public abstract object? Maximum { get; }

		private protected KindleSetting(string section, string key, SettingScope scope, string description, IReadOnlyList<string>? choices)
		{
			if (string.IsNullOrWhiteSpace(section) || section.Trim() != section)
			{
				throw new ArgumentException("Expected a trimmed section name.", "section");
			}
			if (string.IsNullOrWhiteSpace(key) || key.Trim() != key)
			{
				throw new ArgumentException("Expected a trimmed key.", "key");
			}
			if (!Enum.IsDefined(typeof(SettingScope), scope))
			{
				throw new ArgumentException("Unknown scope.", "scope");
			}
			if (string.IsNullOrWhiteSpace(description))
			{
				throw new ArgumentException("Expected a description.", "description");
			}
			Section = section;
			Key = key;
			Scope = scope;
			Description = description;
			Choices = choices ?? NoChoices;
		}

		public abstract object NormalizeBoxed(object? value);

		public override string ToString()
		{
			return Id + " (" + Scope.ToString() + ")";
		}

		public static KindleSetting<bool> Toggle(string section, string key, bool defaultValue, SettingScope scope, string description, bool? safe = null)
		{
			return new KindleSetting<bool>(section, key, scope, description, defaultValue, safe, null, (bool v) => v);
		}

		public static KindleSetting<int> Integer(string section, string key, int defaultValue, int min, int max, SettingScope scope, string description, int? safe = null)
		{
			if (min > max)
			{
				throw new ArgumentException("Minimum above maximum.", "min");
			}
			return new KindleSetting<int>(section, key, scope, description, defaultValue, safe, (min, max), (int v) => Math.Min(max, Math.Max(min, v)));
		}

		public static KindleSetting<float> Number(string section, string key, float defaultValue, float min, float max, SettingScope scope, string description, float? safe = null)
		{
			if (!(min <= max) || float.IsInfinity(min) || float.IsInfinity(max))
			{
				throw new ArgumentException("Expected a finite range.", "min");
			}
			return new KindleSetting<float>(section, key, scope, description, defaultValue, safe, (min, max), (float v) => (!float.IsNaN(v) && !float.IsInfinity(v)) ? Math.Min(max, Math.Max(min, v)) : defaultValue);
		}

		public static KindleSetting<TEnum> Choice<TEnum>(string section, string key, TEnum defaultValue, SettingScope scope, string description) where TEnum : struct, Enum
		{
			return new KindleSetting<TEnum>(section, key, scope, description, defaultValue, null, null, (TEnum v) => (!Enum.IsDefined(typeof(TEnum), v)) ? defaultValue : v, Enum.GetNames(typeof(TEnum)));
		}

		public static KindleSetting<string> Text(string section, string key, string defaultValue, SettingScope scope, string description, Func<string, string> normalize)
		{
			if (normalize == null)
			{
				throw new ArgumentNullException("normalize");
			}
			return new KindleSetting<string>(section, key, scope, description, defaultValue, null, null, normalize);
		}
	}
	public sealed class KindleSetting<T> : KindleSetting
	{
		private readonly Func<T, T> normalize;

		private readonly bool hasSafe;

		private readonly (T Min, T Max)? range;

		public T Default { get; }

		public T Safe { get; }

		public override Type ValueType => typeof(T);

		public override object DefaultValue => Default;

		public override object? SafeValue
		{
			get
			{
				if (!hasSafe)
				{
					return null;
				}
				return Safe;
			}
		}

		public override object? Minimum
		{
			get
			{
				if (!range.HasValue)
				{
					return null;
				}
				return range.Value.Min;
			}
		}

		public override object? Maximum
		{
			get
			{
				if (!range.HasValue)
				{
					return null;
				}
				return range.Value.Max;
			}
		}

		internal KindleSetting(string section, string key, SettingScope scope, string description, T defaultValue, object? safe, (T, T)? range, Func<T, T> normalize, IReadOnlyList<string>? choices = null)
			: base(section, key, scope, description, choices)
		{
			this.normalize = normalize ?? throw new ArgumentNullException("normalize");
			this.range = range;
			if (!EqualityComparer<T>.Default.Equals(normalize(defaultValue), defaultValue))
			{
				throw new ArgumentException(base.Id + ": the default is outside its own rule.", "defaultValue");
			}
			Default = defaultValue;
			if (scope == SettingScope.Cheat)
			{
				if (safe == null)
				{
					throw new ArgumentException(base.Id + ": a cheat needs a safe value.", "safe");
				}
				if (!EqualityComparer<T>.Default.Equals(defaultValue, (T)safe))
				{
					throw new ArgumentException(base.Id + ": a cheat must default to its safe value.", "defaultValue");
				}
				Safe = (T)safe;
				hasSafe = true;
			}
			else
			{
				if (safe != null)
				{
					throw new ArgumentException(base.Id + ": only cheats have a safe value.", "safe");
				}
				Safe = defaultValue;
			}
		}

		public T Normalize(T value)
		{
			return normalize(value);
		}

		public override object NormalizeBoxed(object? value)
		{
			return (value is T value2) ? Normalize(value2) : Default;
		}
	}
	public static class KindleSettings
	{
		public static class RecipeList
		{
			public const string Section = "Recipe List";

			public static readonly KindleSetting<bool> Search = KindleSetting.Toggle("Recipe List", "Search", defaultValue: true, SettingScope.Local, "Show a search row above the recipe list on the Craft and Upgrade tabs.");

			public static readonly KindleSetting<string> SearchKey = KindleSetting.Text("Recipe List", "Search Key", "F + LeftControl", SettingScope.Local, "Focuses the search field (or opens Steam's on-screen keyboard). Empty: no key.", Shortcut);

			public static readonly KindleSetting<bool> ClearSearchOnClose = KindleSetting.Toggle("Recipe List", "Clear Search On Close", defaultValue: true, SettingScope.Local, "Clear the search text when the inventory closes.");

			public static readonly KindleSetting<bool> IgnoreAccents = KindleSetting.Toggle("Recipe List", "Ignore Accents", defaultValue: true, SettingScope.Local, "Search ignores accent marks, so plain letters also find accented names.");

			public static readonly KindleSetting<bool> Categories = KindleSetting.Toggle("Recipe List", "Categories", defaultValue: true, SettingScope.Local, "A row of category buttons under the search: Ammo, Weapons, Bows, Armor, Shields, Tools, Food and Materials. Click one to list only its recipes, click more to add them, click a lit one to take it away; with none lit every recipe shows.");

			public static readonly KindleSetting<bool> Favourites = KindleSetting.Toggle("Recipe List", "Favorites", defaultValue: true, SettingScope.Local, "Allow marking recipes as favorites (middle click, the favorite key or the star button).");

			public static readonly KindleSetting<bool> FavouritesFirst = KindleSetting.Toggle("Recipe List", "Favorites First", defaultValue: true, SettingScope.Local, "List favorite recipes before the others, keeping the chosen sort within each group.");

			public static readonly KindleSetting<string> FavouriteRecipeKey = KindleSetting.Text("Recipe List", "Favorite Recipe Key", "", SettingScope.Local, "Marks or unmarks the recipe under the pointer. Acts only over a recipe row. Unbound by default; middle click and the star button also mark favorites.", Shortcut);

			public static readonly KindleSetting<RecipeView> RecipeView = KindleSetting.Choice("Recipe List", "Recipe View", ExtraPotions.Kindle.Recipes.RecipeView.List, SettingScope.Local, "How recipes are laid out: List, CompactList, SmallGrid, MediumGrid or LargeGrid.");

			public static readonly KindleSetting<bool> SortButton = KindleSetting.Toggle("Recipe List", "Sort Button", defaultValue: true, SettingScope.Local, "Show the sort button. Off hides the button; the stored sort (the game's sortcraft) still applies.");

			public static readonly KindleSetting<bool> GamepadControls = KindleSetting.Toggle("Recipe List", "Gamepad Controls", defaultValue: true, SettingScope.Local, "Lets a gamepad move through and use the search, sort and favorite controls of the recipe list.");

			public static readonly KindleSetting<string> GamepadSortButton = KindleSetting.Text("Recipe List", "Gamepad Sort Button", "JoyBack", SettingScope.Local, "Gamepad button that cycles the sort while the crafting panel is selected (a Crucible pad button name). Default Back, which the game leaves free in the inventory; holding the left stick stays the game's multi-craft modifier. Empty: off.", Shortcut);
		}

		public static class Batch
		{
			public const string Section = "Batch Crafting";

			public static readonly KindleSetting<bool> Enabled = KindleSetting.Toggle("Batch Crafting", "Enabled", defaultValue: true, SettingScope.ServerAuthoritative, "Show the amount stepper left of Craft; Craft makes that many through the game's own multi-craft, at the same cost per item.");

			public static readonly KindleSetting<int> MaxAmount = KindleSetting.Integer("Batch Crafting", "Max Amount", 100, 1, 1000, SettingScope.ServerAuthoritative, "The most one press of Craft makes. Materials and free inventory space still limit the amount.");

			public static readonly KindleSetting<float> CraftSpeed = KindleSetting.Number("Batch Crafting", "Craft Speed", 1f, 0.1f, 10f, SettingScope.Cheat, "Cheat. How fast crafting completes: 2 takes half the game's time. Reads 1 whenever the server blocks cheats.", 1f);

			public static readonly KindleSetting<bool> InstantCrafting = KindleSetting.Toggle("Batch Crafting", "Instant Crafting", defaultValue: false, SettingScope.Cheat, "Cheat. Every craft and batch finishes at once, ignoring Craft Speed. Off whenever the server blocks cheats.", false);
		}

		public static class Repair
		{
			public const string Section = "Repair";

			public static readonly KindleSetting<bool> OnStationOpen = KindleSetting.Toggle("Repair", "Repair On Station Open", defaultValue: false, SettingScope.Local, "Opening a usable crafting station repairs all carried worn items that station can repair, using the same free repair-all action. Off by default.");
		}

		public static class Tracker
		{
			public const string Section = "Recipe Tracker";

			public static readonly KindleSetting<bool> Enabled = KindleSetting.Toggle("Recipe Tracker", "Enabled", defaultValue: true, SettingScope.Local, "Show tracked recipes and their materials on the HUD.");

			public static readonly KindleSetting<int> MaxTracked = KindleSetting.Integer("Recipe Tracker", "Max Tracked", 6, 1, 12, SettingScope.Local, "The most recipes tracked at once.");

			public static readonly KindleSetting<bool> CountNearbyChests = KindleSetting.Toggle("Recipe Tracker", "Count Nearby Chests", defaultValue: true, SettingScope.Local, "Count materials in nearby containers. Needs Burrow; without it only carried items count.");

			public static readonly KindleSetting<bool> UntrackWhenCrafted = KindleSetting.Toggle("Recipe Tracker", "Untrack When Crafted", defaultValue: true, SettingScope.Local, "Stop tracking a recipe once the tracked amount has been crafted.");

			public static readonly KindleSetting<bool> HideInCombat = KindleSetting.Toggle("Recipe Tracker", "Hide In Combat", defaultValue: true, SettingScope.Local, "Hide the tracker while in combat.");

			public static readonly KindleSetting<bool> HideWithMap = KindleSetting.Toggle("Recipe Tracker", "Hide With Map", defaultValue: true, SettingScope.Local, "Hide the tracker while the large map is open.");

			public static readonly KindleSetting<TrackerFont> Font = KindleSetting.Choice("Recipe Tracker", "Font", TrackerFont.Serif, SettingScope.Local, "Tracker font: Sans, Serif or Norse.");

			public static readonly KindleSetting<int> FontSize = KindleSetting.Integer("Recipe Tracker", "Font Size", 16, 10, 28, SettingScope.Local, "Text size of the recipe tracker on the HUD.");

			public static readonly KindleSetting<string> HaveColour = KindleSetting.Text("Recipe Tracker", "Have Color", "#FFFFFF", SettingScope.Local, "Color of materials you have enough of (HTML color, #RRGGBB or #RRGGBBAA).", (string t) => Colour(t, "#FFFFFF"));

			public static readonly KindleSetting<string> MissingColour = KindleSetting.Text("Recipe Tracker", "Missing Color", "#FF6A5A", SettingScope.Local, "Color of materials you are missing (HTML color).", (string t) => Colour(t, "#FF6A5A"));

			public static readonly KindleSetting<string> ReadyColour = KindleSetting.Text("Recipe Tracker", "Ready Color", "#FFB65C", SettingScope.Local, "Color of a recipe title once everything is gathered (HTML color).", (string t) => Colour(t, "#FFB65C"));

			public static readonly KindleSetting<float> BackgroundOpacity = KindleSetting.Number("Recipe Tracker", "Background Opacity", 1f, 0f, 1f, SettingScope.Local, "Opacity of the tracker panel background.");
		}

		public static class Salvage
		{
			public const string Section = "Salvage";

			public static readonly KindleSetting<bool> Enabled = KindleSetting.Toggle("Salvage", "Enabled", defaultValue: true, SettingScope.ServerAuthoritative, "Add a Salvage tab to crafting stations that turns unwanted gear back into materials.");

			public static readonly KindleSetting<float> ReturnFraction = KindleSetting.Number("Salvage", "Return Fraction", 0.75f, 0f, 1f, SettingScope.ServerAuthoritative, "Share of each material's total cost returned by salvage.");

			public static readonly KindleSetting<SalvageRounding> Rounding = KindleSetting.Choice("Salvage", "Rounding", SalvageRounding.Round, SettingScope.ServerAuthoritative, "How a share becomes a whole number: Floor, Round (halves up) or Ceil.");

			public static readonly KindleSetting<bool> AtLeastOne = KindleSetting.Toggle("Salvage", "At Least One", defaultValue: true, SettingScope.ServerAuthoritative, "Every material returns at least one.");

			public static readonly KindleSetting<bool> UpgradeMaterials = KindleSetting.Toggle("Salvage", "Upgrade Materials", defaultValue: true, SettingScope.ServerAuthoritative, "Include the materials spent on upgrades.");

			public static readonly KindleSetting<bool> RequireKnownRecipe = KindleSetting.Toggle("Salvage", "Require Known Recipe", defaultValue: true, SettingScope.ServerAuthoritative, "Only salvage items whose recipe the character knows. Found gear (loot, chest, trader or creature drops, which no one crafted) always counts as known, as does every recipe when the world unlocks all recipes.");

			public static readonly KindleSetting<bool> RequireStation = KindleSetting.Toggle("Salvage", "Require Station", defaultValue: false, SettingScope.ServerAuthoritative, "Only salvage at the item's own crafting station.");

			public static readonly KindleSetting<bool> SkipItemsWithModData = KindleSetting.Toggle("Salvage", "Skip Items With Mod Data", defaultValue: true, SettingScope.ServerAuthoritative, "Never salvage items carrying data from other mods (keys starting with Mod Data Prefixes).");

			public static readonly KindleSetting<string> ModDataPrefixes = KindleSetting.Text("Salvage", "Mod Data Prefixes", "ecf_", SettingScope.ServerAuthoritative, "Comma list of item data key prefixes (case-sensitive) that mark an item as carrying other mods' data.", ExtraPotions.Kindle.Config.ModDataPrefixes.Normalize);

			public static readonly KindleSetting<string> SalvageKey = KindleSetting.Text("Salvage", "Salvage Key", "", SettingScope.Local, "Salvages the item under the pointer on the Salvage tab. Unbound by default; the Salvage button does the same.", Shortcut);

			public static readonly KindleSetting<bool> ShowRarityBackgrounds = KindleSetting.Toggle("Salvage", "Show Rarity Backgrounds", defaultValue: true, SettingScope.Local, "Show rarity backgrounds on the Salvage tab (also obeys Epic Loot's own setting).");

			public static readonly KindleSetting<bool> NearbyChests = KindleSetting.Toggle("Salvage", "Nearby Chests", defaultValue: true, SettingScope.ServerAuthoritative, "The Salvage tab also lists gear in the nearby chests Burrow lets you craft from (needs Burrow: its range, wards and chest rules apply, and chests other players have open are skipped). Salvaged materials go to your inventory; what does not fit drops at your feet. Your own value applies in single player; on a server the host's value applies.");
		}

		public static class Cart
		{
			public const string Section = "Cart Workbench";

			public static readonly KindleSetting<bool> CartWorkbench = KindleSetting.Toggle("Cart Workbench", "Cart Workbench", defaultValue: false, SettingScope.Cheat, "Cheat. Every loaded cart carries a workbench; Shift + Use opens it. Off whenever the server blocks cheats.", false);

			public static readonly KindleSetting<int> CartStationLevel = KindleSetting.Integer("Cart Workbench", "Cart Station Level", 1, 1, 5, SettingScope.ServerAuthoritative, "Workbench level of a cart before extensions.");

			public static readonly KindleSetting<float> CartStationRange = KindleSetting.Number("Cart Workbench", "Cart Station Range", 10f, 1f, 50f, SettingScope.ServerAuthoritative, "Range of a cart's workbench in meters.");
		}

		public static class VirtualWorkbench
		{
			public const string Section = "Virtual Workbench";

			public static readonly KindleSetting<bool> Enabled = KindleSetting.Toggle("Virtual Workbench", "Virtual Workbench", defaultValue: false, SettingScope.ServerAuthoritative, "Host setting, off by default. Lets players reopen the crafting station they used last from anywhere it is still loaded, with Virtual Workbench Key. That station's own level, extensions, roof and fire rules apply, and crafting uses only carried materials, as at the station.");

			public static readonly KindleSetting<string> Key = KindleSetting.Text("Virtual Workbench", "Virtual Workbench Key", "", SettingScope.Local, "Your own key that reopens the crafting station you used last, when the host allows Virtual Workbench. Empty: no key.", Shortcut);
		}

		public static class Stations
		{
			public const string Section = "Crafting Stations";

			public static readonly KindleSetting<float> UseDistance = KindleSetting.Number("Crafting Stations", "Use Distance Multiplier", 1.5f, 1f, 3f, SettingScope.ServerAuthoritative, "How far you can stand from a crafting station and still use it, as a multiple of the game's distance for that station (1 is the game's). Your own value applies in single player; on a server the host's value applies.");
		}

		public static class Server
		{
			public const string Section = "Server";

			public static readonly KindleSetting<string> LockedPlayerSettings = KindleSetting.Text("Server", "Locked Player Settings", "", SettingScope.ServerAuthoritative, "Retained compatibility key. Server lock lists no longer override client-local settings.", (string t) => (t ?? "").Trim());
		}

		private static readonly Lazy<KindleSetting[]> all = new Lazy<KindleSetting[]>(() => new KindleSetting[48]
		{
			RecipeList.Search,
			RecipeList.SearchKey,
			RecipeList.ClearSearchOnClose,
			RecipeList.IgnoreAccents,
			RecipeList.Categories,
			RecipeList.Favourites,
			RecipeList.FavouritesFirst,
			RecipeList.FavouriteRecipeKey,
			RecipeList.RecipeView,
			RecipeList.SortButton,
			RecipeList.GamepadControls,
			RecipeList.GamepadSortButton,
			Batch.Enabled,
			Batch.MaxAmount,
			Batch.CraftSpeed,
			Batch.InstantCrafting,
			Repair.OnStationOpen,
			Tracker.Enabled,
			Tracker.MaxTracked,
			Tracker.CountNearbyChests,
			Tracker.UntrackWhenCrafted,
			Tracker.HideInCombat,
			Tracker.HideWithMap,
			Tracker.Font,
			Tracker.FontSize,
			Tracker.HaveColour,
			Tracker.MissingColour,
			Tracker.ReadyColour,
			Tracker.BackgroundOpacity,
			Salvage.Enabled,
			Salvage.ReturnFraction,
			Salvage.Rounding,
			Salvage.AtLeastOne,
			Salvage.UpgradeMaterials,
			Salvage.RequireKnownRecipe,
			Salvage.RequireStation,
			Salvage.SkipItemsWithModData,
			Salvage.ModDataPrefixes,
			Salvage.SalvageKey,
			Salvage.ShowRarityBackgrounds,
			Salvage.NearbyChests,
			Cart.CartWorkbench,
			Cart.CartStationLevel,
			Cart.CartStationRange,
			VirtualWorkbench.Enabled,
			VirtualWorkbench.Key,
			Stations.UseDistance,
			Server.LockedPlayerSettings
		});

		private static readonly Lazy<Dictionary<string, KindleSetting>> byId = new Lazy<Dictionary<string, KindleSetting>>(() => all.Value.ToDictionary<KindleSetting, string>((KindleSetting s) => s.Id, StringComparer.OrdinalIgnoreCase));

		public static IReadOnlyList<KindleSetting> All => all.Value;

		public static KindleSetting? Find(string? id)
		{
			if (id == null || !byId.Value.TryGetValue(id.Trim(), out KindleSetting value))
			{
				return null;
			}
			return value;
		}

		private static string Shortcut(string text)
		{
			return (text ?? "").Trim();
		}

		private static string Colour(string text, string fallback)
		{
			if (!HtmlColour.TryParse(text, out var colour))
			{
				return fallback;
			}
			return colour.ToString();
		}
	}
	public sealed class LockList
	{
		private readonly HashSet<string> locked;

		public static LockList Empty { get; } = new LockList(Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>());

		public IReadOnlyList<string> Locked { get; }

		public IReadOnlyList<string> Unknown { get; }

		public IReadOnlyList<string> NotLockable { get; }

		private LockList(IReadOnlyList<string> lockedIds, IReadOnlyList<string> unknown, IReadOnlyList<string> notLockable)
		{
			Locked = lockedIds;
			Unknown = unknown;
			NotLockable = notLockable;
			locked = new HashSet<string>(lockedIds, StringComparer.OrdinalIgnoreCase);
		}

		public static LockList Parse(string? text)
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			string[] array = (text ?? "").Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length != 0)
				{
					KindleSetting kindleSetting = KindleSettings.Find(text2);
					List<string> list4 = ((kindleSetting == null) ? list2 : (kindleSetting.Lockable ? list : list3));
					string text3 = kindleSetting?.Id ?? text2;
					if (!list4.Contains<string>(text3, StringComparer.OrdinalIgnoreCase))
					{
						list4.Add(text3);
					}
				}
			}
			if (list.Count + list2.Count + list3.Count != 0)
			{
				return new LockList(list, list2, list3);
			}
			return Empty;
		}

		public bool IsLocked(string? id)
		{
			if (id != null)
			{
				return locked.Contains(id.Trim());
			}
			return false;
		}

		public string Describe()
		{
			string text = Locked.Count + " locked";
			if (Unknown.Count > 0)
			{
				text = text + "; unknown: " + string.Join(", ", Unknown);
			}
			if (NotLockable.Count > 0)
			{
				text = text + "; not lockable: " + string.Join(", ", NotLockable);
			}
			return text;
		}
	}
	public static class LockedValues
	{
		public static string Encode(IEnumerable<KeyValuePair<string, string>> values)
		{
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			return string.Join(";", values.Select<KeyValuePair<string, string>, string>((KeyValuePair<string, string> v) => Escape(v.Key) + "=" + Escape(v.Value ?? "")));
		}

		public static IReadOnlyDictionary<string, string> Decode(string? text)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrEmpty(text))
			{
				return dictionary;
			}
			foreach (string item in Split(text, ';'))
			{
				List<string> list = Split(item, '=').ToList();
				if (list.Count == 2)
				{
					string text2 = Unescape(list[0]);
					string text3 = Unescape(list[1]);
					if (!string.IsNullOrWhiteSpace(text2) && text3 != null && !dictionary.ContainsKey(text2.Trim()))
					{
						dictionary.Add(text2.Trim(), text3);
					}
				}
			}
			return dictionary;
		}

		public static string Compose(LockList list, Func<string, string?> ownText)
		{
			if (list == null)
			{
				throw new ArgumentNullException("list");
			}
			if (ownText == null)
			{
				throw new ArgumentNullException("ownText");
			}
			return Encode(from id in list.Locked
				select new KeyValuePair<string, string>(id, ownText(id)) into p
				where p.Value != null
				select new KeyValuePair<string, string>(p.Key, p.Value));
		}

		private static string Escape(string text)
		{
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			foreach (char c in text)
			{
				if (c == '\\' || c == ';' || c == '=')
				{
					stringBuilder.Append('\\');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		private static IEnumerable<string> Split(string text, char separator)
		{
			int num = 0;
			for (int i = 0; i < text.Length; i++)
			{
				if (text[i] == '\\')
				{
					i++;
				}
				else if (text[i] == separator)
				{
					yield return text.Substring(num, i - num);
					num = i + 1;
				}
			}
			yield return text.Substring(num);
		}

		private static string? Unescape(string text)
		{
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			for (int i = 0; i < text.Length; i++)
			{
				if (text[i] == '\\' && ++i >= text.Length)
				{
					return null;
				}
				stringBuilder.Append(text[i]);
			}
			return stringBuilder.ToString();
		}
	}
	public readonly struct PlayerLock
	{
		public bool Locked { get; }

		public string? ServerText { get; }

		public PlayerLock(bool locked, string? serverText)
		{
			Locked = locked;
			ServerText = (locked ? serverText : null);
		}

		public override string ToString()
		{
			if (!Locked)
			{
				return "Own";
			}
			return "Locked (" + ServerText + ")";
		}
	}
	public static class PlayerLocks
	{
		public static PlayerLock Evaluate(string id, bool serverBinds, LockList list, IReadOnlyDictionary<string, string> values)
		{
			if (list == null)
			{
				throw new ArgumentNullException("list");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			if (!serverBinds || !list.IsLocked(id) || !values.TryGetValue(id.Trim(), out string value))
			{
				return new PlayerLock(locked: false, null);
			}
			return new PlayerLock(locked: true, value);
		}
	}
	public readonly struct HtmlColour
	{
		private readonly bool hasAlpha;

		public byte R { get; }

		public byte G { get; }

		public byte B { get; }

		public byte A { get; }

		private HtmlColour(byte r, byte g, byte b, byte a, bool hasAlpha)
		{
			R = r;
			G = g;
			B = b;
			A = a;
			this.hasAlpha = hasAlpha;
		}

		public static bool TryParse(string? text, out HtmlColour colour)
		{
			colour = default(HtmlColour);
			string text2 = text?.Trim();
			if (text2 == null || text2.Length < 2 || text2[0] != '#')
			{
				return false;
			}
			string text3 = text2.Substring(1);
			if (text3.Length == 3)
			{
				text3 = new string(new char[6]
				{
					text3[0],
					text3[0],
					text3[1],
					text3[1],
					text3[2],
					text3[2]
				});
			}
			if (text3.Length != 6 && text3.Length != 8)
			{
				return false;
			}
			if (!uint.TryParse(text3, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var result))
			{
				return false;
			}
			if (text3.Length == 6)
			{
				colour = new HtmlColour((byte)(result >> 16), (byte)(result >> 8), (byte)result, byte.MaxValue, hasAlpha: false);
			}
			else
			{
				colour = new HtmlColour((byte)(result >> 24), (byte)(result >> 16), (byte)(result >> 8), (byte)result, hasAlpha: true);
			}
			return true;
		}

		public override string ToString()
		{
			return "#" + R.ToString("X2", CultureInfo.InvariantCulture) + G.ToString("X2", CultureInfo.InvariantCulture) + B.ToString("X2", CultureInfo.InvariantCulture) + (hasAlpha ? A.ToString("X2", CultureInfo.InvariantCulture) : "");
		}
	}
	public static class ModDataPrefixes
	{
		public static IReadOnlyList<string> Parse(string? text)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			List<string> list = new List<string>();
			string[] array = (text ?? "").Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length > 0 && hashSet.Add(text2))
				{
					list.Add(text2);
				}
			}
			return list;
		}

		public static string Normalize(string? text)
		{
			return string.Join(",", Parse(text));
		}

		public static bool Matches(IEnumerable<string> prefixes, string? key)
		{
			if (key != null)
			{
				return prefixes.Any((string p) => p.Length > 0 && key.StartsWith(p, StringComparison.Ordinal));
			}
			return false;
		}
	}
}

plugins/Kindle/Kindle.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExtraPotions.Kindle.Config;
using ExtraPotions.Kindle.Recipes;
using ExtraPotions.Kindle.Repair;
using ExtraPotions.Kindle.Runtime.Salvage;
using ExtraPotions.Kindle.Salvage;
using ExtraPotions.Meadworks.Contracts;
using ExtraPotions.Meadworks.Crucible;
using ExtraPotions.Meadworks.Crucible.UI;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Serialization;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ExtraPotions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")]
[assembly: AssemblyFileVersion("0.1.25.0")]
[assembly: AssemblyInformationalVersion("0.1.25")]
[assembly: AssemblyProduct("Kindle")]
[assembly: AssemblyTitle("Kindle")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.25.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 ExtraPotions.Kindle.Runtime
{
	public static class BatchAmount
	{
		private static Recipe recipe;

		public static int Value { get; private set; } = 1;

		public static Recipe Current => recipe;

		internal static void Reset()
		{
			recipe = null;
			Value = 1;
		}

		public static bool Applies(InventoryGui gui, Player player)
		{
			if (!KindleBatch.Active || SalvageTabCapability.Active || !KindleBatch.Config.Get<bool>(Batch.Enabled) || (Object)(object)gui == (Object)null || (Object)(object)player == (Object)null || !gui.InCraftTab())
			{
				return false;
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if (!((Object)(object)currentCraftingStation == (Object)null))
			{
				return !currentCraftingStation.m_upgrader;
			}
			return true;
		}

		public static void Follow(Player player, Recipe selected)
		{
			if ((Object)(object)selected != (Object)(object)recipe)
			{
				recipe = selected;
				Value = 1;
			}
			if ((Object)(object)recipe != (Object)null && Value > 1 && !CanMake(player, recipe, Value))
			{
				Value = Limit(player, recipe);
			}
		}

		public static bool CanStepUp(Player player)
		{
			if ((Object)(object)recipe != (Object)null)
			{
				return CanMake(player, recipe, Value + 1);
			}
			return false;
		}

		public static int NextCraft(InventoryGui gui, Player player)
		{
			if (Applies(gui, player))
			{
				return Value;
			}
			if (!ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyLStick") && !gui.m_touchMultiCrafting)
			{
				return 1;
			}
			return gui.m_multiCraftAmount;
		}

		public static void Set(int typed)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)recipe == (Object)null))
			{
				Value = Mathf.Clamp(typed, 1, Limit(localPlayer, recipe));
			}
		}

		public static bool CanMake(Player player, Recipe made, int amount)
		{
			if (amount <= 1)
			{
				return true;
			}
			if (amount > KindleBatch.Config.Get<int>(Batch.MaxAmount))
			{
				return false;
			}
			return BatchCheck.HaveAndFit(player, made, amount);
		}

		public static int Limit(Player player, Recipe made)
		{
			int num = 1;
			int num2 = KindleBatch.Config.Get<int>(Batch.MaxAmount);
			while (num < num2)
			{
				int num3 = (num + num2 + 1) / 2;
				if (CanMake(player, made, num3))
				{
					num = num3;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			return num;
		}
	}
	internal static class BatchCheck
	{
		private const float MaxAge = 0.25f;

		private static readonly Dictionary<int, bool> answers = new Dictionary<int, bool>();

		private static Recipe forRecipe;

		private static CraftingStation forStation;

		private static Player forPlayer;

		private static int forChange = -1;

		private static float since = float.MinValue;

		public static bool HaveAndFit(Player player, Recipe made, int amount)
		{
			Expire(player, made);
			if (answers.TryGetValue(amount, out var value))
			{
				return value;
			}
			value = Ask(player, made, amount);
			answers[amount] = value;
			return value;
		}

		private static bool Ask(Player player, Recipe made, int amount)
		{
			if (!player.NoCostCheat() && (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25)) && !player.HaveRequirements(made, false, 1, amount))
			{
				return false;
			}
			return ((Humanoid)player).GetInventory().CanAddItem(((Component)made.m_item).gameObject, made.m_amount * amount);
		}

		private static void Expire(Player player, Recipe made)
		{
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			float unscaledTime = Time.unscaledTime;
			if (!((Object)(object)made == (Object)(object)forRecipe) || !((Object)(object)currentCraftingStation == (Object)(object)forStation) || !((Object)(object)player == (Object)(object)forPlayer) || KindleBatch.InventoryChanges != forChange || !(unscaledTime - since < 0.25f))
			{
				answers.Clear();
				forRecipe = made;
				forStation = currentCraftingStation;
				forPlayer = player;
				forChange = KindleBatch.InventoryChanges;
				since = unscaledTime;
			}
		}
	}
	public static class BatchDrive
	{
		private static int gameAmount = 5;

		private static bool driving;

		private static int started;

		public static void Remember(InventoryGui gui)
		{
			gameAmount = gui.m_multiCraftAmount;
			driving = false;
			started = 0;
		}

		public static void Drive(InventoryGui gui, int amount)
		{
			gui.m_multiCraftAmount = amount;
			gui.m_touchMultiCrafting = amount > 1;
			driving = true;
		}

		public static void Release(InventoryGui gui)
		{
			if (driving)
			{
				driving = false;
				gui.m_multiCraftAmount = gameAmount;
				gui.m_touchMultiCrafting = false;
			}
		}

		public static void Started(InventoryGui gui, int amount)
		{
			started = amount;
			gui.m_multiCrafting = amount > 1;
		}

		public static void Forget()
		{
			started = 0;
		}

		public static void Restore(InventoryGui gui)
		{
			if (started > 0)
			{
				gui.m_multiCraftAmount = started;
				gui.m_multiCrafting = started > 1;
			}
		}
	}
	public static class CraftSpeed
	{
		private static float craft = 2f;

		private static float multi = 6f;

		private static float upgrader = 8f;

		private static float perLevel = 1f;

		public static void Remember(InventoryGui gui)
		{
			craft = gui.m_craftDuration;
			multi = gui.m_multiCraftDuration;
			upgrader = gui.m_upgraderDuration;
			perLevel = gui.m_upgraderDurationPerLevel;
		}

		public static void Apply(InventoryGui gui)
		{
			float craftSpeed = KindleBatch.Config.CraftSpeed;
			bool instantCrafting = KindleBatch.Config.InstantCrafting;
			gui.m_craftDuration = KindleCheats.CraftDuration(craft, craftSpeed, instantCrafting);
			gui.m_multiCraftDuration = KindleCheats.CraftDuration(multi, craftSpeed, instantCrafting);
			gui.m_upgraderDuration = KindleCheats.CraftDuration(upgrader, craftSpeed, instantCrafting);
			gui.m_upgraderDurationPerLevel = KindleCheats.CraftDuration(perLevel, craftSpeed, instantCrafting);
		}

		internal static void ApplySafe(InventoryGui gui)
		{
			gui.m_craftDuration = craft;
			gui.m_multiCraftDuration = multi;
			gui.m_upgraderDuration = upgrader;
			gui.m_upgraderDurationPerLevel = perLevel;
		}
	}
	public static class KindleBatch
	{
		internal static KindleConfig Config;

		internal static int InventoryChanges;

		private static MeadworksLog log;

		private static Harmony patches;

		private static InventoryGui owner;

		private static KitStepper stepper;

		private static RectTransform craft;

		private static Vector2 originalMin;

		private static Vector2 originalMax;

		private static float trim;

		private static bool laidOut;

		private const float CaptionPadding = 12f;

		private const float MinRowHeight = 30f;

		public static bool Active
		{
			get
			{
				if (Config != null && Plugin.GameplayAvailable && Plugin.AllowsUi && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return Object.op_Implicit((Object)(object)ZNet.instance);
				}
				return false;
			}
		}

		public static int Amount => BatchAmount.Value;

		public static bool Shown
		{
			get
			{
				if (stepper != null)
				{
					return stepper.Shown;
				}
				return false;
			}
		}

		public static int NextCraft(InventoryGui gui, Player player)
		{
			if (!Object.op_Implicit((Object)(object)gui) || !Object.op_Implicit((Object)(object)player))
			{
				return 1;
			}
			return BatchAmount.NextCraft(gui, player);
		}

		public static void Initialize(KindleConfig config, MeadworksLog logger)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Shutdown();
			Config = config;
			log = logger;
			patches = new Harmony("com.meadworks.kindle.batch");
			patches.CreateClassProcessor(typeof(KindleBatchPatches)).Patch();
			if (Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				Remember(InventoryGui.instance);
			}
		}

		internal static void Guard(Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				MeadworksLog obj = log;
				if (obj != null)
				{
					obj.Warning("Batch crafting: " + ex.GetType().Name + ": " + ex.Message);
				}
			}
		}

		internal static void Remember(InventoryGui gui)
		{
			ClearUi();
			owner = gui;
			BatchDrive.Remember(gui);
			CraftSpeed.Remember(gui);
			BatchAmount.Reset();
		}

		internal static void BeforeRecipe(InventoryGui gui, Player player)
		{
			if ((Object)(object)owner != (Object)(object)gui)
			{
				Remember(gui);
			}
			if (!Active)
			{
				BatchDrive.Release(gui);
				CraftSpeed.ApplySafe(gui);
				return;
			}
			CraftSpeed.Apply(gui);
			if (!BatchAmount.Applies(gui, player))
			{
				BatchDrive.Release(gui);
				return;
			}
			BatchAmount.Follow(player, ((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe);
			BatchDrive.Drive(gui, BatchAmount.Value);
		}

		internal static void Refresh(InventoryGui gui, Player player)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			if (!Active)
			{
				RestoreCraft();
				return;
			}
			if ((Object)(object)owner != (Object)(object)gui)
			{
				Remember(gui);
			}
			if (stepper == null && Object.op_Implicit((Object)(object)gui.m_craftButton))
			{
				craft = (RectTransform)((Component)gui.m_craftButton).transform;
				originalMin = craft.offsetMin;
				originalMax = craft.offsetMax;
				Rect rect = craft.rect;
				float height = ((Rect)(ref rect)).height;
				float num = RowHeight(craft, height);
				trim = (height - num) * 0.5f;
				stepper = KitStepper.Create((RectTransform)((Transform)craft).parent, "Kindle_batch", Vector2.zero, num, 1, 9999);
				if (stepper == null)
				{
					return;
				}
				stepper.Changed += BatchAmount.Set;
			}
			bool num2 = BatchAmount.Applies(gui, player) && gui.m_craftTimer < 0f;
			Show(num2);
			if (!num2 || stepper == null)
			{
				return;
			}
			bool flag = Object.op_Implicit((Object)(object)((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe);
			int num3 = ((!flag) ? 1 : BatchAmount.Limit(player, ((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe));
			stepper.Follow(num3);
			stepper.Set(BatchAmount.Value);
			((Selectable)stepper.Less).interactable = flag && BatchAmount.Value > 1;
			((Selectable)stepper.More).interactable = flag && BatchAmount.CanStepUp(player);
			stepper.Field.SetUsable(flag);
			stepper.PadSteps = ZInput.IsGamepadActive() && gui.m_activeGroup == 3;
			if (flag)
			{
				TMP_Text componentInChildren = ((Component)gui.m_craftButton).GetComponentInChildren<TMP_Text>(true);
				if (componentInChildren != null)
				{
					componentInChildren.text = Localization.instance.Localize("$inventory_craftbutton");
				}
			}
		}

		private static float RowHeight(RectTransform button, float native)
		{
			TMP_Text componentInChildren = ((Component)button).GetComponentInChildren<TMP_Text>(true);
			float num = (((Object)(object)componentInChildren == (Object)null) ? 0f : componentInChildren.fontSize);
			float num2 = Mathf.Max(30f, num + 12f);
			if (!(native > 0f))
			{
				return num2;
			}
			return Mathf.Min(num2, native);
		}

		private static void Show(bool show)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0094: Unknown result type (might be due to invalid IL or missing references)
			//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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			if (stepper != null && Object.op_Implicit((Object)(object)craft))
			{
				float num = (show ? (stepper.Root.sizeDelta.x + 6f) : 0f);
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(originalMin.x + num, originalMin.y + trim);
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(originalMax.x, originalMax.y - trim);
				if (craft.offsetMin != val)
				{
					craft.offsetMin = val;
				}
				if (craft.offsetMax != val2)
				{
					craft.offsetMax = val2;
				}
				laidOut = true;
				RectTransform root = stepper.Root;
				Vector2 anchorMin = (root.anchorMax = craft.anchorMin);
				root.anchorMin = anchorMin;
				root.pivot = new Vector2(0f, 0f);
				root.anchoredPosition = new Vector2(originalMin.x, originalMin.y + trim);
				float x = root.sizeDelta.x;
				Rect rect = craft.rect;
				root.sizeDelta = new Vector2(x, ((Rect)(ref rect)).height);
				stepper.Show(show);
			}
		}

		private static void RestoreCraft()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (laidOut && Object.op_Implicit((Object)(object)craft))
			{
				craft.offsetMin = originalMin;
				craft.offsetMax = originalMax;
			}
			laidOut = false;
			KitStepper obj = stepper;
			if (obj != null)
			{
				obj.Show(false);
			}
		}

		public static void Tick()
		{
			if (!Active)
			{
				RestoreCraft();
			}
			else if ((Object)(object)owner != (Object)(object)InventoryGui.instance && Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				Guard(delegate
				{
					Remember(InventoryGui.instance);
				});
			}
		}

		private static void ClearUi()
		{
			RestoreCraft();
			KitStepper obj = stepper;
			if (obj != null)
			{
				obj.Destroy();
			}
			stepper = null;
			craft = null;
			trim = 0f;
		}

		public static void Shutdown()
		{
			if (Object.op_Implicit((Object)(object)owner))
			{
				BatchDrive.Release(owner);
				CraftSpeed.ApplySafe(owner);
			}
			ClearUi();
			owner = null;
			BatchDrive.Forget();
			BatchAmount.Reset();
			Harmony obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			patches = null;
			Config = null;
			log = null;
		}
	}
	[HarmonyPatch]
	internal static class KindleBatchPatches
	{
		[HarmonyPatch(typeof(InventoryGui), "Awake")]
		[HarmonyPostfix]
		private static void Awake(InventoryGui __instance)
		{
			KindleBatch.Guard(delegate
			{
				KindleBatch.Remember(__instance);
			});
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		[HarmonyPrefix]
		private static void BeforeRecipe(InventoryGui __instance, Player player)
		{
			KindleBatch.Guard(delegate
			{
				KindleBatch.BeforeRecipe(__instance, player);
			});
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		[HarmonyPostfix]
		private static void AfterRecipe(InventoryGui __instance, Player player)
		{
			KindleBatch.Guard(delegate
			{
				KindleBatch.Refresh(__instance, player);
			});
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
		[HarmonyPrefix]
		private static void BeforePressed(InventoryGui __instance, out int __state)
		{
			__state = 0;
			BatchDrive.Forget();
			if (KindleBatch.Active && !(__instance.m_craftTimer >= 0f) && BatchAmount.Applies(__instance, Player.m_localPlayer))
			{
				BatchAmount.Follow(Player.m_localPlayer, ((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe);
				BatchDrive.Drive(__instance, BatchAmount.Value);
				__state = BatchAmount.Value;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
		[HarmonyPostfix]
		private static void AfterPressed(InventoryGui __instance, int __state)
		{
			if (__state > 0 && __instance.m_craftTimer >= 0f)
			{
				BatchDrive.Started(__instance, __state);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void BeforeCraft(InventoryGui __instance)
		{
			BatchDrive.Restore(__instance);
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyFinalizer]
		private static void AfterCraft()
		{
			BatchDrive.Forget();
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		[HarmonyPrefix]
		private static void Changed()
		{
			KindleBatch.InventoryChanges++;
		}
	}
	public static class KindleCarts
	{
		[HarmonyPatch(typeof(Vagon), "Awake")]
		private static class AwakePatch
		{
			[HarmonyPostfix]
			private static void Postfix(Vagon __instance)
			{
				Apply(__instance);
			}
		}

		[HarmonyPatch(typeof(Vagon), "Interact")]
		private static class InteractPatch
		{
			[HarmonyPrefix]
			private static bool Prefix(Vagon __instance, Humanoid character, bool hold, bool alt, ref bool __result)
			{
				if (hold || !alt || !Enabled)
				{
					return true;
				}
				Apply(__instance);
				CraftingStation component = ((Component)__instance).GetComponent<CraftingStation>();
				if (!IsCart(component))
				{
					return true;
				}
				if (!settings.TryUseCheat((KindleSetting)(object)Cart.CartWorkbench))
				{
					return true;
				}
				__result = component.Interact(character, false, false);
				return false;
			}
		}

		[HarmonyPatch(typeof(Vagon), "GetHoverText")]
		private static class HoverPatch
		{
			[HarmonyPostfix]
			private static void Postfix(Vagon __instance, ref string __result)
			{
				if (Enabled && IsCart(((Component)__instance).GetComponent<CraftingStation>()))
				{
					__result = __result + Localization.instance.Localize("\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] ") + KindleText.Text("cartcraft");
				}
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "GetLevel")]
		private static class LevelPatch
		{
			[HarmonyPostfix]
			private static void Postfix(CraftingStation __instance, ref int __result)
			{
				if (Enabled && IsCart(__instance))
				{
					__result += Math.Max(1, settings.Get<int>(Cart.CartStationLevel)) - 1;
				}
			}
		}

		private static readonly HashSet<CraftingStation> added = new HashSet<CraftingStation>();

		private static KindleConfig? settings;

		private static MeadworksLog? log;

		private static Harmony? patches;

		private static float nextScan;

		private static bool previousEnabled;

		private static float previousRange;

		internal static bool Enabled
		{
			get
			{
				if (Plugin.Ready && settings != null)
				{
					return settings.Get<bool>(Cart.CartWorkbench);
				}
				return false;
			}
		}

		public static void Initialize(KindleConfig config, MeadworksLog logger)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Shutdown();
			settings = config;
			log = logger;
			nextScan = 0f;
			settings.Changed += OnSettingsChanged;
			patches = new Harmony("com.meadworks.kindle.carts");
			Type[] array = new Type[4]
			{
				typeof(AwakePatch),
				typeof(InteractPatch),
				typeof(HoverPatch),
				typeof(LevelPatch)
			};
			foreach (Type type in array)
			{
				patches.CreateClassProcessor(type).Patch();
			}
		}

		private static void OnSettingsChanged(object sender, EventArgs args)
		{
			try
			{
				foreach (Vagon item in new List<Vagon>(Vagon.m_instances))
				{
					Apply(item);
				}
			}
			catch (Exception ex)
			{
				MeadworksLog? obj = log;
				if (obj != null)
				{
					obj.Warning("Cart station refresh refused: " + ex.GetType().Name);
				}
			}
		}

		public static void Tick()
		{
			if (settings == null)
			{
				return;
			}
			bool enabled = Enabled;
			float num = settings.Get<float>(Cart.CartStationRange);
			if (enabled == previousEnabled && num == previousRange && Time.unscaledTime < nextScan)
			{
				return;
			}
			previousEnabled = enabled;
			previousRange = num;
			nextScan = Time.unscaledTime + 0.5f;
			foreach (Vagon item in new List<Vagon>(Vagon.m_instances))
			{
				Apply(item);
			}
			added.RemoveWhere((CraftingStation station) => (Object)(object)station == (Object)null);
		}

		public static void Shutdown()
		{
			Harmony? obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			patches = null;
			if (settings != null)
			{
				settings.Changed -= OnSettingsChanged;
			}
			foreach (CraftingStation item in added)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					Object.Destroy((Object)(object)item);
				}
			}
			added.Clear();
			settings = null;
			log = null;
			previousEnabled = false;
			previousRange = 0f;
			nextScan = 0f;
		}

		internal static bool IsCart(CraftingStation station)
		{
			if (Object.op_Implicit((Object)(object)station))
			{
				return added.Contains(station);
			}
			return false;
		}

		internal static void Apply(Vagon cart)
		{
			if (settings == null || !Object.op_Implicit((Object)(object)cart) || !Object.op_Implicit((Object)(object)cart.m_nview) || cart.m_nview.GetZDO() == null)
			{
				return;
			}
			CraftingStation component = ((Component)cart).GetComponent<CraftingStation>();
			if (!Enabled)
			{
				if (IsCart(component))
				{
					added.Remove(component);
					Object.Destroy((Object)(object)component);
				}
				return;
			}
			if (Object.op_Implicit((Object)(object)component))
			{
				if (IsCart(component))
				{
					component.m_rangeBuild = settings.Get<float>(Cart.CartStationRange);
				}
				return;
			}
			GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab("piece_workbench") : null);
			CraftingStation val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentInChildren<CraftingStation>(true) : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				MeadworksLog? obj = log;
				if (obj != null)
				{
					obj.Warning("The workbench prefab has no crafting station; carts stay plain carts.");
				}
			}
			else
			{
				component = ((Component)cart).gameObject.AddComponent<CraftingStation>();
				Copy(val2, component, ((Component)cart).transform);
				added.Add(component);
			}
		}

		private static void Copy(CraftingStation from, CraftingStation to, Transform cart)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			to.m_name = from.m_name;
			to.m_icon = from.m_icon;
			to.m_discoverRange = from.m_discoverRange;
			to.m_rangeBuild = settings.Get<float>(Cart.CartStationRange);
			to.m_extraRangePerLevel = from.m_extraRangePerLevel;
			to.m_craftRequireRoof = false;
			to.m_craftRequireFire = false;
			to.m_roofCheckPoint = cart;
			to.m_connectionPoint = null;
			to.m_showBasicRecipies = from.m_showBasicRecipies;
			to.m_useDistance = Mathf.Max(from.m_useDistance, 4f);
			to.m_craftingSkill = from.m_craftingSkill;
			to.m_hoverOffset = from.m_hoverOffset;
			to.m_hasCraftTab = from.m_hasCraftTab;
			to.m_canRepair = from.m_canRepair;
			to.m_upgrader = false;
			to.m_craftItemEffects = from.m_craftItemEffects;
			to.m_craftItemDoneEffects = from.m_craftItemDoneEffects;
			to.m_repairItemDoneEffects = from.m_repairItemDoneEffects;
			to.m_craftItemDoneFailEffects = from.m_craftItemDoneFailEffects;
		}
	}
	public static class KindleStationReach
	{
		[HarmonyPatch(typeof(CraftingStation), "InUseDistance")]
		private static class DistancePatch
		{
			[HarmonyPostfix]
			private static void Postfix(CraftingStation __instance, Humanoid human, ref bool __result)
			{
				//IL_0038: 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)
				if (__result || !Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)human) || (Object)(object)human != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				try
				{
					float multiplier = Multiplier;
					if (multiplier > 1f)
					{
						__result = Vector3.Distance(((Component)human).transform.position, ((Component)__instance).transform.position) < __instance.m_useDistance * multiplier;
					}
				}
				catch (Exception ex)
				{
					KindleSalvage.Warn("Station use distance: " + ex.GetType().Name + ": " + ex.Message);
				}
			}
		}

		private static KindleConfig? settings;

		private static Harmony? patches;

		private static float Multiplier
		{
			get
			{
				if (settings == null || !Plugin.GameplayAvailable)
				{
					return 1f;
				}
				return settings.Get<float>(Stations.UseDistance);
			}
		}

		public static void Initialize(KindleConfig config)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Shutdown();
			settings = config;
			patches = new Harmony("com.meadworks.kindle.stationreach");
			patches.CreateClassProcessor(typeof(DistancePatch)).Patch();
		}

		public static void Shutdown()
		{
			Harmony? obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			patches = null;
			settings = null;
		}
	}
	public static class KindleVirtualStation
	{
		[HarmonyPatch(typeof(Player), "SetCraftingStation")]
		private static class RememberPatch
		{
			[HarmonyPostfix]
			private static void Postfix(Player __instance, CraftingStation station)
			{
				//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)
				try
				{
					if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)station) && !((Object)(object)station == (Object)(object)active) && !KindleCarts.IsCart(station))
					{
						ZNetView componentInParent = ((Component)station).GetComponentInParent<ZNetView>();
						ZDO val = ((Object.op_Implicit((Object)(object)componentInParent) && componentInParent.IsValid()) ? componentInParent.GetZDO() : null);
						if (val != null)
						{
							remembered = val.m_uid;
						}
					}
				}
				catch (Exception ex)
				{
					KindleSalvage.Warn("Virtual Workbench: " + ex.GetType().Name + ": " + ex.Message);
				}
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "InUseDistance")]
		private static class DistancePatch
		{
			[HarmonyPrefix]
			private static bool Prefix(CraftingStation __instance, Humanoid human, ref bool __result)
			{
				if ((Object)(object)active == (Object)null || (Object)(object)__instance != (Object)(object)active || (Object)(object)human != (Object)(object)Player.m_localPlayer || !Enabled)
				{
					return true;
				}
				__result = true;
				return false;
			}
		}

		private static KindleConfig? settings;

		private static Harmony? patches;

		private static ZDOID remembered = ZDOID.None;

		private static CraftingStation? active;

		internal static bool Enabled
		{
			get
			{
				if (Plugin.GameplayAvailable && settings != null)
				{
					return settings.Get<bool>(VirtualWorkbench.Enabled);
				}
				return false;
			}
		}

		public static void Initialize(KindleConfig config)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Shutdown();
			settings = config;
			patches = new Harmony("com.meadworks.kindle.virtualstation");
			patches.CreateClassProcessor(typeof(RememberPatch)).Patch();
			patches.CreateClassProcessor(typeof(DistancePatch)).Patch();
		}

		public static void Shutdown()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Release(close: true);
			Harmony? obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			patches = null;
			settings = null;
			remembered = ZDOID.None;
		}

		public static void Tick()
		{
			//IL_006c: 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)
			if (settings == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)active != (Object)null)
			{
				if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)localPlayer.GetCurrentCraftingStation() != (Object)(object)active)
				{
					active = null;
				}
				else if (!Enabled)
				{
					Release(close: true);
				}
			}
			if (!Object.op_Implicit((Object)(object)localPlayer) || InventoryGui.IsVisible() || !MeadworksInput.Allows((InputContext)0))
			{
				return;
			}
			KeyboardShortcut val = settings.Shortcut(VirtualWorkbench.Key);
			if (((KeyboardShortcut)(ref val)).IsDown())
			{
				if (!Enabled)
				{
					((Character)localPlayer).Message((MessageType)2, KindleText.Text("virtualoff"), 0, (Sprite)null, false);
				}
				else
				{
					Open(localPlayer);
				}
			}
		}

		private static void Open(Player player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!((Character)player).IsDead() && !((Character)player).IsTeleporting() && !((Character)player).InCutscene() && !((Character)player).InPlaceMode())
			{
				CraftingStation val = Find(remembered);
				if (!Object.op_Implicit((Object)(object)val))
				{
					((Character)player).Message((MessageType)2, KindleText.Text("virtualnone"), 0, (Sprite)null, false);
				}
				else if (val.CheckUsable(player, true))
				{
					active = val;
					player.SetCraftingStation(val);
					InventoryGui.instance.Show((Container)null, 3);
				}
			}
		}

		private static CraftingStation? Find(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (id == ZDOID.None || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject val = ZNetScene.instance.FindInstance(id);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return val.GetComponentInChildren<CraftingStation>();
		}

		private static void Release(bool close)
		{
			Player localPlayer = Player.m_localPlayer;
			if (close && Object.op_Implicit((Object)(object)active) && Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)localPlayer.GetCurrentCraftingStation() == (Object)(object)active)
			{
				localPlayer.SetCraftingStation((CraftingStation)null);
				if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible())
				{
					InventoryGui.instance.Hide();
				}
			}
			active = null;
		}
	}
	public sealed class KindleConfig
	{
		public const string LockedValuesKey = "Locked Player Values";

		private const string Product = "com.meadworks.kindle";

		private const float RefreshSeconds = 0.5f;

		private static readonly HashSet<KindleSetting> Shortcuts = BuildShortcuts();

		private readonly ConfigFile file;

		private readonly Dictionary<KindleSetting, ConfigEntryBase> entries = new Dictionary<KindleSetting, ConfigEntryBase>();

		private readonly Dictionary<ConfigEntryBase, KindleSetting> settingsByEntry = new Dictionary<ConfigEntryBase, KindleSetting>();

		private readonly ConfigurationManagerAttributes nearbyTag = new ConfigurationManagerAttributes();

		private float nextRefresh;

		public PadButton? GamepadSortButton
		{
			get
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				KindleSetting<string> gamepadSortButton = RecipeList.GamepadSortButton;
				string text = Get<string>(gamepadSortButton);
				if (text.Length == 0)
				{
					return null;
				}
				PadButton value = default(PadButton);
				if (GamepadMap.TryParse(text, ref value))
				{
					return value;
				}
				if (!GamepadMap.TryParse(gamepadSortButton.Default, ref value))
				{
					return null;
				}
				return value;
			}
		}

		public float CraftSpeed => Get<float>(Batch.CraftSpeed);

		public bool InstantCrafting => Get<bool>(Batch.InstantCrafting);

		public bool CartWorkbench => Get<bool>(Cart.CartWorkbench);

		public LockList Locks => LockList.Empty;

		public event EventHandler? Changed;

		private static HashSet<KindleSetting> BuildShortcuts()
		{
			_ = KindleSettings.All;
			return new HashSet<KindleSetting>
			{
				(KindleSetting)(object)RecipeList.SearchKey,
				(KindleSetting)(object)RecipeList.FavouriteRecipeKey,
				(KindleSetting)(object)Salvage.SalvageKey,
				(KindleSetting)(object)VirtualWorkbench.Key
			};
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			this.Changed?.Invoke(this, EventArgs.Empty);
		}

		private KindleConfig(ConfigFile file, MeadworksLog log)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//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)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			KindleConfig kindleConfig = this;
			this.file = file;
			bool saveOnConfigSet = file.SaveOnConfigSet;
			file.SaveOnConfigSet = false;
			try
			{
				foreach (KindleSetting item in KindleSettings.All)
				{
					BindSetting(item);
				}
				ConfigDescription description = entries[(KindleSetting)(object)Tracker.CountNearbyChests].Description;
				typeof(ConfigDescription).GetField("<Tags>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(description, description.Tags.Concat(new object[1] { nearbyTag }).ToArray());
				ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
				{
					Browsable = false,
					ReadOnly = true
				};
				ConfigFileExtensions.BindConfig<string>(file, "Server", "Locked Player Values", "", "Retained compatibility carrier. Client-local settings always use their own values.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, val);
				MeadworksConfig.EnsureSchema(file, 1, (IReadOnlyList<MigrationStep>)(object)new MigrationStep[1]
				{
					new MigrationStep(0, 1, (Action)delegate
					{
						kindleConfig.MigrateDefaults(log);
					})
				});
			}
			finally
			{
				file.SaveOnConfigSet = saveOnConfigSet;
			}
			file.Save();
			file.SettingChanged += OnSettingChanged;
		}

		public static KindleConfig Bind(ConfigFile file, MeadworksLog log)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (file == null)
			{
				throw new ArgumentNullException("file");
			}
			if (log == null)
			{
				throw new ArgumentNullException("log");
			}
			KindleConfig kindleConfig = new KindleConfig(file, log);
			foreach (KeyValuePair<KindleSetting, ConfigEntryBase> item in kindleConfig.entries.Where<KeyValuePair<KindleSetting, ConfigEntryBase>>((KeyValuePair<KindleSetting, ConfigEntryBase> p) => (int)p.Key.Scope > 0))
			{
				MeadworksBlockedOptions.Track("com.meadworks.kindle", item.Value, Map(item.Key.Scope), true);
			}
			kindleConfig.Refresh();
			log.Verbose("Configuration bound: " + Count((SettingScope)0) + " Local, " + Count((SettingScope)1) + " ServerAuthoritative, " + Count((SettingScope)2) + " Cheat.");
			return kindleConfig;
		}

		public static ConfigScope Map(SettingScope scope)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			return (ConfigScope)((int)scope switch
			{
				0 => 0, 
				1 => 1, 
				2 => 2, 
				_ => throw new ArgumentException("Unknown scope.", "scope"), 
			});
		}

		public ConfigEntryBase Entry(KindleSetting setting)
		{
			if (!entries.TryGetValue(setting ?? throw new ArgumentNullException("setting"), out ConfigEntryBase value))
			{
				throw new ArgumentException("Not a Kindle setting.", "setting");
			}
			return value;
		}

		public T Get<T>(KindleSetting<T> setting)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			if (Shortcuts.Contains((KindleSetting)(object)setting))
			{
				throw new ArgumentException(((KindleSetting)setting).Id + " is a keyboard shortcut; use Shortcut.", "setting");
			}
			ConfigEntry<T> val = (ConfigEntry<T>)(object)Entry((KindleSetting)(object)setting);
			SettingScope scope = ((KindleSetting)setting).Scope;
			if ((int)scope != 1)
			{
				if ((int)scope == 2)
				{
					return KindleCheats.Effective<T>(setting, CheatLocked(), val.Value);
				}
				return setting.Normalize(val.Value);
			}
			return setting.Normalize(MeadworksConfig.Effective<T>(val, "com.meadworks.kindle", (ConfigScope)1, setting.Default, true));
		}

		public KeyboardShortcut Shortcut(KindleSetting<string> setting)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!Shortcuts.Contains((KindleSetting)(object)setting))
			{
				throw new ArgumentException(((KindleSetting)setting).Id + " is not a keyboard shortcut.", "setting");
			}
			return ((ConfigEntry<KeyboardShortcut>)(object)Entry((KindleSetting)(object)setting)).Value;
		}

		public bool IsLocked(KindleSetting setting)
		{
			return false;
		}

		public bool TryUseCheat(KindleSetting cheat, string? label = null)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (cheat == null || (int)cheat.Scope != 2)
			{
				throw new ArgumentException("Expected a Kindle cheat.", "cheat");
			}
			return MeadworksBlockedOptions.TryUse("com.meadworks.kindle", cheat.Id, (ConfigScope)2, label, true);
		}

		public bool TryChange(KindleSetting setting, string? label = null)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (setting == null)
			{
				throw new ArgumentNullException("setting");
			}
			if ((object)setting == Tracker.CountNearbyChests && !KindleTracker.NearbyAvailable)
			{
				if ((Object)(object)MessageHud.instance != (Object)null && MeadworksHeadless.AllowsUi)
				{
					MessageHud.instance.ShowMessage((MessageType)2, KindleText.Text("needs_burrow"), 0, (Sprite)null, false, true);
				}
				return false;
			}
			if ((int)setting.Scope != 0)
			{
				return MeadworksBlockedOptions.TryEdit("com.meadworks.kindle", setting.Id, Map(setting.Scope), label, true);
			}
			return true;
		}

		public void Tick(float now)
		{
			if (!(now < nextRefresh))
			{
				nextRefresh = now + 0.5f;
				Refresh();
			}
		}

		public void Shutdown()
		{
			file.SettingChanged -= OnSettingChanged;
			this.Changed = null;
			foreach (ConfigEntryBase item in entries.Values.Where((ConfigEntryBase e) => (int)settingsByEntry[e].Scope > 0))
			{
				MeadworksBlockedOptions.Untrack(item);
			}
		}

		private void Refresh()
		{
			nearbyTag.ReadOnly = (KindleTracker.NearbyAvailable ? ((bool?)null) : new bool?(true));
		}

		private void MigrateDefaults(MeadworksLog log)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			foreach (KeyValuePair<KindleSetting<string>, string> change in KindleDefaultsMigration.Changes)
			{
				ConfigEntryBase val = entries[(KindleSetting)(object)change.Key];
				object obj;
				if (!(val is ConfigEntry<KeyboardShortcut> val2))
				{
					obj = val.BoxedValue as string;
				}
				else
				{
					KeyboardShortcut value = val2.Value;
					obj = ((KeyboardShortcut)(ref value)).Serialize();
				}
				string text = (string)obj;
				string text2 = KindleDefaultsMigration.Migrate(change.Key, text);
				if (text2 != null)
				{
					val.BoxedValue = ((val is ConfigEntry<KeyboardShortcut>) ? ((object)KeyboardShortcut.Deserialize(text2)) : text2);
					list.Add(((KindleSetting)change.Key).Id);
				}
			}
			if (list.Count > 0)
			{
				log.Info("Moved unchanged old input defaults to the new defaults: " + string.Join(", ", list) + ". Customized values were kept.");
			}
		}

		private static bool CheatLocked()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			return (int)MeadworksAuthority.Decide("com.meadworks.kindle", (ConfigScope)2, true).Source == 2;
		}

		private void BindSetting(KindleSetting setting)
		{
			//IL_0062: 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)
			ConfigEntryBase val;
			if ((object)setting == Server.LockedPlayerSettings)
			{
				val = (ConfigEntryBase)(object)MeadworksConfig.BindHidden<string>(file, setting.Section, setting.Key, (string)setting.DefaultValue, setting.Description, (ConfigScope)1, (AcceptableValueBase)null);
			}
			else if (Shortcuts.Contains(setting))
			{
				val = (ConfigEntryBase)(object)MeadworksConfig.Bind<KeyboardShortcut>(file, setting.Section, setting.Key, KeyboardShortcut.Deserialize((string)setting.DefaultValue), Describe(setting, null), Map(setting.Scope));
			}
			else if (!(setting is KindleSetting<bool> setting2))
			{
				if (!(setting is KindleSetting<int> val2))
				{
					if (!(setting is KindleSetting<float> val3))
					{
						if (!(setting is KindleSetting<string> setting3))
						{
							if (!(setting is KindleSetting<RecipeView> setting4))
							{
								if (!(setting is KindleSetting<TrackerFont> setting5))
								{
									if (!(setting is KindleSetting<SalvageRounding> setting6))
									{
										throw new NotSupportedException(setting.Id + ": unsupported value type " + setting.ValueType.Name + ".");
									}
									val = (ConfigEntryBase)(object)Bind<SalvageRounding>(setting6, null);
								}
								else
								{
									val = (ConfigEntryBase)(object)Bind<TrackerFont>(setting5, null);
								}
							}
							else
							{
								val = (ConfigEntryBase)(object)Bind<RecipeView>(setting4, null);
							}
						}
						else
						{
							val = (ConfigEntryBase)(object)Bind<string>(setting3, null);
						}
					}
					else
					{
						val = (ConfigEntryBase)(object)Bind<float>(val3, (AcceptableValueBase?)(object)new AcceptableValueRange<float>((float)((KindleSetting)val3).Minimum, (float)((KindleSetting)val3).Maximum));
					}
				}
				else
				{
					val = (ConfigEntryBase)(object)Bind<int>(val2, (AcceptableValueBase?)(object)new AcceptableValueRange<int>((int)((KindleSetting)val2).Minimum, (int)((KindleSetting)val2).Maximum));
				}
			}
			else
			{
				val = (ConfigEntryBase)(object)Bind<bool>(setting2, null);
			}
			entries.Add(setting, val);
			settingsByEntry.Add(val, setting);
		}

		private ConfigDescription Describe(KindleSetting setting, AcceptableValueBase? acceptable, string? text = null)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			ConfigDependency val = null;
			if ((object)setting == Tracker.MaxTracked || (object)setting == Tracker.CountNearbyChests || (object)setting == Tracker.HideInCombat || (object)setting == Tracker.HideWithMap || (object)setting == Tracker.Font || (object)setting == Tracker.FontSize || (object)setting == Tracker.HaveColour || (object)setting == Tracker.MissingColour || (object)setting == Tracker.ReadyColour || (object)setting == Tracker.BackgroundOpacity)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(Tracker.Enabled)), (Func<string>)(() => "Requires " + ((KindleSetting)Tracker.Enabled).Section + ": " + ((KindleSetting)Tracker.Enabled).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == RecipeList.FavouritesFirst || (object)setting == RecipeList.FavouriteRecipeKey)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(RecipeList.Favourites)), (Func<string>)(() => "Requires " + ((KindleSetting)RecipeList.Favourites).Section + ": " + ((KindleSetting)RecipeList.Favourites).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == RecipeList.SearchKey)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(RecipeList.Search)), (Func<string>)(() => "Requires " + ((KindleSetting)RecipeList.Search).Section + ": " + ((KindleSetting)RecipeList.Search).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == RecipeList.GamepadSortButton)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(RecipeList.GamepadControls)), (Func<string>)(() => "Requires " + ((KindleSetting)RecipeList.GamepadControls).Section + ": " + ((KindleSetting)RecipeList.GamepadControls).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == Batch.MaxAmount)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(Batch.Enabled)), (Func<string>)(() => "Requires " + ((KindleSetting)Batch.Enabled).Section + ": " + ((KindleSetting)Batch.Enabled).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == VirtualWorkbench.Key)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(VirtualWorkbench.Enabled)), (Func<string>)(() => "Requires " + ((KindleSetting)VirtualWorkbench.Enabled).Section + ": " + ((KindleSetting)VirtualWorkbench.Enabled).Key + "."), (Func<bool>)null);
			}
			if ((object)setting == Salvage.SalvageKey)
			{
				val = new ConfigDependency((Func<bool>)(() => Get<bool>(Salvage.Enabled)), (Func<string>)(() => "Requires " + ((KindleSetting)Salvage.Enabled).Section + ": " + ((KindleSetting)Salvage.Enabled).Key + "."), (Func<bool>)null);
			}
			return new ConfigDescription(text ?? setting.Description, acceptable, (val == null) ? Array.Empty<object>() : new object[1] { val });
		}

		private ConfigEntry<T> Bind<T>(KindleSetting<T> setting, AcceptableValueBase? acceptable)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KindleSetting)setting).Scope != 2)
			{
				return MeadworksConfig.Bind<T>(file, ((KindleSetting)setting).Section, ((KindleSetting)setting).Key, setting.Default, Describe((KindleSetting)(object)setting, acceptable), Map(((KindleSetting)setting).Scope));
			}
			return MeadworksConfig.BindCheat<T>(file, ((KindleSetting)setting).Section, ((KindleSetting)setting).Key, setting.Safe, ((KindleSetting)setting).Description, acceptable);
		}

		private static int Count(SettingScope scope)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return KindleSettings.All.Count((KindleSetting s) => s.Scope == scope);
		}
	}
	internal static class InscribeDetails
	{
		private static Tuple<Func<object, string>, Func<object, string>, Func<object, Tuple<string, string, float, string, string, string>[]>> Resolve()
		{
			if (!Plugin.IsReady)
			{
				return null;
			}
			Tuple<Func<object, string>, Func<object, string>, Func<object, Tuple<string, string, float, string, string, string>[]>> result = default(Tuple<Func<object, string>, Func<object, string>, Func<object, Tuple<string, string, float, string, string, string>[]>>);
			if (!Plugin.Services.Capabilities.TryResolve<Tuple<Func<object, string>, Func<object, string>, Func<object, Tuple<string, string, float, string, string, string>[]>>>("meadworks.items.decoration", ItemDecorationContract.ContractVersion, ref result))
			{
				return null;
			}
			return result;
		}

		internal static string Name(ItemData item, string fallback)
		{
			try
			{
				string text = Resolve()?.Item1(item);
				return string.IsNullOrEmpty(text) ? fallback : text;
			}
			catch (Exception)
			{
				return fallback;
			}
		}

		internal static string Lines(ItemData item)
		{
			try
			{
				Tuple<string, string, float, string, string, string>[] array = Resolve()?.Item3(item);
				if (array == null)
				{
					return "";
				}
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				List<string> list = new List<string>();
				Tuple<string, string, float, string, string, string>[] array2 = array;
				foreach (Tuple<string, string, float, string, string, string> tuple in array2)
				{
					if (list.Count == 128)
					{
						break;
					}
					if (tuple != null && tuple.Item1 != null && tuple.Item1.StartsWith("inscribe.", StringComparison.Ordinal) && hashSet.Add(tuple.Item1) && !float.IsNaN(tuple.Item3) && !float.IsInfinity(tuple.Item3) && !string.IsNullOrEmpty(tuple.Item6))
					{
						list.Add(tuple.Item6);
					}
				}
				return string.Join("\n", list);
			}
			catch (Exception)
			{
				return "";
			}
		}
	}
	public sealed class KindleImportValue
	{
		public string SourceId { get; }

		public string TargetId { get; }

		public string SourceValue { get; }

		public string Value { get; }

		public string CurrentValue { get; }

		internal KindleImportValue(string source, string target, string original, string value, string current)
		{
			SourceId = source;
			TargetId = target;
			SourceValue = original;
			Value = value;
			CurrentValue = current;
		}
	}
	public sealed class KindleImportPreview
	{
		internal KindleReferenceImport Owner { get; }

		internal IReadOnlyDictionary<string, string> Sources { get; }

		internal IReadOnlyList<string> PrepareErrors { get; }

		internal long Generation { get; }

		public ConversionPreview Preview { get; }

		public IReadOnlyList<KindleImportValue> Values { get; }

		public IReadOnlyList<string> Errors { get; }

		public IReadOnlyList<string> Skipped { get; }

		public IReadOnlyList<string> Normalizations { get; }

		public IReadOnlyList<ConversionConflict> Conflicts => Preview.Conflicts;

		public IReadOnlyList<ConversionConflict> BindingConflicts => Preview.BindingConflicts;

		public string SourceSha256 { get; }

		public string TargetSha256 { get; }

		internal KindleImportPreview(KindleReferenceImport owner, ConversionPreview plan, IEnumerable<KindleImportValue> values, IEnumerable<string> errors, IEnumerable<string> prepareErrors, IEnumerable<string> skipped, IEnumerable<string> normalizations, IReadOnlyDictionary<string, string> sources, string sourceHash, string targetHash, long generation)
		{
			Owner = owner;
			Preview = plan;
			Values = Array.AsReadOnly(values.ToArray());
			Errors = Array.AsReadOnly(errors.ToArray());
			PrepareErrors = Array.AsReadOnly(prepareErrors.ToArray());
			Skipped = Array.AsReadOnly(skipped.ToArray());
			Normalizations = Array.AsReadOnly(normalizations.ToArray());
			Sources = new ReadOnlyDictionary<string, string>(sources.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> p) => p.Key, (KeyValuePair<string, string> p) => p.Value, StringComparer.OrdinalIgnoreCase));
			SourceSha256 = sourceHash;
			TargetSha256 = targetHash;
			Generation = generation;
		}

		public override string ToString()
		{
			List<string> list = new List<string> { KindleText.Text("import_review") };
			list.AddRange(Values.Select((KindleImportValue v) => v.SourceId + " → " + v.TargetId + ": " + v.CurrentValue + " → " + v.Value + " (source: " + v.SourceValue + ")"));
			list.AddRange(Normalizations.Select((string v) => "Normalized: " + v));
			list.AddRange(Skipped.Select((string v) => "Skipped: " + v));
			list.AddRange(Errors.Select((string v) => "Invalid: " + v));
			list.AddRange(Conflicts.Select((ConversionConflict c) => "Choice required: " + c.TargetId + " = " + string.Join(" or ", c.Choices.Select((ConversionValue v) => v.SourceId))));
			list.AddRange(BindingConflicts.Select((ConversionConflict c) => "Shortcut collision: " + c.TargetId + "; replace binding:<target>=<shortcut>"));
			list.AddRange(from p in Sources
				where !p.Key.EndsWith(".cfg", StringComparison.OrdinalIgnoreCase)
				select "Salvage file: " + Path.GetFileName(p.Key) + " → " + Path.GetFileName(p.Key).Replace("OpenKeep.", "Kindle."));
			list.Add("Overrides: binding:<Section.Key>=<shortcut>; conflicts: <Section.Key>=<source id>.");
			list.Add("Source SHA256: " + SourceSha256);
			list.Add("Target SHA256: " + TargetSha256);
			return string.Join("\n", list);
		}
	}
	public sealed class KindleImportResult
	{
		public int Written { get; }

		public bool BackedUp { get; }

		public string SourceSha256 { get; }

		public string TargetSha256 { get; }

		public IReadOnlyList<string> Backups { get; }

		public IReadOnlyList<string> Messages { get; }

		internal KindleImportResult(ConversionResult result, string sourceHash, string targetHash, IEnumerable<string> backups, IEnumerable<string> messages)
		{
			Written = result.Written;
			BackedUp = result.BackedUp;
			SourceSha256 = sourceHash;
			TargetSha256 = targetHash;
			Backups = Array.AsReadOnly(backups.ToArray());
			Messages = Array.AsReadOnly(messages.ToArray());
		}

		public override string ToString()
		{
			return string.Join("\n", new string[1] { "Applied " + Written + " settings; config backup " + (BackedUp ? "created" : "no config changes") }.Concat(Messages).Concat(Backups.Select((string p) => "Backup: " + p)).Concat(new string[2]
			{
				"Source SHA256: " + SourceSha256,
				"Target SHA256: " + TargetSha256
			}));
		}
	}
	internal static class KindleAlmanac
	{
		internal const int MaxBytes = 1048576;

		internal static string ReadText(string path)
		{
			using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
			if (fileStream.Length > 1048576)
			{
				throw new InvalidDataException("Registered text exceeds 1 MiB.");
			}
			using StreamReader streamReader = new StreamReader(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true);
			return streamReader.ReadToEnd();
		}

		internal static string Hash(string text)
		{
			using SHA256 sHA = SHA256.Create();
			return Hex(sHA.ComputeHash(Encoding.UTF8.GetBytes(text)));
		}

		internal static string FileHash(string path)
		{
			if (!File.Exists(path))
			{
				return "missing";
			}
			using FileStream inputStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
			using SHA256 sHA = SHA256.Create();
			return Hex(sHA.ComputeHash(inputStream));
		}

		private static string Hex(byte[] bytes)
		{
			return string.Concat(bytes.Select((byte b) => b.ToString("X2", CultureInfo.InvariantCulture)));
		}

		internal static string SetHash(IEnumerable<KeyValuePair<string, string>> files)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, string> item in files.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> p) => p.Key, StringComparer.Ordinal))
			{
				stringBuilder.Append(item.Key.Length).Append(':').Append(item.Key)
					.Append(item.Value.Length)
					.Append(':')
					.Append(item.Value);
			}
			return Hash(stringBuilder.ToString());
		}

		internal static IEnumerable<KeyValuePair<string, string>> Ordered(IEnumerable<KeyValuePair<string, string>> files)
		{
			return files.OrderBy<KeyValuePair<string, string>, int>((KeyValuePair<string, string> p) => (!Path.GetFileName(p.Key).Equals("Kindle.Salvage.yml", StringComparison.OrdinalIgnoreCase)) ? 1 : 0).ThenBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> p) => Path.GetFileName(p.Key), StringComparer.OrdinalIgnoreCase);
		}

		internal static void Authority()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if (!Plugin.IsReady || !Plugin.Ready)
			{
				throw new InvalidOperationException("Kindle configuration owner is unavailable.");
			}
			AuthorityDecision val = MeadworksAuthority.Decide("com.meadworks.kindle", (ConfigScope)1, true);
			if ((int)Plugin.Session.Role == 3 || !val.Allowed || val.RequiresServerAmendment)
			{
				throw new InvalidOperationException("Apply this import on the authority machine; this client cannot replace server-controlled configuration.");
			}
		}

		internal static string Temporary(string path, string text)
		{
			if (Encoding.UTF8.GetByteCount(text) > 1048576)
			{
				throw new InvalidDataException("Registered text exceeds 1 MiB.");
			}
			string text2 = path + ".import-" + Guid.NewGuid().ToString("N") + ".tmp";
			try
			{
				using (FileStream fileStream = new FileStream(text2, FileMode.CreateNew, FileAccess.Write, FileShare.None))
				{
					using (StreamWriter streamWriter = new StreamWriter(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), 1024, leaveOpen: true))
					{
						streamWriter.Write(text);
						streamWriter.Flush();
					}
					fileStream.Flush(flushToDisk: true);
				}
				return text2;
			}
			catch
			{
				if (File.Exists(text2))
				{
					File.Delete(text2);
				}
				throw;
			}
		}

		internal static string Backup(string path)
		{
			return path + ".import-" + DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture) + "-" + Guid.NewGuid().ToString("N") + ".bak";
		}
	}
	public sealed class KindleReferenceImport : IDisposable
	{
		private sealed class ImportTarget : IValidatedConversionTarget, IConversionTarget
		{
			private readonly KindleReferenceImport owner;

			private readonly KindleImportPreview preview;

			private readonly IConversionTarget target;

			internal readonly List<string> Backups = new List<string>();

			private bool backupRequested;

			private bool written;

			public int SchemaVersion => target.SchemaVersion;

			internal ImportTarget(KindleReferenceImport owner, KindleImportPreview preview)
			{
				this.owner = owner;
				this.preview = preview;
				target = MeadworksConversion.Target(owner.config);
			}

			private ConfigEntryBase[] Entries(IReadOnlyDictionary<string, object> values)
			{
				List<ConfigEntryBase> list = new List<ConfigEntryBase>();
				ConfigEntryMetadata val2 = default(ConfigEntryMetadata);
				foreach (KeyValuePair<string, object> value in values)
				{
					KindleSetting setting = ((IEnumerable<KindleSetting>)KindleSettings.All).SingleOrDefault((Func<KindleSetting, bool>)((KindleSetting s) => s.Id == value.Key)) ?? throw new ArgumentException("Unknown Kindle import target: " + value.Key);
					ConfigEntryBase val = owner.settingsEntry(setting);
					if (!MeadworksConfig.TryGetMetadata(val, ref val2) || val2.ProductId != "com.meadworks.kindle" || !val2.Decision.Allowed || val2.Decision.RequiresServerAmendment || owner.settings.IsLocked(setting))
					{
						throw new InvalidOperationException("An import target is now locked: " + value.Key);
					}
					object obj = (val.SettingType.IsInstanceOfType(value.Value) ? value.Value : TomlTypeConverter.ConvertToValue(Convert.ToString(value.Value, CultureInfo.InvariantCulture), val.SettingType));
					if (val.Description.AcceptableValues != null && !val.Description.AcceptableValues.IsValid(obj))
					{
						throw new ArgumentException("Invalid Kindle import target value: " + value.Key);
					}
					list.Add(val);
				}
				return list.Distinct().ToArray();
			}

			public void Validate(IReadOnlyDictionary<string, object> values)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				if (written)
				{
					throw new InvalidOperationException("This Kindle configuration import has already been applied.");
				}
				owner.Admission(preview);
				((IValidatedConversionTarget)target).Validate(values);
				Entries(values);
			}

			public void Backup()
			{
				owner.Admission(preview);
				if (!File.Exists(owner.config.ConfigFilePath))
				{
					throw new InvalidOperationException("Save Kindle configuration before importing; a target backup is required.");
				}
				backupRequested = true;
			}

			private void VerifiedBackup()
			{
				string configFilePath = owner.config.ConfigFilePath;
				string directoryName = Path.GetDirectoryName(configFilePath);
				string searchPattern = Path.GetFileName(configFilePath) + ".import-*.bak";
				string[] files = Directory.GetFiles(directoryName, searchPattern);
				string text = KindleAlmanac.FileHash(configFilePath);
				target.Backup();
				string[] array = Directory.GetFiles(directoryName, searchPattern).Except<string>(files, StringComparer.OrdinalIgnoreCase).ToArray();
				if (array.Length != 1 || KindleAlmanac.FileHash(array[0]) != text)
				{
					throw new IOException("The exact target backup could not be verified.");
				}
				Backups.Add(array[0]);
			}

			public void WriteAtomic(IReadOnlyDictionary<string, object> values)
			{
				Validate(values);
				if (!backupRequested)
				{
					throw new InvalidOperationException("Kindle import requires a backup.");
				}
				ConfigEntryBase[] array = Entries(values);
				if (array.Length == 0)
				{
					return;
				}
				try
				{
					if (!MeadworksConfig.AmendBatch("com.meadworks.kindle", (IReadOnlyList<ConfigEntryBase>)array, (Action)delegate
					{
						owner.Admission(preview);
						Entries(values);
						VerifiedBackup();
						target.WriteAtomic(values);
						written = true;
					}, "Kindle import").Applied || !written)
					{
						throw new InvalidOperationException("Current authority or synchronization refused the Kindle import before writing.");
					}
				}
				catch (Exception innerException) when (written)
				{
					throw new IOException("Kindle settings were saved locally, but synchronization did not complete. Salvage files and the import marker were not updated; review synchronization before continuing.", innerException);
				}
			}
		}

		private readonly ConfigFile config;

		private readonly ConfigEntry<string> marker;

		private readonly ConfigEntry<bool> apply;

		private readonly ConfigEntry<bool> preview;

		private readonly ConfigEntry<string> choices;

		private readonly Dictionary<string, KindleSetting> mappings = new Dictionary<string, KindleSetting>(StringComparer.Ordinal);

		private readonly ConfigConverter converter;

		private readonly MeadworksLog log;

		private readonly KindleConfig settings;

		private readonly int thread = Thread.CurrentThread.ManagedThreadId;

		private IDisposable registration;

		private bool disposed;

		private Player lastPlayer;

		private bool offered;

		public string ReportPath => Path.Combine(Paths.ConfigPath, "Meadworks", "kindle", "import-report.txt");

		public string SourcePath => Path.Combine(Paths.ConfigPath, "milkyteam.openkeep.cfg");

		public KindleReferenceImport(ConfigFile config, KindleConfig settings, MeadworksLog log)
		{
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: 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_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Expected O, but got Unknown
			this.config = config;
			this.log = log;
			this.settings = settings;
			marker = MeadworksConfig.BindHidden<string>(config, "Import", "Imported Sources", "", "Managed by Kindle.", (ConfigScope)0, (AcceptableValueBase)null);
			preview = MeadworksConfig.Bind<bool>(config, "Import", "Preview OpenKeep", false, "Write a preview report without changing any source or target settings. Resets after running.", (ConfigScope)0, (AcceptableValueBase)null);
			apply = MeadworksConfig.Bind<bool>(config, "Import", "Apply OpenKeep", false, "Apply the previewed reference settings with a target backup. Source files remain intact. Resets after running.", (ConfigScope)0, (AcceptableValueBase)null);
			choices = MeadworksConfig.Bind<string>(config, "Import", "Binding Overrides", "", "Replacement shortcuts as Section.Key=value, separated by semicolons, for collisions shown by Preview.", (ConfigScope)0, (AcceptableValueBase)null);
			foreach (KindleSetting item in KindleSettings.All)
			{
				string text = ((item.Section == "Recipe List") ? "12. Recipe List" : ((item.Section == "Batch Crafting") ? "10. Batch Crafting" : ((item.Section == "Recipe Tracker") ? "13. Recipe Tracker" : ((item.Section == "Salvage") ? "3. Salvage" : ((item.Section == "Cart Workbench") ? "6. Carts" : "")))));
				if (text.Length != 0 && (object)item != RecipeList.FavouriteRecipeKey && (object)item != RecipeList.IgnoreAccents && (object)item != RecipeList.SortButton && (object)item != RecipeList.GamepadSortButton)
				{
					mappings.Add("OpenKeep." + text + "." + item.Key, item);
				}
			}
			mappings.Add("OpenKeep.2. Stow.Favourite Item Key", (KindleSetting)(object)RecipeList.FavouriteRecipeKey);
			IEnumerable<ConversionRule> enumerable = mappings.Select<KeyValuePair<string, KindleSetting>, ConversionRule>((KeyValuePair<string, KindleSetting> pair) => new ConversionRule(pair.Key, pair.Value.Id, IsShortcut(pair.Value) ? "KeyboardShortcut" : pair.Value.ValueType.Name, string.Join(",", pair.Value.Choices), false, IsShortcut(pair.Value)));
			converter = new ConfigConverter(new ConversionMapping(1, "OpenKeep", 0, enumerable));
			registration = MeadworksConversion.Register(new ConversionRegistration("kindle.openkeep", "com.meadworks.kindle", "milkyteam.openkeep", "OpenKeep", (Func<bool>)(() => !disposed && (File.Exists(SourcePath) || Directory.GetFiles(Paths.ConfigPath, "OpenKeep.Salvage*.yml").Length != 0)), (Func<object>)(() => Preview()), (Func<object, IReadOnlyDictionary<string, string>, bool, object>)delegate(object document, IReadOnlyDictionary<string, string> resolutions, bool backup)
			{
				if (!backup)
				{
					throw new InvalidOperationException("Kindle import requires a backup.");
				}
				Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
				Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.Ordinal);
				foreach (KeyValuePair<string, string> resolution in resolutions)
				{
					if (resolution.Key.StartsWith("binding:", StringComparison.Ordinal))
					{
						dictionary2.Add(resolution.Key.Substring(8), resolution.Value);
					}
					else if (KindleSettings.All.Any((KindleSetting s) => s.Id == resolution.Key && IsShortcut(s)) && !mappings.ContainsKey(resolution.Value))
					{
						dictionary2.Add(resolution.Key, resolution.Value);
					}
					else
					{
						dictionary.Add(resolution.Key, resolution.Value);
					}
				}
				return Apply((document as KindleImportPreview) ?? throw new ArgumentException("Wrong Kindle import preview."), dictionary, dictionary2);
			}));
		}

		private void Check()
		{
			if (disposed || Thread.CurrentThread.ManagedThreadId != thread)
			{
				throw new InvalidOperationException("Kindle imports require their live owning thread.");
			}
		}

		public void Dispose()
		{
			if (!disposed)
			{
				disposed = true;
				registration?.Dispose();
				registration = null;
			}
		}

		private static bool IsShortcut(KindleSetting setting)
		{
			if ((object)setting != RecipeList.SearchKey && (object)setting != RecipeList.FavouriteRecipeKey)
			{
				return (object)setting == Salvage.SalvageKey;
			}
			return true;
		}

		public static bool DeclareAndYield()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			if (!Plugin.Services.StepAside.Declared("com.meadworks.kindle").Any())
			{
				List<SourceMod> list = new List<SourceMod>();
				if (Chainloader.PluginInfos.TryGetValue("milkyteam.openkeep", out var value) && value.Metadata.Version >= new Version(2, 0))
				{
					list.Add(new SourceMod(value.Metadata.GUID, "OpenKeep"));
				}
				foreach (PluginInfo info in Chainloader.PluginInfos.Values)
				{
					if ((info.Metadata.GUID == "com.ab5olutezer0.valheim.craftingsearch" || string.Equals(info.Metadata.Name, "Crafting Search", StringComparison.OrdinalIgnoreCase) || string.Equals(((object)info.Instance)?.GetType().Assembly.GetName().Name, "CraftingSearch", StringComparison.OrdinalIgnoreCase)) && !list.Any((SourceMod s) => s.Guid == info.Metadata.GUID))
					{
						list.Add(new SourceMod(info.Metadata.GUID, "Crafting Search"));
					}
				}
				MeadworksStepAside.Declare("com.meadworks.kindle", "Kindle", (IEnumerable<SourceMod>)list);
			}
			return MeadworksStepAside.ShouldYield("com.meadworks.kindle");
		}

		public void Tick(bool active)
		{
			if (!offered)
			{
				offered = true;
				if (marker.Value.Length == 0 && File.Exists(Path.Combine(Paths.ConfigPath, "milkyteam.openkeep.cfg")))
				{
					Run(write: false);
				}
			}
			if (preview.Value || apply.Value)
			{
				Run(apply.Value);
			}
			if (!active)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer == (Object)(object)lastPlayer)
			{
				return;
			}
			lastPlayer = localPlayer;
			(string, string)[] array = new(string, string)[3]
			{
				("favouriteRecipes", "favoriteRecipes"),
				("favouriteRecipesOnly", "favoriteRecipesOnly"),
				("trackedRecipes", "trackedRecipes")
			};
			for (int i = 0; i < array.Length; i++)
			{
				var (text, text2) = array[i];
				if (!localPlayer.m_customData.ContainsKey("Kindle." + text2) && localPlayer.m_customData.TryGetValue("OpenKeep." + text, out var value))
				{
					localPlayer.m_customData["Kindle." + text2] = value;
				}
			}
			string text3 = default(string);
			if (!localPlayer.TryGetUniqueKeyValue("kindle_sort_desc", ref text3) && !localPlayer.m_customData.ContainsKey("Kindle.importedCraftingSearch") && localPlayer.TryGetUniqueKeyValue("craftingsearch_desc", ref text3))
			{
				localPlayer.AddUniqueKeyValue("kindle_sort_desc", "1");
				localPlayer.m_customData["Kindle.importedCraftingSearch"] = "1";
			}
		}

		public KindleImportPreview Preview()
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Invalid comparison between Unknown and I4
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Invalid comparison between Unknown and I4
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: 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)
			Check();
			string hash;
			Dictionary<string, string> dictionary = ReadSources(out hash);
			if (dictionary.Count == 0)
			{
				throw new InvalidOperationException("No OpenKeep settings or salvage files were found to import.");
			}
			IReadOnlyList<KeyValuePair<string, string>> readOnlyList2;
			if (!dictionary.TryGetValue(SourcePath, out var value))
			{
				IReadOnlyList<KeyValuePair<string, string>> readOnlyList = Array.Empty<KeyValuePair<string, string>>();
				readOnlyList2 = readOnlyList;
			}
			else
			{
				readOnlyList2 = CfgText.Read(value, "OpenKeep");
			}
			IReadOnlyList<KeyValuePair<string, string>> raw = readOnlyList2;
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			List<string> list4 = new List<string>();
			foreach (KeyValuePair<string, string> item in raw)
			{
				if (!mappings.TryGetValue(item.Key, out KindleSetting value2))
				{
					list3.Add(item.Key + ": no Kindle mapping");
					continue;
				}
				if ((object)value2 == RecipeList.FavouriteRecipeKey && item.Value == "F")
				{
					list3.Add(item.Key + ": default reference F binding retained as Kindle's configured binding");
					continue;
				}
				AuthorityDecision val = MeadworksAuthority.Decide("com.meadworks.kindle", KindleConfig.Map(value2.Scope), true);
				if (settings.IsLocked(value2) || (int)val.Source == 1 || (int)val.Source == 2)
				{
					list3.Add(item.Key + ": target is locked or server-provided");
					continue;
				}
				try
				{
					Type valueType = value2.ValueType;
					object result;
					object obj = (IsShortcut(value2) ? ((object)KeyboardShortcut.Deserialize(item.Value)) : ((!valueType.IsEnum) ? TomlTypeConverter.ConvertToValue(item.Value, valueType) : (Enum.TryParse(valueType, item.Value, ignoreCase: true, out result) ? result : value2.DefaultValue)));
					object obj2 = (IsShortcut(value2) ? obj : value2.NormalizeBoxed(obj));
					object obj3;
					if (!IsShortcut(value2))
					{
						obj3 = Convert.ToString(obj2, CultureInfo.InvariantCulture) ?? "";
					}
					else
					{
						KeyboardShortcut val2 = (KeyboardShortcut)obj2;
						obj3 = ((KeyboardShortcut)(ref val2)).Serialize();
					}
					string text = (string)obj3;
					if (text != item.Value)
					{
						list4.Add(item.Key + ": " + item.Value + " -> " + text + " (normalized)");
					}
					list.Add(new KeyValuePair<string, string>(item.Key, text));
				}
				catch (Exception ex)
				{
					list2.Add(item.Key + ": " + ex.GetBaseException().Message);
				}
			}
			ConversionPreview val3 = converter.Preview((IEnumerable<KeyValuePair<string, string>>)list);
			list2.AddRange(val3.Errors);
			Dictionary<string, string> dictionary2 = ReadTargetYaml();
			foreach (KeyValuePair<string, string> item2 in dictionary.Where((KeyValuePair<string, string> p) => p.Key != SourcePath))
			{
				dictionary2[Destination(item2.Key)] = ImportedText(item2.Key, item2.Value);
			}
			if (dictionary2.Count != 0)
			{
				SalvageModel salvageModel = new SalvageModel();
				salvageModel.LoadAll(KindleAlmanac.Ordered(dictionary2));
				list2.AddRange(salvageModel.Errors);
			}
			string[] prepareErrors = list2.ToArray();
			try
			{
				ValidateFinalBindings(val3, ReadOverrides());
			}
			catch (Exception ex2)
			{
				list2.Add(ex2.GetBaseException().Message);
			}
			IEnumerable<KindleImportValue> values = val3.Values.Select((ConversionValue v) => new KindleImportValue(v.SourceId, v.TargetId, raw.First<KeyValuePair<string, string>>((KeyValuePair<string, string> p) => p.Key == v.SourceId).Value, Convert.ToString(v.Value, CultureInfo.InvariantCulture) ?? "", config[config.Keys.Single((ConfigDefinition k) => k.Section + "." + k.Key == v.TargetId)].GetSerializedValue()));
			return new KindleImportPreview(this, val3, values, list2, prepareErrors, list3, list4, dictionary, hash, TargetHash(), Plugin.Session.Generation);
		}

		private Dictionary<string, string> ReadOverrides()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			string[] array = choices.Value.Split(';');
			foreach (string text in array)
			{
				int num = text.IndexOf('=');
				if (num > 0)
				{
					dictionary[text.Substring(0, num).Trim()] = text.Substring(num + 1).Trim();
				}
			}
			return dictionary;
		}

		private Dictionary<string, string> ReadSources(out string hash)
		{
			List<string> list = Directory.GetFiles(Paths.ConfigPath, "OpenKeep.Salvage*.yml").OrderBy<string, string>((string p) => p, StringComparer.Ordinal).ToList();
			if (File.Exists(SourcePath))
			{
				list.Insert(0, SourcePath);
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in list)
			{
				string text = KindleAlmanac.FileHash(item);
				string value = KindleAlmanac.ReadText(item);
				if (KindleAlmanac.FileHash(item) != text)
				{
					throw new InvalidOperationException("Source changed while preparing the import.");
				}
				dictionary.Add(item, value);
				dictionary2.Add(item, text);
			}
			hash = KindleAlmanac.SetHash(dictionary2);
			return dictionary;
		}

		private Dictionary<string, string> ReadTargetYaml()
		{
			return Directory.GetFiles(Paths.ConfigPath, "Kindle.Salvage*.yml").ToDictionary<string, string, string>((string p) => p, (string p) => KindleAlmanac.ReadText(p), StringComparer.OrdinalIgnoreCase);
		}

		private static string Destination(string source)
		{
			return Path.Combine(Paths.ConfigPath, Path.GetFileName(source).Replace("OpenKeep.", "Kindle."));
		}

		private static string ImportedText(string path, string text)
		{
			return "# Imported from " + Path.GetFileName(path) + "; source preserved.\n" + text;
		}

		private string TargetHash()
		{
			List<KeyValuePair<string, string>> list = (from k in config.Keys.OrderBy<ConfigDefinition, string>((ConfigDefinition k) => k.Section, StringComparer.Ordinal).ThenBy<ConfigDefinition, string>((ConfigDefinition k) => k.Key, StringComparer.Ordinal)
				select new KeyValuePair<string, string>(k.Section.Length + ":" + k.Section + k.Key.Length + ":" + k.Key, TomlTypeConverter.ConvertToString(config[k].BoxedValue, config[k].SettingType))).ToList();
			list.Add(new KeyValuePair<string, string>("config-bytes", KindleAlmanac.FileHash(config.ConfigFilePath)));
			list.Add(new KeyValuePair<string, string>("yaml-set", KindleAlmanac.SetHash(ReadTargetYaml())));
			return KindleAlmanac.SetHash(list);
		}

		private void Admission(KindleImportPreview document, bool target = true)
		{
			//IL_00c4: 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)
			Check();
			if (document == null || document.Owner != this)
			{
				throw new ArgumentException("Preview belongs to another Kindle importer.");
			}
			KindleAlmanac.Authority();
			if (Plugin.Session.Generation != document.Generation)
			{
				throw new InvalidOperationException("Session changed; preview again.");
			}
			ReadSources(out string hash);
			if (hash != document.SourceSha256)
			{
				throw new InvalidOperationException("Source files changed; preview again.");
			}
			if (target && TargetHash() != document.TargetSha256)
			{
				throw new InvalidOperationException("Target configuration or salvage files changed; preview again.");
			}
			foreach (ConversionValue value in document.Preview.Values)
			{
				KindleSetting val = KindleSettings.All.Single((KindleSetting s) => s.Id == value.TargetId);
				AuthorityDecision val2 = MeadworksAuthority.Decide("com.meadworks.kindle", KindleConfig.Map(val.Scope), true);
				if (settings.IsLocked(val) || !val2.Allowed || val2.RequiresServerAmendment)
				{
					throw new InvalidOperationException("An import target is now locked: " + value.TargetId);
				}
			}
		}

		public KindleImportResult Apply(KindleImportPreview document, IReadOnlyDictionary<string, string> sourceChoices, IReadOnlyDictionary<string, string> bindingOverrides = null)
		{
			Admission(document);
			if (document.PrepareErrors.Count != 0)
			{
				throw new ArgumentException(string.Join("; ", document.PrepareErrors));
			}
			if (bindingOverrides == null)
			{
				bindingOverrides = new Dictionary<string, string>();
			}
			ValidateFinalBindings(document.Preview, bindingOverrides);
			ImportTarget importTarget = new ImportTarget(this, document);
			ConversionResult val = converter.Apply(document.Preview, (IConversionTarget)(object)importTarget, sourceChoices, bindingOverrides);
			List<string> list = new List<string>();
			List<string> list2 = importTarget.Backups.ToList();
			try
			{
				CopyYaml(document, list, list2);
				Admission(document, target: false);
			}
			catch (Exception ex)
			{
				throw new InvalidOperationException("Configuration committed " + val.Written + " settings before YAML/source verification stopped: " + ex.GetBaseException().Message + ". Backups: " + string.Join(", ", list2), ex);
			}
			marker.Value = "OpenKeep";
			return new KindleImportResult(val, document.SourceSha256, TargetHash(), list2, list);
		}

		private void Run(bool write)
		{
			List<string> list = new List<string> { "Kindle OpenKeep import: " + (write ? "apply" : "preview") };
			try
			{
				KindleImportPreview kindleImportPreview = Preview();
				list.AddRange(kindleImportPreview.Normalizations);
				list.AddRange(kindleImportPreview.Values.Select((KindleImportValue v) => v.SourceId + " -> " + v.TargetId + " = " + v.Value));
				list.AddRange(kindleImportPreview.Errors);
				list.AddRange(kindleImportPreview.Skipped);
				list.AddRange(kindleImportPreview.BindingConflicts.Select((ConversionConflict c) => "Shortcut collision: " + c.TargetId + " (set Binding Overrides)"));
				list.Add("Source SHA256: " + kindleImportPreview.SourceSha256 + "; target SHA256: " + kindleImportPreview.TargetSha256);
				if (write)
				{
					KindleImportResult kindleImportResult = Apply(kindleImportPreview, new Dictionary<string, string>(), ReadOverrides());
					list.AddRange(kindleImportResult.Messages);
					list.Add("Applied " + kindleImportResult.Written + " settings; target backup: " + kindleImportResult.BackedUp);
				}
				else
				{
					list.Add("Preview only; no settings changed.");
				}
			}
			catch (Exception ex)
			{
				list.Add("Import stopped: " + ex.GetType().Name + ": " + ex.Message);
			}
			finally
			{
				ConfigEntry<bool> obj = preview;
				bool value = (apply.Value = false);
				obj.Value = value;
				Directory.CreateDirectory(Path.GetDirectoryName(ReportPath));
				File.WriteAllLines(ReportPath, list);
				log.Info(list[list.Count - 1] + " Report: " + ReportPath);
			}
		}

		private void ValidateFinalBindings(ConversionPreview plan, IReadOnlyDictionary<string, string> overrides)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			foreach (KindleSetting item in KindleSettings.All.Where(IsShortcut))
			{
				dictionary[item.Id] = settingsEntry(item).GetSerializedValue();
			}
			foreach (ConversionValue value in plan.Values)
			{
				if (dictionary.ContainsKey(value.TargetId))
				{
					dictionary[value.TargetId] = Convert.ToString(value.Value, CultureInfo.InvariantCulture) ?? "";
				}
			}
			foreach (KeyValuePair<string, string> @override in overrides)
			{
				if (dictionary.ContainsKey(@override.Key))
				{
					dictionary[@override.Key] = @override.Value;
				}
			}
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.Ordinal);
			HotkeyChord val = default(HotkeyChord);
			foreach (KeyValuePair<string, string> item2 in dictionary)
			{
				if (!HotkeyChord.TryParse(item2.Value, ref val))
				{
					throw new ArgumentException("Unknown shortcut: " + item2.Key);
				}
				if (!val.IsNone)
				{
					dictionary2[item2.Key] = string.Join(" + ", new string[1] { val.Main }.Concat(val.Modifiers.OrderBy<string, string>((string m) => m, StringComparer.Ordinal)));
				}
			}
			IGrouping<string, KeyValuePair<string, string>>[] array = (from @group in dictionary2.GroupBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> pair) => pair.Value, StringComparer.OrdinalIgnoreCase)
				where @group.Count() > 1
				select @group).ToArray();
			if (array.Length == 0)
			{
				return;
			}
			throw new ArgumentException("Final shortcut collision: " + string.Join("; ", array.Select((IGrouping<string, KeyValuePair<string, string>> group) => group.Key + " -> " + string.Join(", ", group.Select((KeyValuePair<string, string> pair) => pair.Key)))));
		}

		private ConfigEntryBase settingsEntry(KindleSetting setting)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			return config[new ConfigDefinition(setting.Section, setting.Key)];
		}

		private void CopyYaml(KindleImportPreview document, List<string> report, List<string> backups)
		{
			string text = TargetHash();
			foreach (KeyValuePair<string, string> item in document.Sources.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> p) => p.Key != SourcePath))
			{
				Admission(document, target: false);
				if (TargetHash() != text)
				{
					throw new InvalidOperationException("Target changed during YAML import.");
				}
				string text2 = Destination(item.Key);
				string text3 = ImportedText(item.Key, item.Value);
				string text4 = (File.Exists(text2) ? KindleAlmanac.ReadText(text2) : null);
				string text5 = KindleAlmanac.Temporary(text2, text3);
				string text6 = null;
				try
				{
					Admission(document, target: false);
					if (TargetHash() != text)
					{
						throw new InvalidOperationException("Target changed at YAML publication.");
					}
					if (text4 != null)
					{
						text6 = KindleAlmanac.Backup(text2);
						File.Replace(text5, text2, text6);
						backups.Add(text6);
					}
					else
					{
						File.Move(text5, text2);
					}
					if (KindleAlmanac.ReadText(text2) != text3)
					{
						throw new IOException("Imported YAML verification failed; backup: " + text6);
					}
					text = TargetHash();
					report.Add("Copied " + Path.GetFileName(text2) + ((text6 != null) ? " (existing target backed up)" : " (new target; no previous bytes)"));
				}
				finally
				{
					if (File.Exists(text5))
					{
						File.Delete(text5);
					}
				}
			}
		}
	}
	internal sealed class KindleSyncReceipt
	{
		private ZNet network;

		private ZRpc server;

		private string epoch = "";

		private long world;

		internal long CurrentGeneration
		{
			get
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Invalid comparison between Unknown and I4
				if (!Plugin.IsReady || (Object)(object)network == (Object)null || server == null || !server.IsConnected() || network != ZNet.instance || network.IsServer() || server != network.GetServerRPC())
				{
					return -1L;
				}
				SessionSnapshot session = Plugin.Session;
				if ((int)session.Role != 3 || !session.AuthorityReady || session.WorldId == 0L || string.IsNullOrEmpty(session.SessionId))
				{
					return -1L;
				}
				if (epoch.Length == 0)
				{
					epoch = session.SessionId;
					world = session.WorldId;
				}
				if (!(epoch == session.SessionId) || world != session.WorldId)
				{
					return -1L;
				}
				return session.Generation;
			}
		}

		internal void Observe()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			network = ZNet.instance;
			server = (((Object)(object)network != (Object)null && !network.IsServer()) ? network.GetServerRPC() : null);
			epoch = "";
			world = 0L;
			if (server != null && server.IsConnected() && Plugin.IsReady)
			{
				SessionSnapshot session = Plugin.Session;
				if ((int)session.Role == 3 && !string.IsNullOrEmpty(session.SessionId))
				{
					epoch = session.SessionId;
					world = session.WorldId;
				}
			}
		}
	}
	public static class KindleText
	{
		private static MeadworksTranslations catalog;

		public static long Revision
		{
			get
			{
				MeadworksTranslations obj = catalog;
				if (obj == null)
				{
					return -1L;
				}
				return obj.Translations.Revision;
			}
		}

		public static void Initialize(BepInPlugin metadata, ManualLogSource log)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			Assembly assembly = typeof(KindleText).Assembly;
			foreach (string item in MeadworksLanguages.Supported)
			{
				using Stream stream = assembly.GetManifestResourceStream("Kindle.localization." + item + ".json");
				if (stream != null)
				{
					using StreamReader streamReader = new StreamReader(stream);
					dictionary.Add(item, streamReader.ReadToEnd());
				}
			}
			catalog = MeadworksTranslations.Register(metadata, new ProductTranslations("kindle", (IReadOnlyDictionary<string, string>)dictionary), (string)null, log);
		}

		public static void Notice(string text, bool top = false)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!((Object)(object)MessageHud.instance == (Object)null))
			{
				ProductRegistration source = Plugin.Source;
				if (source != null && source.IsActive && CrucibleUiPlugin.Active)
				{
					KitNotices.Show(source, new KitNotice(text, (KitNoticeKind)(!top), "", 0, (Sprite)null, true, false, true));
				}
				else
				{
					MessageHud.instance.ShowMessage((MessageType)(top ? 1 : 2), text, 0, (Sprite)null, false, true);
				}
			}
		}

		public static string Text(string key)
		{
			MeadworksTranslations obj = catalog;
			return ((obj != null) ? obj.Text(key) : null) ?? key;
		}

		public static string Format(string key, params object[] arguments)
		{
			MeadworksTranslations obj = catalog;
			return ((obj != null) ? obj.Format(key, arguments) : null) ?? key;
		}

		public static string Token(string key)
		{
			return "$meadworks_kindle_" + key;
		}

		public static void Tick()
		{
			MeadworksTranslations obj = catalog;
			if (obj != null)
			{
				obj.Update();
			}
		}

		public static void Shutdown()
		{
			MeadworksTranslations obj = catalog;
			if (obj != null)
			{
				obj.Dispose();
			}
			catalog = null;
		}
	}
	public static class SalvageStackCapability
	{
		public const string CanId = "meadworks.crafting.salvage_can";

		public const string ItemId = "meadworks.crafting.salvage_item";

		public static readonly Version ContractVersion = new Version(1, 0);

		public static readonly Func<object, bool> Can = delegate(object item)
		{
			ItemData val = (ItemData)((item is ItemData) ? item : null);
			return val != null && SalvageActions.CanSalvage(val);
		};

		public static readonly Func<object, object, bool> Salvage = delegate(object player, object item)
		{
			Player val = (Player)((player is Player) ? player : null);
			if (val != null)
			{
				ItemData val2 = (ItemData)((item is ItemData) ? item : null);
				if (val2 != null)
				{
					return SalvageActions.Salvage(val, val2);
				}
			}
			return false;
		};

		public static void Register(ProductRegistration registration)
		{
			if (registration == null)
			{
				throw new ArgumentNullException("registration");
			}
			registration.AddCapability<Func<object, bool>>("meadworks.crafting.salvage_can", ContractVersion, Can);
			registration.AddCapability<Func<object, object, bool>>("meadworks.crafting.salvage_item", ContractVersion, Salvage);
		}
	}
	public static class SalvageTabCapability
	{
		public const string Id = "meadworks.crafting.salvage_tab";

		public static readonly Version ContractVersion = new Version(1, 0);

		public static readonly Func<bool> Provider = () => Active;

		public static bool Active { get; internal set; }

		public static void Register(ProductRegistration registration)
		{
			if (registration == null)
			{
				throw new ArgumentNullException("registration");
			}
			registration.AddCapability<Func<bool>>("meadworks.crafting.salvage_tab", ContractVersion, Provider);
		}
	}
	[BepInPlugin("com.meadworks.kindle", "Kindle", "0.1.25")]
	[BepInDependency("com.meadworks.crucible", "0.3.32")]
	[BepInDependency("com.meadworks.crucible.ui", "0.3.21")]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.meadworks.kindle";

		public const string Name = "Kindle";

		public const string Version = "0.1.25";

		public const string Family = "Forge";

		private ProductRegistration? registration;

		private MeadworksLog? log;

		private KindleReferenceImport? referenceImport;

		private bool started;

		private long noticedSession = -1L;

		internal static ProductRegistration? Source { get; private set; }

		public static bool Ready { get; private set; }

		public static bool SteppedAside { get; private set; }

		public static bool GameplayAvailable
		{
			get
			{
				ConfigBlockReason val = default(ConfigBlockReason);
				if (Ready && !SteppedAside)
				{
					return MeadworksAuthority.ProductActive("com.meadworks.kindle", ref val);
				}
				return false;
			}
		}

		public static bool AllowsUi { get; private set; }

		public static KindleConfig? Settings { get; private set; }

		private void Awake()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			log = MeadworksLog.For(((BaseUnityPlugin)this).Logger, "Kindle");
			try
			{
				if (!Plugin.IsReady)
				{
					throw new InvalidOperationException("Required Crucible is not ready");
				}
				registration = Plugin.Services.Register(new ProductMetadata("com.meadworks.kindle", "Kindle", new Version("0.1.25"), new Version(0, 1), new Version(0, 1), (MultiplayerPolicy)1, "Forge"));
				Source = registration;
				AllowsUi = MeadworksHeadless.AllowsUi;
				Settings = KindleConfig.Bind(((BaseUnityPlugin)this).Config, log);
				KindleText.Initialize(((BaseUnityPlugin)this).Info.Metadata, ((BaseUnityPlugin)this).Logger);
				referenceImport = new KindleReferenceImport(((BaseUnityPlugin)this).Config, Settings, log);
				SalvageTabCapability.Register(registration);
				SalvageStackCapability.Register(registration);
				Ready = true;
				log.Info(AllowsUi ? "Kindle registered; crafting modules start after plugin discovery." : "Kindle registered on a headless process; no UI is created.");
			}
			catch (Exception ex)
			{
				Shutdown();
				log.Error((object)("Kindle initialization rejected: " + ex));
			}
		}

		private void Start()
		{
			if (!Ready || Settings == null || registration == null || log == null)
			{
				return;
			}
			try
			{
				SteppedAside = KindleReferenceImport.DeclareAndYield();
				KindleSalvage.Initialize(((BaseUnityPlugin)this).Config, registration, delegate(string message)
				{
					log.Warning(message);
				});
				if (!SteppedAside && AllowsUi)
				{
					KindleRecipes.Initialize(Settings, log);
					KindleBatch.Initialize(Settings, log);
					KindleTracker.Initialize(Settings, log);
					KindleCarts.Initialize(Settings, log);
					KindleVirtualStation.Initialize(Settings);
					KindleStationReach.Initialize(Settings);
					KindleRepair.Initialize();
					KindleRecipes.ToggleTracking = KindleTracker.Toggle;
					KindleRecipes.IsTracked = KindleTracker.IsTracked;
					Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(Relabel));
				}
				started = true;
			}
			catch (Exception ex)
			{
				log.Error((object)("Kindle modules rejected: " + ex.GetType().Name + ": " + ex.Message));
				Shutdown();
			}
		}

		private void Update()
		{
			if (!Ready)
			{
				return;
			}
			Settings?.Tick(Time.unscaledTime);
			KindleText.Tick();
			if (!started)
			{
				return;
			}
			referenceImport?.Tick(GameplayAvailable);
			if (SteppedAside && AllowsUi && InventoryGui.IsVisible() && (Object)(object)MessageHud.instance != (Object)null && noticedSession != Plugin.Session.Generation)
			{
				noticedSession = Plugin.Session.Generation;
				IReadOnlyList<SourceMod> present = MeadworksStepAside.Decide("com.meadworks.kindle").Present;
				MessageHud.instance.ShowMessage((MessageType)2, KindleText.Format("step_aside", string.Join(", ", present.Select((SourceMod source) => source.Name))), 0, (Sprite)null, false, true);
			}
			KindleSalvage.Tick();
			if (GameplayAvailable && AllowsUi)
			{
				KindleRecipes.Tick();
				KindleBatch.Tick();
				KindleTracker.Tick();
				KindleCarts.Tick();
				KindleVirtualStation.T

plugins/Kindle/YamlDotNet.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.CodeAnalysis;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("13.7.1.0")]
[assembly: AssemblyInformationalVersion("13.7.1")]
[assembly: AssemblyTitle("YamlDotNet")]
[assembly: AssemblyDescription("The YamlDotNet library.")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("YamlDotNet")]
[assembly: AssemblyCopyright("Copyright (c) Antoine Aubry and contributors 2008 - 2019")]
[assembly: AssemblyTrademark("")]
[assembly: CLSCompliant(true)]
[assembly: InternalsVisibleTo("YamlDotNet.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010065e52a453dde5c5b4be5bbe2205755727fce80244b79b894faf8793d80f7db9a96d360b51c220782db32aacee4cb5b8a91bee33aeec700e1f21895c4baadef501eeeac609220d1651603b378173811ee5bb6a002df973d38821bd2fef820c00c174a69faec326a1983b570f07ec66147026b9c8753465de3a8d0c44b613b02af")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("13.0.0.0")]
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;
		}
	}
}
namespace YamlDotNet
{
	internal sealed class CultureInfoAdapter : CultureInfo
	{
		private readonly IFormatProvider provider;

		public CultureInfoAdapter(CultureInfo baseCulture, IFormatProvider provider)
			: base(baseCulture.Name)
		{
			this.provider = provider;
		}

		public override object GetFormat(Type formatType)
		{
			return provider.GetFormat(formatType);
		}
	}
	internal static class ReflectionExtensions
	{
		private static readonly Func<PropertyInfo, bool> IsInstance = (PropertyInfo property) => !(property.GetMethod ?? property.SetMethod).IsStatic;

		private static readonly Func<PropertyInfo, bool> IsInstancePublic = (PropertyInfo property) => IsInstance(property) && (property.GetMethod ?? property.SetMethod).IsPublic;

		public static Type? BaseType(this Type type)
		{
			return type.GetTypeInfo().BaseType;
		}

		public static bool IsValueType(this Type type)
		{
			return type.GetTypeInfo().IsValueType;
		}

		public static bool IsGenericType(this Type type)
		{
			return type.GetTypeInfo().IsGenericType;
		}

		public static bool IsGenericTypeDefinition(this Type type)
		{
			return type.GetTypeInfo().IsGenericTypeDefinition;
		}

		public static bool IsInterface(this Type type)
		{
			return type.GetTypeInfo().IsInterface;
		}

		public static bool IsEnum(this Type type)
		{
			return type.GetTypeInfo().IsEnum;
		}

		public static bool HasDefaultConstructor(this Type type, bool allowPrivateConstructors)
		{
			TypeInfo typeInfo = type.GetTypeInfo();
			if (!typeInfo.IsValueType)
			{
				return typeInfo.DeclaredConstructors.Any((ConstructorInfo c) => (c.IsPublic || (allowPrivateConstructors && c.IsPrivate)) && !c.IsStatic && c.GetParameters().Length == 0);
			}
			return true;
		}

		public static bool IsAssignableFrom(this Type type, Type source)
		{
			return type.IsAssignableFrom(source.GetTypeInfo());
		}

		public static bool IsAssignableFrom(this Type type, TypeInfo source)
		{
			return type.GetTypeInfo().IsAssignableFrom(source);
		}

		public static TypeCode GetTypeCode(this Type type)
		{
			if (type.IsEnum())
			{
				type = Enum.GetUnderlyingType(type);
			}
			if (type == typeof(bool))
			{
				return TypeCode.Boolean;
			}
			if (type == typeof(char))
			{
				return TypeCode.Char;
			}
			if (type == typeof(sbyte))
			{
				return TypeCode.SByte;
			}
			if (type == typeof(byte))
			{
				return TypeCode.Byte;
			}
			if (type == typeof(short))
			{
				return TypeCode.Int16;
			}
			if (type == typeof(ushort))
			{
				return TypeCode.UInt16;
			}
			if (type == typeof(int))
			{
				return TypeCode.Int32;
			}
			if (type == typeof(uint))
			{
				return TypeCode.UInt32;
			}
			if (type == typeof(long))
			{
				return TypeCode.Int64;
			}
			if (type == typeof(ulong))
			{
				return TypeCode.UInt64;
			}
			if (type == typeof(float))
			{
				return TypeCode.Single;
			}
			if (type == typeof(double))
			{
				return TypeCode.Double;
			}
			if (type == typeof(decimal))
			{
				return TypeCode.Decimal;
			}
			if (type == typeof(DateTime))
			{
				return TypeCode.DateTime;
			}
			if (type == typeof(string))
			{
				return TypeCode.String;
			}
			return TypeCode.Object;
		}

		public static bool IsDbNull(this object value)
		{
			return value?.GetType()?.FullName == "System.DBNull";
		}

		public static Type[] GetGenericArguments(this Type type)
		{
			return type.GetTypeInfo().GenericTypeArguments;
		}

		public static PropertyInfo? GetPublicProperty(this Type type, string name)
		{
			return type.GetRuntimeProperty(name);
		}

		public static FieldInfo? GetPublicStaticField(this Type type, string name)
		{
			return type.GetRuntimeField(name);
		}

		public static IEnumerable<PropertyInfo> GetProperties(this Type type, bool includeNonPublic)
		{
			Func<PropertyInfo, bool> predicate = (includeNonPublic ? IsInstance : IsInstancePublic);
			if (!type.IsInterface())
			{
				return type.GetRuntimeProperties().Where(predicate);
			}
			return new Type[1] { type }.Concat(type.GetInterfaces()).SelectMany((Type i) => i.GetRuntimeProperties().Where(predicate));
		}

		public static IEnumerable<PropertyInfo> GetPublicProperties(this Type type)
		{
			return type.GetProperties(includeNonPublic: false);
		}

		public static IEnumerable<FieldInfo> GetPublicFields(this Type type)
		{
			return from f in type.GetRuntimeFields()
				where !f.IsStatic && f.IsPublic
				select f;
		}

		public static IEnumerable<MethodInfo> GetPublicStaticMethods(this Type type)
		{
			return from m in type.GetRuntimeMethods()
				where m.IsPublic && m.IsStatic
				select m;
		}

		public static MethodInfo GetPrivateStaticMethod(this Type type, string name)
		{
			return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => !m.IsPublic && m.IsStatic && m.Name.Equals(name)) ?? throw new MissingMethodException("Expected to find a method named '" + name + "' in '" + type.FullName + "'.");
		}

		public static MethodInfo? GetPublicStaticMethod(this Type type, string name, params Type[] parameterTypes)
		{
			return type.GetRuntimeMethods().FirstOrDefault(delegate(MethodInfo m)
			{
				if (m.IsPublic && m.IsStatic && m.Name.Equals(name))
				{
					ParameterInfo[] parameters = m.GetParameters();
					if (parameters.Length == parameterTypes.Length)
					{
						return parameters.Zip(parameterTypes, (ParameterInfo pi, Type pt) => pi.ParameterType == pt).All((bool r) => r);
					}
					return false;
				}
				return false;
			});
		}

		public static MethodInfo? GetPublicInstanceMethod(this Type type, string name)
		{
			return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => m.IsPublic && !m.IsStatic && m.Name.Equals(name));
		}

		public static MethodInfo? GetGetMethod(this PropertyInfo property, bool nonPublic)
		{
			MethodInfo methodInfo = property.GetMethod;
			if (!nonPublic && !methodInfo.IsPublic)
			{
				methodInfo = null;
			}
			return methodInfo;
		}

		public static MethodInfo GetSetMethod(this PropertyInfo property)
		{
			return property.SetMethod;
		}

		public static IEnumerable<Type> GetInterfaces(this Type type)
		{
			return type.GetTypeInfo().ImplementedInterfaces;
		}

		public static Exception Unwrap(this TargetInvocationException ex)
		{
			return ex.InnerException;
		}

		public static bool IsInstanceOf(this Type type, object o)
		{
			if (!(o.GetType() == type))
			{
				return o.GetType().GetTypeInfo().IsSubclassOf(type);
			}
			return true;
		}

		public static Attribute[] GetAllCustomAttributes<TAttribute>(this PropertyInfo member)
		{
			List<Attribute> list = new List<Attribute>();
			Type type = member.DeclaringType;
			while (type != null)
			{
				type.GetPublicProperty(member.Name);
				list.AddRange(member.GetCustomAttributes(typeof(TAttribute)));
				type = type.BaseType();
			}
			return list.ToArray();
		}
	}
	internal static class PropertyInfoExtensions
	{
		public static object? ReadValue(this PropertyInfo property, object target)
		{
			return property.GetValue(target, null);
		}
	}
	internal static class StandardRegexOptions
	{
		public const RegexOptions Compiled = RegexOptions.Compiled;
	}
}
namespace YamlDotNet.Serialization
{
	public abstract class BuilderSkeleton<TBuilder> where TBuilder : BuilderSkeleton<TBuilder>
	{
		internal INamingConvention namingConvention = NullNamingConvention.Instance;

		internal ITypeResolver typeResolver;

		internal readonly YamlAttributeOverrides overrides;

		internal readonly LazyComponentRegistrationList<Nothing, IYamlTypeConverter> typeConverterFactories;

		internal readonly LazyComponentRegistrationList<ITypeInspector, ITypeInspector> typeInspectorFactories;

		internal bool ignoreFields;

		internal bool includeNonPublicProperties;

		internal Settings settings;

		internal YamlFormatter yamlFormatter = YamlFormatter.Default;

		protected abstract TBuilder Self { get; }

		internal BuilderSkeleton(ITypeResolver typeResolver)
		{
			overrides = new YamlAttributeOverrides();
			typeConverterFactories = new LazyComponentRegistrationList<Nothing, IYamlTypeConverter>
			{
				{
					typeof(YamlDotNet.Serialization.Converters.GuidConverter),
					(Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false)
				},
				{
					typeof(SystemTypeConverter),
					(Nothing _) => new SystemTypeConverter()
				}
			};
			typeInspectorFactories = new LazyComponentRegistrationList<ITypeInspector, ITypeInspector>();
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			settings = new Settings();
		}

		public TBuilder IgnoreFields()
		{
			ignoreFields = true;
			return Self;
		}

		public TBuilder IncludeNonPublicProperties()
		{
			includeNonPublicProperties = true;
			return Self;
		}

		public TBuilder EnablePrivateConstructors()
		{
			settings.AllowPrivateConstructors = true;
			return Self;
		}

		public TBuilder WithNamingConvention(INamingConvention namingConvention)
		{
			this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention");
			return Self;
		}

		public TBuilder WithTypeResolver(ITypeResolver typeResolver)
		{
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			return Self;
		}

		public abstract TBuilder WithTagMapping(TagName tag, Type type);

		public TBuilder WithAttributeOverride<TClass>(Expression<Func<TClass, object>> propertyAccessor, Attribute attribute)
		{
			overrides.Add(propertyAccessor, attribute);
			return Self;
		}

		public TBuilder WithAttributeOverride(Type type, string member, Attribute attribute)
		{
			overrides.Add(type, member, attribute);
			return Self;
		}

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter)
		{
			return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action<IRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where)
		{
			if (typeConverter == null)
			{
				throw new ArgumentNullException("typeConverter");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter.GetType(), (Nothing _) => typeConverter));
			return Self;
		}

		public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter
		{
			if (typeConverterFactory == null)
			{
				throw new ArgumentNullException("typeConverterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory(wrapped)));
			return Self;
		}

		public TBuilder WithoutTypeConverter<TYamlTypeConverter>() where TYamlTypeConverter : IYamlTypeConverter
		{
			return WithoutTypeConverter(typeof(TYamlTypeConverter));
		}

		public TBuilder WithoutTypeConverter(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			typeConverterFactories.Remove(converterType);
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory) where TTypeInspector : ITypeInspector
		{
			return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory, Action<IRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			if (typeInspectorFactory == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory(inner)));
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			if (typeInspectorFactory == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory(wrapped, inner)));
			return Self;
		}

		public TBuilder WithoutTypeInspector<TTypeInspector>() where TTypeInspector : ITypeInspector
		{
			return WithoutTypeInspector(typeof(TTypeInspector));
		}

		public TBuilder WithoutTypeInspector(Type inspectorType)
		{
			if (inspectorType == null)
			{
				throw new ArgumentNullException("inspectorType");
			}
			typeInspectorFactories.Remove(inspectorType);
			return Self;
		}

		public TBuilder WithYamlFormatter(YamlFormatter formatter)
		{
			yamlFormatter = formatter ?? throw new ArgumentNullException("formatter");
			return Self;
		}

		protected IEnumerable<IYamlTypeConverter> BuildTypeConverters()
		{
			return typeConverterFactories.BuildComponentList();
		}
	}
	public delegate TComponent WrapperFactory<TComponentBase, TComponent>(TComponentBase wrapped) where TComponent : TComponentBase;
	public delegate TComponent WrapperFactory<TArgument, TComponentBase, TComponent>(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase;
	[Flags]
	public enum DefaultValuesHandling
	{
		Preserve = 0,
		OmitNull = 1,
		OmitDefaults = 2,
		OmitEmptyCollections = 4
	}
	public sealed class Deserializer : IDeserializer
	{
		private readonly IValueDeserializer valueDeserializer;

		public Deserializer()
			: this(new DeserializerBuilder().BuildValueDeserializer())
		{
		}

		private Deserializer(IValueDeserializer valueDeserializer)
		{
			this.valueDeserializer = valueDeserializer ?? throw new ArgumentNullException("valueDeserializer");
		}

		public static Deserializer FromValueDeserializer(IValueDeserializer valueDeserializer)
		{
			return new Deserializer(valueDeserializer);
		}

		public T Deserialize<T>(string input)
		{
			using StringReader input2 = new StringReader(input);
			return Deserialize<T>(input2);
		}

		public T Deserialize<T>(TextReader input)
		{
			return Deserialize<T>(new Parser(input));
		}

		public T Deserialize<T>(IParser parser)
		{
			return (T)Deserialize(parser, typeof(T));
		}

		public object? Deserialize(string input)
		{
			return Deserialize(input, typeof(object));
		}

		public object? Deserialize(TextReader input)
		{
			return Deserialize(input, typeof(object));
		}

		public object? Deserialize(IParser parser)
		{
			return Deserialize(parser, typeof(object));
		}

		public object? Deserialize(string input, Type type)
		{
			using StringReader input2 = new StringReader(input);
			return Deserialize(input2, type);
		}

		public object? Deserialize(TextReader input, Type type)
		{
			return Deserialize(new Parser(input), type);
		}

		public object? Deserialize(IParser parser, Type type)
		{
			if (parser == null)
			{
				throw new ArgumentNullException("parser");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			YamlDotNet.Core.Events.StreamStart @event;
			bool flag = parser.TryConsume<YamlDotNet.Core.Events.StreamStart>(out @event);
			YamlDotNet.Core.Events.DocumentStart event2;
			bool flag2 = parser.TryConsume<YamlDotNet.Core.Events.DocumentStart>(out event2);
			object result = null;
			if (!parser.Accept<YamlDotNet.Core.Events.DocumentEnd>(out var _) && !parser.Accept<YamlDotNet.Core.Events.StreamEnd>(out var _))
			{
				using SerializerState serializerState = new SerializerState();
				result = valueDeserializer.DeserializeValue(parser, type, serializerState, valueDeserializer);
				serializerState.OnDeserialization();
			}
			if (flag2)
			{
				parser.Consume<YamlDotNet.Core.Events.DocumentEnd>();
			}
			if (flag)
			{
				parser.Consume<YamlDotNet.Core.Events.StreamEnd>();
			}
			return result;
		}
	}
	public sealed class DeserializerBuilder : BuilderSkeleton<DeserializerBuilder>
	{
		private Lazy<IObjectFactory> objectFactory;

		private readonly LazyComponentRegistrationList<Nothing, INodeDeserializer> nodeDeserializerFactories;

		private readonly LazyComponentRegistrationList<Nothing, INodeTypeResolver> nodeTypeResolverFactories;

		private readonly Dictionary<TagName, Type> tagMappings;

		private readonly Dictionary<Type, Type> typeMappings;

		private readonly ITypeConverter typeConverter;

		private bool ignoreUnmatched;

		private bool duplicateKeyChecking;

		private bool attemptUnknownTypeDeserialization;

		protected override DeserializerBuilder Self => this;

		public DeserializerBuilder()
			: base((ITypeResolver)new StaticTypeResolver())
		{
			typeMappings = new Dictionary<Type, Type>();
			objectFactory = new Lazy<IObjectFactory>(() => new DefaultObjectFactory(typeMappings, settings), isThreadSafe: true);
			tagMappings = new Dictionary<TagName, Type>
			{
				{
					FailsafeSchema.Tags.Map,
					typeof(Dictionary<object, object>)
				},
				{
					FailsafeSchema.Tags.Str,
					typeof(string)
				},
				{
					JsonSchema.Tags.Bool,
					typeof(bool)
				},
				{
					JsonSchema.Tags.Float,
					typeof(double)
				},
				{
					JsonSchema.Tags.Int,
					typeof(int)
				},
				{
					DefaultSchema.Tags.Timestamp,
					typeof(DateTime)
				}
			};
			typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner));
			typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner);
			typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner));
			typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone()));
			typeInspectorFactories.Add(typeof(ReadableAndWritablePropertiesTypeInspector), (ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner));
			nodeDeserializerFactories = new LazyComponentRegistrationList<Nothing, INodeDeserializer>
			{
				{
					typeof(YamlConvertibleNodeDeserializer),
					(Nothing _) => new YamlConvertibleNodeDeserializer(objectFactory.Value)
				},
				{
					typeof(YamlSerializableNodeDeserializer),
					(Nothing _) => new YamlSerializableNodeDeserializer(objectFactory.Value)
				},
				{
					typeof(TypeConverterNodeDeserializer),
					(Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters())
				},
				{
					typeof(NullNodeDeserializer),
					(Nothing _) => new NullNodeDeserializer()
				},
				{
					typeof(ScalarNodeDeserializer),
					(Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, yamlFormatter)
				},
				{
					typeof(ArrayNodeDeserializer),
					(Nothing _) => new ArrayNodeDeserializer()
				},
				{
					typeof(DictionaryNodeDeserializer),
					(Nothing _) => new DictionaryNodeDeserializer(objectFactory.Value, duplicateKeyChecking)
				},
				{
					typeof(CollectionNodeDeserializer),
					(Nothing _) => new CollectionNodeDeserializer(objectFactory.Value)
				},
				{
					typeof(EnumerableNodeDeserializer),
					(Nothing _) => new EnumerableNodeDeserializer()
				},
				{
					typeof(ObjectNodeDeserializer),
					(Nothing _) => new ObjectNodeDeserializer(objectFactory.Value, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter)
				}
			};
			nodeTypeResolverFactories = new LazyComponentRegistrationList<Nothing, INodeTypeResolver>
			{
				{
					typeof(MappingNodeTypeResolver),
					(Nothing _) => new MappingNodeTypeResolver(typeMappings)
				},
				{
					typeof(YamlConvertibleTypeResolver),
					(Nothing _) => new YamlConvertibleTypeResolver()
				},
				{
					typeof(YamlSerializableTypeResolver),
					(Nothing _) => new YamlSerializableTypeResolver()
				},
				{
					typeof(TagNodeTypeResolver),
					(Nothing _) => new TagNodeTypeResolver(tagMappings)
				},
				{
					typeof(PreventUnknownTagsNodeTypeResolver),
					(Nothing _) => new PreventUnknownTagsNodeTypeResolver()
				},
				{
					typeof(DefaultContainersNodeTypeResolver),
					(Nothing _) => new DefaultContainersNodeTypeResolver()
				}
			};
			typeConverter = new ReflectionTypeConverter();
		}

		internal ITypeInspector BuildTypeInspector()
		{
			ITypeInspector typeInspector = new WritablePropertiesTypeInspector(typeResolver, includeNonPublicProperties);
			if (!ignoreFields)
			{
				typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector);
			}
			return typeInspectorFactories.BuildComponentChain(typeInspector);
		}

		public DeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization()
		{
			attemptUnknownTypeDeserialization = true;
			return this;
		}

		public DeserializerBuilder WithObjectFactory(IObjectFactory objectFactory)
		{
			if (objectFactory == null)
			{
				throw new ArgumentNullException("objectFactory");
			}
			this.objectFactory = new Lazy<IObjectFactory>(() => objectFactory, isThreadSafe: true);
			return this;
		}

		public DeserializerBuilder WithObjectFactory(Func<Type, object> objectFactory)
		{
			if (objectFactory == null)
			{
				throw new ArgumentNullException("objectFactory");
			}
			return WithObjectFactory(new LambdaObjectFactory(objectFactory));
		}

		public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer)
		{
			return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> w)
			{
				w.OnTop();
			});
		}

		public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action<IRegistrationLocationSelectionSyntax<INodeDeserializer>> where)
		{
			if (nodeDeserializer == null)
			{
				throw new ArgumentNullException("nodeDeserializer");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer.GetType(), (Nothing _) => nodeDeserializer));
			return this;
		}

		public DeserializerBuilder WithNodeDeserializer<TNodeDeserializer>(WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeDeserializer>> where) where TNodeDeserializer : INodeDeserializer
		{
			if (nodeDeserializerFactory == null)
			{
				throw new ArgumentNullException("nodeDeserializerFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory(wrapped)));
			return this;
		}

		public DeserializerBuilder WithoutNodeDeserializer<TNodeDeserializer>() where TNodeDeserializer : INodeDeserializer
		{
			return WithoutNodeDeserializer(typeof(TNodeDeserializer));
		}

		public DeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType)
		{
			if (nodeDeserializerType == null)
			{
				throw new ArgumentNullException("nodeDeserializerType");
			}
			nodeDeserializerFactories.Remove(nodeDeserializerType);
			return this;
		}

		public DeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action<ITypeDiscriminatingNodeDeserializerOptions> configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1)
		{
			TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions();
			configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions);
			TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength);
			return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> s)
			{
				s.Before<DictionaryNodeDeserializer>();
			});
		}

		public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver)
		{
			return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax<INodeTypeResolver> w)
			{
				w.OnTop();
			});
		}

		public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action<IRegistrationLocationSelectionSyntax<INodeTypeResolver>> where)
		{
			if (nodeTypeResolver == null)
			{
				throw new ArgumentNullException("nodeTypeResolver");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver.GetType(), (Nothing _) => nodeTypeResolver));
			return this;
		}

		public DeserializerBuilder WithNodeTypeResolver<TNodeTypeResolver>(WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) where TNodeTypeResolver : INodeTypeResolver
		{
			if (nodeTypeResolverFactory == null)
			{
				throw new ArgumentNullException("nodeTypeResolverFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory(wrapped)));
			return this;
		}

		public DeserializerBuilder WithoutNodeTypeResolver<TNodeTypeResolver>() where TNodeTypeResolver : INodeTypeResolver
		{
			return WithoutNodeTypeResolver(typeof(TNodeTypeResolver));
		}

		public DeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType)
		{
			if (nodeTypeResolverType == null)
			{
				throw new ArgumentNullException("nodeTypeResolverType");
			}
			nodeTypeResolverFactories.Remove(nodeTypeResolverType);
			return this;
		}

		public override DeserializerBuilder WithTagMapping(TagName tag, Type type)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (tagMappings.TryGetValue(tag, out Type value))
			{
				throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag");
			}
			tagMappings.Add(tag, type);
			return this;
		}

		public DeserializerBuilder WithTypeMapping<TInterface, TConcrete>() where TConcrete : TInterface
		{
			Type typeFromHandle = typeof(TInterface);
			Type typeFromHandle2 = typeof(TConcrete);
			if (!typeFromHandle.IsAssignableFrom(typeFromHandle2))
			{
				throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'.");
			}
			if (typeMappings.ContainsKey(typeFromHandle))
			{
				typeMappings[typeFromHandle] = typeFromHandle2;
			}
			else
			{
				typeMappings.Add(typeFromHandle, typeFromHandle2);
			}
			return this;
		}

		public DeserializerBuilder WithoutTagMapping(TagName tag)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (!tagMappings.Remove(tag))
			{
				throw new KeyNotFoundException($"Tag '{tag}' is not registered");
			}
			return this;
		}

		public DeserializerBuilder IgnoreUnmatchedProperties()
		{
			ignoreUnmatched = true;
			return this;
		}

		public DeserializerBuilder WithDuplicateKeyChecking()
		{
			duplicateKeyChecking = true;
			return this;
		}

		public IDeserializer Build()
		{
			return Deserializer.FromValueDeserializer(BuildValueDeserializer());
		}

		public IValueDeserializer BuildValueDeserializer()
		{
			return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter));
		}
	}
	public sealed class EmissionPhaseObjectGraphVisitorArgs
	{
		private readonly IEnumerable<IObjectGraphVisitor<Nothing>> preProcessingPhaseVisitors;

		public IObjectGraphVisitor<IEmitter> InnerVisitor { get; private set; }

		public IEventEmitter EventEmitter { get; private set; }

		public ObjectSerializer NestedObjectSerializer { get; private set; }

		public IEnumerable<IYamlTypeConverter> TypeConverters { get; private set; }

		public EmissionPhaseObjectGraphVisitorArgs(IObjectGraphVisitor<IEmitter> innerVisitor, IEventEmitter eventEmitter, IEnumerable<IObjectGraphVisitor<Nothing>> preProcessingPhaseVisitors, IEnumerable<IYamlTypeConverter> typeConverters, ObjectSerializer nestedObjectSerializer)
		{
			InnerVisitor = innerVisitor ?? throw new ArgumentNullException("innerVisitor");
			EventEmitter = eventEmitter ?? throw new ArgumentNullException("eventEmitter");
			this.preProcessingPhaseVisitors = preProcessingPhaseVisitors ?? throw new ArgumentNullException("preProcessingPhaseVisitors");
			TypeConverters = typeConverters ?? throw new ArgumentNullException("typeConverters");
			NestedObjectSerializer = nestedObjectSerializer ?? throw new ArgumentNullException("nestedObjectSerializer");
		}

		public T GetPreProcessingPhaseObjectGraphVisitor<T>() where T : IObjectGraphVisitor<Nothing>
		{
			return preProcessingPhaseVisitors.OfType<T>().Single();
		}
	}
	public abstract class EventInfo
	{
		public IObjectDescriptor Source { get; }

		protected EventInfo(IObjectDescriptor source)
		{
			Source = source ?? throw new ArgumentNullException("source");
		}
	}
	public class AliasEventInfo : EventInfo
	{
		public AnchorName Alias { get; }

		public bool NeedsExpansion { get; set; }

		public AliasEventInfo(IObjectDescriptor source, AnchorName alias)
			: base(source)
		{
			if (alias.IsEmpty)
			{
				throw new ArgumentNullException("alias");
			}
			Alias = alias;
		}
	}
	public class ObjectEventInfo : EventInfo
	{
		public AnchorName Anchor { get; set; }

		public TagName Tag { get; set; }

		protected ObjectEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	public sealed class ScalarEventInfo : ObjectEventInfo
	{
		public string RenderedValue { get; set; }

		public ScalarStyle Style { get; set; }

		public bool IsPlainImplicit { get; set; }

		public bool IsQuotedImplicit { get; set; }

		public ScalarEventInfo(IObjectDescriptor source)
			: base(source)
		{
			Style = source.ScalarStyle;
			RenderedValue = string.Empty;
		}
	}
	public sealed class MappingStartEventInfo : ObjectEventInfo
	{
		public bool IsImplicit { get; set; }

		public MappingStyle Style { get; set; }

		public MappingStartEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	public sealed class MappingEndEventInfo : EventInfo
	{
		public MappingEndEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	public sealed class SequenceStartEventInfo : ObjectEventInfo
	{
		public bool IsImplicit { get; set; }

		public SequenceStyle Style { get; set; }

		public SequenceStartEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	public sealed class SequenceEndEventInfo : EventInfo
	{
		public SequenceEndEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	public interface IAliasProvider
	{
		AnchorName GetAlias(object target);
	}
	public interface IDeserializer
	{
		T Deserialize<T>(string input);

		T Deserialize<T>(TextReader input);

		T Deserialize<T>(IParser parser);

		object? Deserialize(string input);

		object? Deserialize(TextReader input);

		object? Deserialize(IParser parser);

		object? Deserialize(string input, Type type);

		object? Deserialize(TextReader input, Type type);

		object? Deserialize(IParser parser, Type type);
	}
	public interface IEventEmitter
	{
		void Emit(AliasEventInfo eventInfo, IEmitter emitter);

		void Emit(ScalarEventInfo eventInfo, IEmitter emitter);

		void Emit(MappingStartEventInfo eventInfo, IEmitter emitter);

		void Emit(MappingEndEventInfo eventInfo, IEmitter emitter);

		void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter);

		void Emit(SequenceEndEventInfo eventInfo, IEmitter emitter);
	}
	public interface INamingConvention
	{
		string Apply(string value);
	}
	public interface INodeDeserializer
	{
		bool Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value);
	}
	public interface INodeTypeResolver
	{
		bool Resolve(NodeEvent? nodeEvent, ref Type currentType);
	}
	public interface IObjectAccessor
	{
		void Set(string name, object target, object value);

		object? Read(string name, object target);
	}
	public interface IObjectDescriptor
	{
		object? Value { get; }

		Type Type { get; }

		Type StaticType { get; }

		ScalarStyle ScalarStyle { get; }
	}
	public static class ObjectDescriptorExtensions
	{
		public static object NonNullValue(this IObjectDescriptor objectDescriptor)
		{
			return objectDescriptor.Value ?? throw new InvalidOperationException("Attempted to use a IObjectDescriptor of type '" + objectDescriptor.Type.FullName + "' whose Value is null at a point whete it is invalid to do so. This may indicate a bug in YamlDotNet.");
		}
	}
	public interface IObjectFactory
	{
		object Create(Type type);

		object? CreatePrimitive(Type type);

		bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments);

		Type GetValueType(Type type);

		void ExecuteOnDeserializing(object value);

		void ExecuteOnDeserialized(object value);

		void ExecuteOnSerializing(object value);

		void ExecuteOnSerialized(object value);
	}
	public interface IObjectGraphTraversalStrategy
	{
		void Traverse<TContext>(IObjectDescriptor graph, IObjectGraphVisitor<TContext> visitor, TContext context);
	}
	public interface IObjectGraphVisitor<TContext>
	{
		bool Enter(IObjectDescriptor value, TContext context);

		bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, TContext context);

		bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, TContext context);

		void VisitScalar(IObjectDescriptor scalar, TContext context);

		void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, TContext context);

		void VisitMappingEnd(IObjectDescriptor mapping, TContext context);

		void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, TContext context);

		void VisitSequenceEnd(IObjectDescriptor sequence, TContext context);
	}
	public interface IPropertyDescriptor
	{
		string Name { get; }

		bool CanWrite { get; }

		Type Type { get; }

		Type? TypeOverride { get; set; }

		int Order { get; set; }

		ScalarStyle ScalarStyle { get; set; }

		T? GetCustomAttribute<T>() where T : Attribute;

		IObjectDescriptor Read(object target);

		void Write(object target, object? value);
	}
	public interface IRegistrationLocationSelectionSyntax<TBaseRegistrationType>
	{
		void InsteadOf<TRegistrationType>() where TRegistrationType : TBaseRegistrationType;

		void Before<TRegistrationType>() where TRegistrationType : TBaseRegistrationType;

		void After<TRegistrationType>() where TRegistrationType : TBaseRegistrationType;

		void OnTop();

		void OnBottom();
	}
	public interface ITrackingRegistrationLocationSelectionSyntax<TBaseRegistrationType>
	{
		void InsteadOf<TRegistrationType>() where TRegistrationType : TBaseRegistrationType;
	}
	public interface ISerializer
	{
		string Serialize(object? graph);

		string Serialize(object? graph, Type type);

		void Serialize(TextWriter writer, object? graph);

		void Serialize(TextWriter writer, object? graph, Type type);

		void Serialize(IEmitter emitter, object? graph);

		void Serialize(IEmitter emitter, object? graph, Type type);
	}
	public interface ITypeInspector
	{
		IEnumerable<IPropertyDescriptor> GetProperties(Type type, object? container);

		IPropertyDescriptor GetProperty(Type type, object? container, string name, [MaybeNullWhen(true)] bool ignoreUnmatched);
	}
	public interface ITypeResolver
	{
		Type Resolve(Type staticType, object? actualValue);
	}
	public interface IValueDeserializer
	{
		object? DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer);
	}
	public interface IValuePromise
	{
		event Action<object?> ValueAvailable;
	}
	public interface IValueSerializer
	{
		void SerializeValue(IEmitter emitter, object? value, Type? type);
	}
	public interface IYamlConvertible
	{
		void Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer);

		void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer);
	}
	public delegate object? ObjectDeserializer(Type type);
	public delegate void ObjectSerializer(object? value, Type? type = null);
	[Obsolete("Please use IYamlConvertible instead")]
	public interface IYamlSerializable
	{
		void ReadYaml(IParser parser);

		void WriteYaml(IEmitter emitter);
	}
	public interface IYamlTypeConverter
	{
		bool Accepts(Type type);

		object? ReadYaml(IParser parser, Type type);

		void WriteYaml(IEmitter emitter, object? value, Type type);
	}
	internal sealed class LazyComponentRegistrationList<TArgument, TComponent> : IEnumerable<Func<TArgument, TComponent>>, IEnumerable
	{
		public sealed class LazyComponentRegistration
		{
			public readonly Type ComponentType;

			public readonly Func<TArgument, TComponent> Factory;

			public LazyComponentRegistration(Type componentType, Func<TArgument, TComponent> factory)
			{
				ComponentType = componentType;
				Factory = factory;
			}
		}

		public sealed class TrackingLazyComponentRegistration
		{
			public readonly Type ComponentType;

			public readonly Func<TComponent, TArgument, TComponent> Factory;

			public TrackingLazyComponentRegistration(Type componentType, Func<TComponent, TArgument, TComponent> factory)
			{
				ComponentType = componentType;
				Factory = factory;
			}
		}

		private class RegistrationLocationSelector : IRegistrationLocationSelectionSyntax<TComponent>
		{
			private readonly LazyComponentRegistrationList<TArgument, TComponent> registrations;

			private readonly LazyComponentRegistration newRegistration;

			public RegistrationLocationSelector(LazyComponentRegistrationList<TArgument, TComponent> registrations, LazyComponentRegistration newRegistration)
			{
				this.registrations = registrations;
				this.newRegistration = newRegistration;
			}

			void IRegistrationLocationSelectionSyntax<TComponent>.InsteadOf<TRegistrationType>()
			{
				if (newRegistration.ComponentType != typeof(TRegistrationType))
				{
					registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				}
				int index = registrations.EnsureRegistrationExists<TRegistrationType>();
				registrations.entries[index] = newRegistration;
			}

			void IRegistrationLocationSelectionSyntax<TComponent>.After<TRegistrationType>()
			{
				registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				int num = registrations.EnsureRegistrationExists<TRegistrationType>();
				registrations.entries.Insert(num + 1, newRegistration);
			}

			void IRegistrationLocationSelectionSyntax<TComponent>.Before<TRegistrationType>()
			{
				registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				int index = registrations.EnsureRegistrationExists<TRegistrationType>();
				registrations.entries.Insert(index, newRegistration);
			}

			void IRegistrationLocationSelectionSyntax<TComponent>.OnBottom()
			{
				registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				registrations.entries.Add(newRegistration);
			}

			void IRegistrationLocationSelectionSyntax<TComponent>.OnTop()
			{
				registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				registrations.entries.Insert(0, newRegistration);
			}
		}

		private class TrackingRegistrationLocationSelector : ITrackingRegistrationLocationSelectionSyntax<TComponent>
		{
			private readonly LazyComponentRegistrationList<TArgument, TComponent> registrations;

			private readonly TrackingLazyComponentRegistration newRegistration;

			public TrackingRegistrationLocationSelector(LazyComponentRegistrationList<TArgument, TComponent> registrations, TrackingLazyComponentRegistration newRegistration)
			{
				this.registrations = registrations;
				this.newRegistration = newRegistration;
			}

			void ITrackingRegistrationLocationSelectionSyntax<TComponent>.InsteadOf<TRegistrationType>()
			{
				if (newRegistration.ComponentType != typeof(TRegistrationType))
				{
					registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType);
				}
				int index = registrations.EnsureRegistrationExists<TRegistrationType>();
				Func<TArgument, TComponent> innerComponentFactory = registrations.entries[index].Factory;
				registrations.entries[index] = new LazyComponentRegistration(newRegistration.ComponentType, (TArgument arg) => newRegistration.Factory(innerComponentFactory(arg), arg));
			}
		}

		private readonly List<LazyComponentRegistration> entries = new List<LazyComponentRegistration>();

		public int Count => entries.Count;

		public IEnumerable<Func<TArgument, TComponent>> InReverseOrder
		{
			get
			{
				int i = entries.Count - 1;
				while (i >= 0)
				{
					yield return entries[i].Factory;
					int num = i - 1;
					i = num;
				}
			}
		}

		public LazyComponentRegistrationList<TArgument, TComponent> Clone()
		{
			LazyComponentRegistrationList<TArgument, TComponent> lazyComponentRegistrationList = new LazyComponentRegistrationList<TArgument, TComponent>();
			foreach (LazyComponentRegistration entry in entries)
			{
				lazyComponentRegistrationList.entries.Add(entry);
			}
			return lazyComponentRegistrationList;
		}

		public void Clear()
		{
			entries.Clear();
		}

		public void Add(Type componentType, Func<TArgument, TComponent> factory)
		{
			entries.Add(new LazyComponentRegistration(componentType, factory));
		}

		public void Remove(Type componentType)
		{
			for (int i = 0; i < entries.Count; i++)
			{
				if (entries[i].ComponentType == componentType)
				{
					entries.RemoveAt(i);
					return;
				}
			}
			throw new KeyNotFoundException("A component registration of type '" + componentType.FullName + "' was not found.");
		}

		public IRegistrationLocationSelectionSyntax<TComponent> CreateRegistrationLocationSelector(Type componentType, Func<TArgument, TComponent> factory)
		{
			return new RegistrationLocationSelector(this, new LazyComponentRegistration(componentType, factory));
		}

		public ITrackingRegistrationLocationSelectionSyntax<TComponent> CreateTrackingRegistrationLocationSelector(Type componentType, Func<TComponent, TArgument, TComponent> factory)
		{
			return new TrackingRegistrationLocationSelector(this, new TrackingLazyComponentRegistration(componentType, factory));
		}

		public IEnumerator<Func<TArgument, TComponent>> GetEnumerator()
		{
			return entries.Select((LazyComponentRegistration e) => e.Factory).GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private int IndexOfRegistration(Type registrationType)
		{
			for (int i = 0; i < entries.Count; i++)
			{
				if (registrationType == entries[i].ComponentType)
				{
					return i;
				}
			}
			return -1;
		}

		private void EnsureNoDuplicateRegistrationType(Type componentType)
		{
			if (IndexOfRegistration(componentType) != -1)
			{
				throw new InvalidOperationException("A component of type '" + componentType.FullName + "' has already been registered.");
			}
		}

		private int EnsureRegistrationExists<TRegistrationType>()
		{
			int num = IndexOfRegistration(typeof(TRegistrationType));
			if (num == -1)
			{
				throw new InvalidOperationException("A component of type '" + typeof(TRegistrationType).FullName + "' has not been registered.");
			}
			return num;
		}
	}
	internal static class LazyComponentRegistrationListExtensions
	{
		public static TComponent BuildComponentChain<TComponent>(this LazyComponentRegistrationList<TComponent, TComponent> registrations, TComponent innerComponent)
		{
			return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func<TComponent, TComponent> factory) => factory(inner));
		}

		public static TComponent BuildComponentChain<TArgument, TComponent>(this LazyComponentRegistrationList<TArgument, TComponent> registrations, TComponent innerComponent, Func<TComponent, TArgument> argumentBuilder)
		{
			return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func<TArgument, TComponent> factory) => factory(argumentBuilder(inner)));
		}

		public static List<TComponent> BuildComponentList<TComponent>(this LazyComponentRegistrationList<Nothing, TComponent> registrations)
		{
			return registrations.Select((Func<Nothing, TComponent> factory) => factory(default(Nothing))).ToList();
		}

		public static List<TComponent> BuildComponentList<TArgument, TComponent>(this LazyComponentRegistrationList<TArgument, TComponent> registrations, TArgument argument)
		{
			return registrations.Select((Func<TArgument, TComponent> factory) => factory(argument)).ToList();
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct Nothing
	{
	}
	public sealed class ObjectDescriptor : IObjectDescriptor
	{
		public object? Value { get; private set; }

		public Type Type { get; private set; }

		public Type StaticType { get; private set; }

		public ScalarStyle ScalarStyle { get; private set; }

		public ObjectDescriptor(object? value, Type type, Type staticType)
			: this(value, type, staticType, ScalarStyle.Any)
		{
		}

		public ObjectDescriptor(object? value, Type type, Type staticType, ScalarStyle scalarStyle)
		{
			Value = value;
			Type = type ?? throw new ArgumentNullException("type");
			StaticType = staticType ?? throw new ArgumentNullException("staticType");
			ScalarStyle = scalarStyle;
		}
	}
	public delegate IObjectGraphTraversalStrategy ObjectGraphTraversalStrategyFactory(ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion);
	public sealed class PropertyDescriptor : IPropertyDescriptor
	{
		private readonly IPropertyDescriptor baseDescriptor;

		public string Name { get; set; }

		public Type Type => baseDescriptor.Type;

		public Type? TypeOverride
		{
			get
			{
				return baseDescriptor.TypeOverride;
			}
			set
			{
				baseDescriptor.TypeOverride = value;
			}
		}

		public int Order { get; set; }

		public ScalarStyle ScalarStyle
		{
			get
			{
				return baseDescriptor.ScalarStyle;
			}
			set
			{
				baseDescriptor.ScalarStyle = value;
			}
		}

		public bool CanWrite => baseDescriptor.CanWrite;

		public PropertyDescriptor(IPropertyDescriptor baseDescriptor)
		{
			this.baseDescriptor = baseDescriptor;
			Name = baseDescriptor.Name;
		}

		public void Write(object target, object? value)
		{
			baseDescriptor.Write(target, value);
		}

		public T? GetCustomAttribute<T>() where T : Attribute
		{
			return baseDescriptor.GetCustomAttribute<T>();
		}

		public IObjectDescriptor Read(object target)
		{
			return baseDescriptor.Read(target);
		}
	}
	public sealed class Serializer : ISerializer
	{
		private readonly IValueSerializer valueSerializer;

		private readonly EmitterSettings emitterSettings;

		public Serializer()
			: this(new SerializerBuilder().BuildValueSerializer(), EmitterSettings.Default)
		{
		}

		private Serializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings)
		{
			this.valueSerializer = valueSerializer ?? throw new ArgumentNullException("valueSerializer");
			this.emitterSettings = emitterSettings ?? throw new ArgumentNullException("emitterSettings");
		}

		public static Serializer FromValueSerializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings)
		{
			return new Serializer(valueSerializer, emitterSettings);
		}

		public string Serialize(object? graph)
		{
			using StringWriter stringWriter = new StringWriter();
			Serialize(stringWriter, graph);
			return stringWriter.ToString();
		}

		public string Serialize(object? graph, Type type)
		{
			using StringWriter stringWriter = new StringWriter();
			Serialize(stringWriter, graph, type);
			return stringWriter.ToString();
		}

		public void Serialize(TextWriter writer, object? graph)
		{
			Serialize(new Emitter(writer, emitterSettings), graph);
		}

		public void Serialize(TextWriter writer, object? graph, Type type)
		{
			Serialize(new Emitter(writer, emitterSettings), graph, type);
		}

		public void Serialize(IEmitter emitter, object? graph)
		{
			if (emitter == null)
			{
				throw new ArgumentNullException("emitter");
			}
			EmitDocument(emitter, graph, null);
		}

		public void Serialize(IEmitter emitter, object? graph, Type type)
		{
			if (emitter == null)
			{
				throw new ArgumentNullException("emitter");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			EmitDocument(emitter, graph, type);
		}

		private void EmitDocument(IEmitter emitter, object? graph, Type? type)
		{
			emitter.Emit(new YamlDotNet.Core.Events.StreamStart());
			emitter.Emit(new YamlDotNet.Core.Events.DocumentStart());
			valueSerializer.SerializeValue(emitter, graph, type);
			emitter.Emit(new YamlDotNet.Core.Events.DocumentEnd(isImplicit: true));
			emitter.Emit(new YamlDotNet.Core.Events.StreamEnd());
		}
	}
	public sealed class SerializerBuilder : BuilderSkeleton<SerializerBuilder>
	{
		private class ValueSerializer : IValueSerializer
		{
			private readonly IObjectGraphTraversalStrategy traversalStrategy;

			private readonly IEventEmitter eventEmitter;

			private readonly IEnumerable<IYamlTypeConverter> typeConverters;

			private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories;

			private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories;

			public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable<IYamlTypeConverter> typeConverters, LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories)
			{
				this.traversalStrategy = traversalStrategy;
				this.eventEmitter = eventEmitter;
				this.typeConverters = typeConverters;
				this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories;
				this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories;
			}

			public void SerializeValue(IEmitter emitter, object? value, Type? type)
			{
				Type type2 = type ?? ((value != null) ? value.GetType() : typeof(object));
				Type staticType = type ?? typeof(object);
				ObjectDescriptor graph = new ObjectDescriptor(value, type2, staticType);
				List<IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitors = preProcessingPhaseObjectGraphVisitorFactories.BuildComponentList(typeConverters);
				foreach (IObjectGraphVisitor<Nothing> item in preProcessingPhaseObjectGraphVisitors)
				{
					traversalStrategy.Traverse(graph, item, default(Nothing));
				}
				IObjectGraphVisitor<IEmitter> visitor = emissionPhaseObjectGraphVisitorFactories.BuildComponentChain<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>>(new EmittingObjectGraphVisitor(eventEmitter), (IObjectGraphVisitor<IEmitter> inner) => new EmissionPhaseObjectGraphVisitorArgs(inner, eventEmitter, preProcessingPhaseObjectGraphVisitors, typeConverters, NestedObjectSerializer));
				traversalStrategy.Traverse(graph, visitor, emitter);
				void NestedObjectSerializer(object? v, Type? t)
				{
					SerializeValue(emitter, v, t);
				}
			}
		}

		private ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory;

		private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories;

		private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories;

		private readonly LazyComponentRegistrationList<IEventEmitter, IEventEmitter> eventEmitterFactories;

		private readonly IDictionary<Type, TagName> tagMappings = new Dictionary<Type, TagName>();

		private readonly IObjectFactory objectFactory;

		private int maximumRecursion = 50;

		private EmitterSettings emitterSettings = EmitterSettings.Default;

		private DefaultValuesHandling defaultValuesHandlingConfiguration;

		private ScalarStyle defaultScalarStyle;

		private bool quoteNecessaryStrings;

		private bool quoteYaml1_1Strings;

		protected override SerializerBuilder Self => this;

		public SerializerBuilder()
			: base((ITypeResolver)new DynamicTypeResolver())
		{
			typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner));
			typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner);
			typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner));
			typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone()));
			preProcessingPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> { 
			{
				typeof(AnchorAssigner),
				(IEnumerable<IYamlTypeConverter> typeConverters) => new AnchorAssigner(typeConverters)
			} };
			emissionPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>>
			{
				{
					typeof(CustomSerializationObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new CustomSerializationObjectGraphVisitor(args.InnerVisitor, args.TypeConverters, args.NestedObjectSerializer)
				},
				{
					typeof(AnchorAssigningObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new AnchorAssigningObjectGraphVisitor(args.InnerVisitor, args.EventEmitter, args.GetPreProcessingPhaseObjectGraphVisitor<AnchorAssigner>())
				},
				{
					typeof(DefaultValuesObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new DefaultValuesObjectGraphVisitor(defaultValuesHandlingConfiguration, args.InnerVisitor, new DefaultObjectFactory())
				},
				{
					typeof(CommentsObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new CommentsObjectGraphVisitor(args.InnerVisitor)
				}
			};
			eventEmitterFactories = new LazyComponentRegistrationList<IEventEmitter, IEventEmitter> { 
			{
				typeof(TypeAssigningEventEmitter),
				(IEventEmitter inner) => new TypeAssigningEventEmitter(inner, requireTagWhenStaticAndActualTypesAreDifferent: false, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter)
			} };
			objectFactory = new DefaultObjectFactory();
			objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, namingConvention, objectFactory);
		}

		public SerializerBuilder WithQuotingNecessaryStrings(bool quoteYaml1_1Strings = false)
		{
			quoteNecessaryStrings = true;
			this.quoteYaml1_1Strings = quoteYaml1_1Strings;
			return this;
		}

		public SerializerBuilder WithDefaultScalarStyle(ScalarStyle style)
		{
			defaultScalarStyle = style;
			return this;
		}

		public SerializerBuilder WithMaximumRecursion(int maximumRecursion)
		{
			if (maximumRecursion <= 0)
			{
				throw new ArgumentOutOfRangeException("maximumRecursion", $"The maximum recursion specified ({maximumRecursion}) is invalid. It should be a positive integer.");
			}
			this.maximumRecursion = maximumRecursion;
			return this;
		}

		public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory) where TEventEmitter : IEventEmitter
		{
			return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> w)
			{
				w.OnTop();
			});
		}

		public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory, Action<IRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter
		{
			if (eventEmitterFactory == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory(inner)));
			return Self;
		}

		public SerializerBuilder WithEventEmitter<TEventEmitter>(WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter
		{
			if (eventEmitterFactory == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory(wrapped, inner)));
			return Self;
		}

		public SerializerBuilder WithoutEventEmitter<TEventEmitter>() where TEventEmitter : IEventEmitter
		{
			return WithoutEventEmitter(typeof(TEventEmitter));
		}

		public SerializerBuilder WithoutEventEmitter(Type eventEmitterType)
		{
			if (eventEmitterType == null)
			{
				throw new ArgumentNullException("eventEmitterType");
			}
			eventEmitterFactories.Remove(eventEmitterType);
			return this;
		}

		public override SerializerBuilder WithTagMapping(TagName tag, Type type)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (tagMappings.TryGetValue(type, out var value))
			{
				throw new ArgumentException($"Type already has a registered tag '{value}' for type '{type.FullName}'", "type");
			}
			tagMappings.Add(type, tag);
			return this;
		}

		public SerializerBuilder WithoutTagMapping(Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (!tagMappings.Remove(type))
			{
				throw new KeyNotFoundException("Tag for type '" + type.FullName + "' is not registered");
			}
			return this;
		}

		public SerializerBuilder EnsureRoundtrip()
		{
			objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new RoundtripObjectGraphTraversalStrategy(typeConverters, typeInspector, typeResolver, maximumRecursion, namingConvention, settings, objectFactory);
			WithEventEmitter((IEventEmitter inner) => new TypeAssigningEventEmitter(inner, requireTagWhenStaticAndActualTypesAreDifferent: true, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc)
			{
				loc.InsteadOf<TypeAssigningEventEmitter>();
			});
			return WithTypeInspector((ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner), delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> loc)
			{
				loc.OnBottom();
			});
		}

		public SerializerBuilder DisableAliases()
		{
			preProcessingPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigner));
			emissionPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigningObjectGraphVisitor));
			return this;
		}

		[Obsolete("The default behavior is now to always emit default values, thefore calling this method has no effect. This behavior is now controlled by ConfigureDefaultValuesHandling.", true)]
		public SerializerBuilder EmitDefaults()
		{
			return ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve);
		}

		public SerializerBuilder ConfigureDefaultValuesHandling(DefaultValuesHandling configuration)
		{
			defaultValuesHandlingConfiguration = configuration;
			return this;
		}

		public SerializerBuilder JsonCompatible()
		{
			emitterSettings = emitterSettings.WithMaxSimpleKeyLength(int.MaxValue).WithoutAnchorName();
			return WithTypeConverter(new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: true), delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w)
			{
				w.InsteadOf<YamlDotNet.Serialization.Converters.GuidConverter>();
			}).WithTypeConverter(new YamlDotNet.Serialization.Converters.DateTimeConverter(DateTimeKind.Utc, null, true)).WithEventEmitter((IEventEmitter inner) => new JsonEventEmitter(inner, yamlFormatter), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc)
			{
				loc.InsteadOf<TypeAssigningEventEmitter>();
			});
		}

		public SerializerBuilder WithNewLine(string newLine)
		{
			emitterSettings = emitterSettings.WithNewLine(newLine);
			return this;
		}

		public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing>
		{
			return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitor, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>> w)
			{
				w.OnTop();
			});
		}

		public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor, Action<IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing>
		{
			if (objectGraphVisitor == null)
			{
				throw new ArgumentNullException("objectGraphVisitor");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable<IYamlTypeConverter> _) => objectGraphVisitor));
			return this;
		}

		public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(WrapperFactory<IObjectGraphVisitor<Nothing>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing>
		{
			if (objectGraphVisitorFactory == null)
			{
				throw new ArgumentNullException("objectGraphVisitorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor<Nothing> wrapped, IEnumerable<IYamlTypeConverter> _) => objectGraphVisitorFactory(wrapped)));
			return this;
		}

		public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>() where TObjectGraphVisitor : IObjectGraphVisitor<Nothing>
		{
			return WithoutPreProcessingPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor));
		}

		public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor(Type objectGraphVisitorType)
		{
			if (objectGraphVisitorType == null)
			{
				throw new ArgumentNullException("objectGraphVisitorType");
			}
			preProcessingPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType);
			return this;
		}

		public SerializerBuilder WithObjectGraphTraversalStrategyFactory(ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory)
		{
			this.objectGraphTraversalStrategyFactory = objectGraphTraversalStrategyFactory;
			return this;
		}

		public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<EmissionPhaseObjectGraphVisitorArgs, TObjectGraphVisitor> objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter>
		{
			return WithEmissionPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>> w)
			{
				w.OnTop();
			});
		}

		public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<EmissionPhaseObjectGraphVisitorArgs, TObjectGraphVisitor> objectGraphVisitorFactory, Action<IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter>
		{
			if (objectGraphVisitorFactory == null)
			{
				throw new ArgumentNullException("objectGraphVisitorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(emissionPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory(args)));
			return this;
		}

		public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(WrapperFactory<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter>
		{
			if (objectGraphVisitorFactory == null)
			{
				throw new ArgumentNullException("objectGraphVisitorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(emissionPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor<IEmitter> wrapped, EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory(wrapped, args)));
			return this;
		}

		public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>() where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter>
		{
			return WithoutEmissionPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor));
		}

		public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor(Type objectGraphVisitorType)
		{
			if (objectGraphVisitorType == null)
			{
				throw new ArgumentNullException("objectGraphVisitorType");
			}
			emissionPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType);
			return this;
		}

		public SerializerBuilder WithIndentedSequences()
		{
			emitterSettings = emitterSettings.WithIndentedSequences();
			return this;
		}

		public ISerializer Build()
		{
			return Serializer.FromValueSerializer(BuildValueSerializer(), emitterSettings);
		}

		public IValueSerializer BuildValueSerializer()
		{
			IEnumerable<IYamlTypeConverter> typeConverters = BuildTypeConverters();
			ITypeInspector typeInspector = BuildTypeInspector();
			IObjectGraphTraversalStrategy traversalStrategy = objectGraphTraversalStrategyFactory(typeInspector, typeResolver, typeConverters, maximumRecursion);
			IEventEmitter eventEmitter = eventEmitterFactories.BuildComponentChain(new WriterEventEmitter());
			return new ValueSerializer(traversalStrategy, eventEmitter, typeConverters, preProcessingPhaseObjectGraphVisitorFactories.Clone(), emissionPhaseObjectGraphVisitorFactories.Clone());
		}

		internal ITypeInspector BuildTypeInspector()
		{
			ITypeInspector typeInspector = new ReadablePropertiesTypeInspector(typeResolver, includeNonPublicProperties);
			if (!ignoreFields)
			{
				typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector);
			}
			return typeInspectorFactories.BuildComponentChain(typeInspector);
		}
	}
	public class Settings
	{
		public bool AllowPrivateConstructors { get; set; }
	}
	public abstract class StaticBuilderSkeleton<TBuilder> where TBuilder : StaticBuilderSkeleton<TBuilder>
	{
		internal INamingConvention namingConvention = NullNamingConvention.Instance;

		internal ITypeResolver typeResolver;

		internal readonly LazyComponentRegistrationList<Nothing, IYamlTypeConverter> typeConverterFactories;

		internal readonly LazyComponentRegistrationList<ITypeInspector, ITypeInspector> typeInspectorFactories;

		internal bool includeNonPublicProperties;

		internal Settings settings;

		internal YamlFormatter yamlFormatter = YamlFormatter.Default;

		protected abstract TBuilder Self { get; }

		internal StaticBuilderSkeleton(ITypeResolver typeResolver)
		{
			typeConverterFactories = new LazyComponentRegistrationList<Nothing, IYamlTypeConverter> { 
			{
				typeof(YamlDotNet.Serialization.Converters.GuidConverter),
				(Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false)
			} };
			typeInspectorFactories = new LazyComponentRegistrationList<ITypeInspector, ITypeInspector>();
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			settings = new Settings();
		}

		public TBuilder WithNamingConvention(INamingConvention namingConvention)
		{
			this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention");
			return Self;
		}

		public TBuilder WithTypeResolver(ITypeResolver typeResolver)
		{
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			return Self;
		}

		public abstract TBuilder WithTagMapping(TagName tag, Type type);

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter)
		{
			return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action<IRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where)
		{
			if (typeConverter == null)
			{
				throw new ArgumentNullException("typeConverter");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter.GetType(), (Nothing _) => typeConverter));
			return Self;
		}

		public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter
		{
			if (typeConverterFactory == null)
			{
				throw new ArgumentNullException("typeConverterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory(wrapped)));
			return Self;
		}

		public TBuilder WithoutTypeConverter<TYamlTypeConverter>() where TYamlTypeConverter : IYamlTypeConverter
		{
			return WithoutTypeConverter(typeof(TYamlTypeConverter));
		}

		public TBuilder WithoutTypeConverter(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			typeConverterFactories.Remove(converterType);
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory) where TTypeInspector : ITypeInspector
		{
			return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory, Action<IRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			if (typeInspectorFactory == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory(inner)));
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			if (typeInspectorFactory == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory(wrapped, inner)));
			return Self;
		}

		public TBuilder WithoutTypeInspector<TTypeInspector>() where TTypeInspector : ITypeInspector
		{
			return WithoutTypeInspector(typeof(TTypeInspector));
		}

		public TBuilder WithoutTypeInspector(Type inspectorType)
		{
			if (inspectorType == null)
			{
				throw new ArgumentNullException("inspectorType");
			}
			typeInspectorFactories.Remove(inspectorType);
			return Self;
		}

		public TBuilder WithYamlFormatter(YamlFormatter formatter)
		{
			yamlFormatter = formatter ?? throw new ArgumentNullException("formatter");
			return Self;
		}

		protected IEnumerable<IYamlTypeConverter> BuildTypeConverters()
		{
			return typeConverterFactories.BuildComponentList();
		}
	}
	public abstract class StaticContext
	{
		public virtual bool IsKnownType(Type type)
		{
			throw new NotImplementedException();
		}

		public virtual ITypeResolver GetTypeResolver()
		{
			throw new NotImplementedException();
		}

		public virtual StaticObjectFactory GetFactory()
		{
			throw new NotImplementedException();
		}

		public virtual ITypeInspector GetTypeInspector()
		{
			throw new NotImplementedException();
		}
	}
	public sealed class StaticDeserializerBuilder : StaticBuilderSkeleton<StaticDeserializerBuilder>
	{
		private readonly StaticContext context;

		private readonly StaticObjectFactory factory;

		private readonly LazyComponentRegistrationList<Nothing, INodeDeserializer> nodeDeserializerFactories;

		private readonly LazyComponentRegistrationList<Nothing, INodeTypeResolver> nodeTypeResolverFactories;

		private readonly Dictionary<TagName, Type> tagMappings;

		private readonly ITypeConverter typeConverter;

		private readonly Dictionary<Type, Type> typeMappings;

		private bool ignoreUnmatched;

		private bool duplicateKeyChecking;

		private bool attemptUnknownTypeDeserialization;

		protected override StaticDeserializerBuilder Self => this;

		public StaticDeserializerBuilder(StaticContext context)
			: base(context.GetTypeResolver())
		{
			this.context = context;
			factory = context.GetFactory();
			typeMappings = new Dictionary<Type, Type>();
			tagMappings = new Dictionary<TagName, Type>
			{
				{
					FailsafeSchema.Tags.Map,
					typeof(Dictionary<object, object>)
				},
				{
					FailsafeSchema.Tags.Str,
					typeof(string)
				},
				{
					JsonSchema.Tags.Bool,
					typeof(bool)
				},
				{
					JsonSchema.Tags.Float,
					typeof(double)
				},
				{
					JsonSchema.Tags.Int,
					typeof(int)
				},
				{
					DefaultSchema.Tags.Timestamp,
					typeof(DateTime)
				}
			};
			typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner));
			typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner);
			typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner));
			nodeDeserializerFactories = new LazyComponentRegistrationList<Nothing, INodeDeserializer>
			{
				{
					typeof(YamlConvertibleNodeDeserializer),
					(Nothing _) => new YamlConvertibleNodeDeserializer(factory)
				},
				{
					typeof(YamlSerializableNodeDeserializer),
					(Nothing _) => new YamlSerializableNodeDeserializer(factory)
				},
				{
					typeof(TypeConverterNodeDeserializer),
					(Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters())
				},
				{
					typeof(NullNodeDeserializer),
					(Nothing _) => new NullNodeDeserializer()
				},
				{
					typeof(ScalarNodeDeserializer),
					(Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, yamlFormatter)
				},
				{
					typeof(StaticArrayNodeDeserializer),
					(Nothing _) => new StaticArrayNodeDeserializer(factory)
				},
				{
					typeof(StaticDictionaryNodeDeserializer),
					(Nothing _) => new StaticDictionaryNodeDeserializer(factory, duplicateKeyChecking)
				},
				{
					typeof(StaticCollectionNodeDeserializer),
					(Nothing _) => new StaticCollectionNodeDeserializer(factory)
				},
				{
					typeof(ObjectNodeDeserializer),
					(Nothing _) => new ObjectNodeDeserializer(factory, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter)
				}
			};
			nodeTypeResolverFactories = new LazyComponentRegistrationList<Nothing, INodeTypeResolver>
			{
				{
					typeof(MappingNodeTypeResolver),
					(Nothing _) => new MappingNodeTypeResolver(typeMappings)
				},
				{
					typeof(YamlConvertibleTypeResolver),
					(Nothing _) => new YamlConvertibleTypeResolver()
				},
				{
					typeof(YamlSerializableTypeResolver),
					(Nothing _) => new YamlSerializableTypeResolver()
				},
				{
					typeof(TagNodeTypeResolver),
					(Nothing _) => new TagNodeTypeResolver(tagMappings)
				},
				{
					typeof(PreventUnknownTagsNodeTypeResolver),
					(Nothing _) => new PreventUnknownTagsNodeTypeResolver()
				},
				{
					typeof(DefaultContainersNodeTypeResolver),
					(Nothing _) => new DefaultContainersNodeTypeResolver()
				}
			};
			typeConverter = new NullTypeConverter();
		}

		internal ITypeInspector BuildTypeInspector()
		{
			ITypeInspector typeInspector = context.GetTypeInspector();
			return typeInspectorFactories.BuildComponentChain(typeInspector);
		}

		public StaticDeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization()
		{
			attemptUnknownTypeDeserialization = true;
			return this;
		}

		public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer)
		{
			return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> w)
			{
				w.OnTop();
			});
		}

		public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action<IRegistrationLocationSelectionSyntax<INodeDeserializer>> where)
		{
			if (nodeDeserializer == null)
			{
				throw new ArgumentNullException("nodeDeserializer");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer.GetType(), (Nothing _) => nodeDeserializer));
			return this;
		}

		public StaticDeserializerBuilder WithNodeDeserializer<TNodeDeserializer>(WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeDeserializer>> where) where TNodeDeserializer : INodeDeserializer
		{
			if (nodeDeserializerFactory == null)
			{
				throw new ArgumentNullException("nodeDeserializerFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory(wrapped)));
			return this;
		}

		public StaticDeserializerBuilder WithoutNodeDeserializer<TNodeDeserializer>() where TNodeDeserializer : INodeDeserializer
		{
			return WithoutNodeDeserializer(typeof(TNodeDeserializer));
		}

		public StaticDeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType)
		{
			if (nodeDeserializerType == null)
			{
				throw new ArgumentNullException("nodeDeserializerType");
			}
			nodeDeserializerFactories.Remove(nodeDeserializerType);
			return this;
		}

		public StaticDeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action<ITypeDiscriminatingNodeDeserializerOptions> configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1)
		{
			TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions();
			configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions);
			TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength);
			return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> s)
			{
				s.Before<DictionaryNodeDeserializer>();
			});
		}

		public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver)
		{
			return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax<INodeTypeResolver> w)
			{
				w.OnTop();
			});
		}

		public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action<IRegistrationLocationSelectionSyntax<INodeTypeResolver>> where)
		{
			if (nodeTypeResolver == null)
			{
				throw new ArgumentNullException("nodeTypeResolver");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver.GetType(), (Nothing _) => nodeTypeResolver));
			return this;
		}

		public StaticDeserializerBuilder WithNodeTypeResolver<TNodeTypeResolver>(WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) where TNodeTypeResolver : INodeTypeResolver
		{
			if (nodeTypeResolverFactory == null)
			{
				throw new ArgumentNullException("nodeTypeResolverFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory(wrapped)));
			return this;
		}

		public StaticDeserializerBuilder WithoutNodeTypeResolver<TNodeTypeResolver>() where TNodeTypeResolver : INodeTypeResolver
		{
			return WithoutNodeTypeResolver(typeof(TNodeTypeResolver));
		}

		public StaticDeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType)
		{
			if (nodeTypeResolverType == null)
			{
				throw new ArgumentNullException("nodeTypeResolverType");
			}
			nodeTypeResolverFactories.Remove(nodeTypeResolverType);
			return this;
		}

		public override StaticDeserializerBuilder WithTagMapping(TagName tag, Type type)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (tagMappings.TryGetValue(tag, out Type value))
			{
				throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag");
			}
			tagMappings.Add(tag, type);
			return this;
		}

		public StaticDeserializerBuilder WithTypeMapping<TInterface, TConcrete>() where TConcrete : TInterface
		{
			Type typeFromHandle = typeof(TInterface);
			Type typeFromHandle2 = typeof(TConcrete);
			if (!typeFromHandle.IsAssignableFrom(typeFromHandle2))
			{
				throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'.");
			}
			if (typeMappings.ContainsKey(typeFromHandle))
			{
				typeMappings[typeFromHandle] = typeFromHandle2;
			}
			else
			{
				typeMappings.Add(typeFromHandle, typeFromHandle2);
			}
			return this;
		}

		public StaticDeserializerBuilder WithoutTagMapping(TagName tag)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (!tagMappings.Remove(tag))
			{
				throw new KeyNotFoundException($"Tag '{tag}' is not registered");
			}
			return this;
		}

		public StaticDeserializerBuilder IgnoreUnmatchedProperties()
		{
			ignoreUnmatched = true;
			return this;
		}

		public StaticDeserializerBuilder WithDuplicateKeyChecking()
		{
			duplicateKeyChecking = true;
			return this;
		}

		public IDeserializer Build()
		{
			return Deserializer.FromValueDeserializer(BuildValueDeserializer());
		}

		public IValueDeserializer BuildValueDeserializer()
		{
			return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter));
		}
	}
	public sealed class StaticSerializerBuilder : StaticBuilderSkeleton<StaticSerializerBuilder>
	{
		private class ValueSerializer : IValueSerializer
		{
			private readonly IObjectGraphTraversalStrategy traversalStrategy;

			private readonly IEventEmitter eventEmitter;

			private readonly IEnumerable<IYamlTypeConverter> typeConverters;

			private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories;

			private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories;

			public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable<IYamlTypeConverter> typeConverters, LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories)
			{
				this.traversalStrategy = traversalStrategy;
				this.eventEmitter = eventEmitter;
				this.typeConverters = typeConverters;
				this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories;
				this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories;
			}

			public void SerializeValue(IEmitter emitter, object? value, Type? type)
			{
				Type type2 = type ?? ((value != null) ? value.GetType() : typeof(object));
				Type staticType = type ?? typeof(object);
				ObjectDescriptor graph = new ObjectDescriptor(value, type2, staticType);
				List<IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitors = preProcessingPhaseObjectGraphVisitorFactories.BuildComponentList(typeConverters);
				foreach (IObjectGraphVisitor<Nothing> item in preProcessingPhaseObjectGraphVisitors)
				{
					traversalStrategy.Traverse(graph, item, default(Nothing));
				}
				IObjectGraphVisitor<IEmitter> visitor = emissionPhaseObjectGraphVisitorFactories.BuildComponentChain<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>>(new EmittingObjectGraphVisitor(eventEmitter), (IObjectGraphVisitor<IEmitter> inner) => new EmissionPhaseObjectGraphVisitorArgs(inner, eventEmitter, preProcessingPhaseObjectGraphVisitors, typeConverters, NestedObjectSerializer));
				traversalStrategy.Traverse(graph, visitor, emitter);
				void NestedObjectSerializer(object? v, Type? t)
				{
					SerializeValue(emitter, v, t);
				}
			}
		}

		private readonly StaticContext context;

		private readonly StaticObjectFactory factory;

		private ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory;

		private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories;

		private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories;

		private readonly LazyComponentRegistrationList<IEventEmitter, IEventEmitter> eventEmitterFactories;

		private readonly IDictionary<Type, TagName> tagMappings = new Dictionary<Type, TagName>();

		private int maximumRecursion = 50;

		private EmitterSettings emitterSettings = EmitterSettings.Default;

		private DefaultValuesHandling defaultValuesHandlingConfiguration;

		private bool quoteNecessaryStrings;

		private bool quoteYaml1_1Strings;

		private ScalarStyle defaultScalarStyle;

		protected override StaticSerializerBuilder Self => this;

		public StaticSerializerBuilder(StaticContext context)
			: base((ITypeResolver)new DynamicTypeResolver())
		{
			this.context = context;
			factory = context.GetFactory();
			typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner));
			typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner);
			typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner));
			preProcessingPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> { 
			{
				typeof(AnchorAssigner),
				(IEnumerable<IYamlTypeConverter> typeConverters) => new AnchorAssigner(typeConverters)
			} };
			emissionPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>>
			{
				{
					typeof(CustomSerializationObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new CustomSerializationObjectGraphVisitor(args.InnerVisitor, args.TypeConverters, args.NestedObjectSerializer)
				},
				{
					typeof(AnchorAssigningObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new AnchorAssigningObjectGraphVisitor(args.InnerVisitor, args.EventEmitter, args.GetPreProcessingPhaseObjectGraphVisitor<AnchorAssigner>())
				},
				{
					typeof(DefaultValuesObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new DefaultValuesObjectGraphVisitor(defaultValuesHandlingConfiguration, args.InnerVisitor, factory)
				},
				{
					typeof(CommentsObjectGraphVisitor),
					(EmissionPhaseObjectGraphVisitorArgs args) => new CommentsObjectGraphVisitor(args.InnerVisitor)
				}
			};
			eventEmitterFactories = new LazyComponentRegistrationList<IEventEmitter, IEventEmitter> { 
			{
				typeof(TypeAssigningEventEmitter),
				(IEventEmitter inner) => new TypeAssigningEventEmitter(inner, requireTagWhenStaticAndActualTypesAreDifferent: false, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter)
			} };
			objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, namingConvention, factory);
		}

		public StaticSerializerBuilder WithQuotingNecessaryStrings(bool quoteYaml1_1Strings = false)
		{
			quoteNecessaryStrings = true;
			this.quoteYaml1_1Strings = quoteYaml1_1Strings;
			return this;
		}

		public StaticSerializerBuilder WithQuotingNecessaryStrings()
		{
			quoteNecessaryStrings = true;
			return this;
		}

		public StaticSerializerBuilder WithDefaultScalarStyle(ScalarStyle style)
		{
			defaultScalarStyle = style;
			return this;
		}

		public StaticSerializerBuilder WithMaximumRecursion(int maximumRecursion)
		{
			if (maximumRecursion <= 0)
			{
				throw new ArgumentOutOfRangeException("maximumRecursion", $"The maximum recursion specified ({maximumRecursion}) is invalid. It should be a positive integer.");
			}
			this.maximumRecursion = maximumRecursion;
			return this;
		}

		public StaticSerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory) where TEventEmitter : IEventEmitter
		{
			return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> w)
			{
				w.OnTop();
			});
		}

		public StaticSerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory, Action<IRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter
		{
			if (eventEmitterFactory == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory(inner)));
			return Self;
		}

		public StaticSerializerBuilder WithEventEmitter<TEventEmitter>(WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter
		{
			if (eventEmitterFactory == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory(wrapped, inner)));
			return Self;
		}

		public StaticSerializerBuilder WithoutEventEmitter<TEventEmitter>() where TEventEmitter : IEventEmitter
		{
			return WithoutEventEmitter(typeof(TEventEmitter));
		}

		public StaticSerializerBuilder WithoutEventEmitter(Type eventEmitterType)
		{
			if (eventEmitterType == null)
			{
				throw new ArgumentNullException("eventEmitterType");
			}
			eventEmitterFactories.Remove(eventEmitterType);
			return this;
		}

		public override StaticSerializerBuilder WithTagMapping(TagName tag, Type type)
		{
			if (tag.IsEmpty)
			{
				throw new ArgumentException("Non-specific tags cannot be maped");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (tagMappings.TryGetValue(type, out var value))
			{
				throw new ArgumentException($"Type already has a registered tag '{value}' for type '{type.FullName}'", "type");
			}
			tagMappings.Add(type, tag);
			return this;
		}

		public StaticSerializerBuilder WithoutTagMapping(Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (!tagMappings.Remove(type))
			{
				throw new KeyNotFoundException("Tag for type '" + type.FullName + "' is not registered");
			}
			return this;
		}

		public StaticSerializerBuilder EnsureRoundtrip()
		{
			objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new RoundtripObjectGraphTraversalStrategy(typeConverters, typeInspector, typeResolver, maximumRecursion, namingConvention, settings, factory);
			WithEventEmitter((IEventEmitter inner) => new TypeAssigningEventEmitter(inner, requireTagWhenStaticAndActualTypesAreDifferent: true, tagMappings, quoteNecessaryStrings), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc)
			{
				loc.InsteadOf<TypeAssigningEventEmitter>();
			});
			return WithTypeInspector((ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner), delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> loc)
			{
				loc.OnBottom();
			});
		}

		public StaticSerializerBuilder DisableAliases()
		{
			preProcessingPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigner));
			emissionPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigningObjectGraphVisitor));
			return this;
		}

		[Obsolete("The default behavior is now to always emit default values, thefore calling this method has no effect. This behavior is now controlled by ConfigureDefaultValuesHandling.", true)]
		public StaticSerializerBuilder EmitDefaults()
		{
			return ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve);
		}

		public StaticSerializerBuilder ConfigureDefaultValuesHandling(DefaultValuesHandling configuration)
		{
			defaultValuesHandlingConfiguration = configuration;
			return this;
		}

		public StaticSerializerBuilder JsonCompatible()
		{
			emitterSettings = emitterSettings.WithMaxSimpleKeyLength(int.MaxValue).WithoutAnchorName();
			return WithTypeConverter(new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: true), delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w)
			{
				w.InsteadOf<YamlDotNet.Serialization.Converters.GuidConverter>();
			}).WithTypeConverter(new YamlDotNet.Serialization.Converters.DateTimeConverter(DateTimeKind.Utc, null, true)).WithEventEmitter((IEventEmitter inner) => new JsonEventEmitter(inner, yamlFormatter), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc)
			{
				loc.InsteadOf<TypeAssigningEventEmitter>();
			});
		}

		public StaticSerializerBuilder WithNewLine(string newLine)
		{
			emitterSettings = emitterSettings.WithNewLine(newLine);
			return this;
		}

		public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing>
		{
			return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitor, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>> w)
			{
				w.OnTop();
			});
		}

		public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor, A