Decompiled source of RecipeManager v0.3.3

plugins/RecipeManager.dll

Decompiled 2 months 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.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RecipeManager.Common;
using UnityEngine;
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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RecipeManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RecipeManager")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
namespace RecipeManager
{
	internal class RecipeReloadCommand : ConsoleCommand
	{
		public override string Name => "RecipeManager_Reload";

		public override string Help => "Resynchronizes recipes.";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			RecipeUpdater.RecipeRevert();
			string input = File.ReadAllText(Config.recipeConfigFilePath);
			try
			{
				DataObjects.RecipeModificationCollection recipeMods = Config.yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
				RecipeUpdater.UpdateRecipeModifications(recipeMods);
			}
			catch
			{
				Logger.LogWarning((object)("Could not reload the recipe file from disk: " + Config.recipeConfigFilePath));
			}
			RecipeUpdater.BuildRecipesForTracking();
			RecipeUpdater.SecondaryRecipeSync();
		}
	}
	internal class RecipePrintCommand : ConsoleCommand
	{
		public override string Name => "RecipeManager_PrintAllRecipes";

		public override string Help => "Prints all the recipes stored in the Object DB";

		public override void Run(string[] args)
		{
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Starting to dump recipes");
			}
			string text = Path.Combine(Paths.ConfigPath, "RecipeManager", "ObjectDBRecipes.yaml");
			DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
			using StreamWriter streamWriter = new StreamWriter(text);
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Loading recipes from ODB");
			}
			foreach (Recipe item in ObjectDB.instance.m_recipes.ToList())
			{
				if ((Object)(object)item == (Object)null || ((Object)item).name == null)
				{
					continue;
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Building Recipe " + ((Object)item).name));
				}
				DataObjects.RecipeModification recipeModification = new DataObjects.RecipeModification();
				recipeModification.recipeName = ((Object)item).name;
				recipeModification.minStationLevel = (short)item.m_minStationLevel;
				recipeModification.craftAmount = (short)item.m_amount;
				recipeModification.action = DataObjects.Action.Enable;
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)"Checking for empty referenced objects");
				}
				if ((Object)(object)item.m_craftingStation != (Object)null)
				{
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Adding crafting station");
					}
					recipeModification.craftedAt = ((Object)item.m_craftingStation).name;
				}
				if ((Object)(object)item.m_item != (Object)null)
				{
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Adding prefab");
					}
					recipeModification.prefab = ((Object)item.m_item).name;
				}
				DataObjects.SimpleRecipe simpleRecipe = new DataObjects.SimpleRecipe();
				if (item.m_resources != null && item.m_resources.Length != 0)
				{
					simpleRecipe.anyOneResource = item.m_requireOnlyOneIngredient;
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Building resource requirements");
					}
					Requirement[] resources = item.m_resources;
					foreach (Requirement val in resources)
					{
						try
						{
							DataObjects.Ingrediant ingrediant = new DataObjects.Ingrediant();
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogInfo((object)"Setting crafting cost");
							}
							ingrediant.craftCost = (short)val.m_amount;
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogInfo((object)"Setting upgrade cost");
							}
							ingrediant.upgradeCost = (short)val.m_amountPerLevel;
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogInfo((object)"Setting refund bool");
							}
							ingrediant.refund = val.m_recover;
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogInfo((object)"Setting prefab name");
							}
							if ((Object)(object)val.m_resItem != (Object)null)
							{
								ingrediant.prefab = ((Object)val.m_resItem).name;
							}
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogInfo((object)"Adding to ingrediants list");
							}
							simpleRecipe.ingredients.Add(ingrediant);
						}
						catch (Exception arg)
						{
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogWarning((object)$"Requirement did not contain all of the details required to set an ingrediant {val} \n{arg}");
							}
						}
					}
				}
				if (simpleRecipe.ingredients != null && simpleRecipe.ingredients.Count > 0)
				{
					recipeModification.recipe = simpleRecipe;
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Adding " + ((Object)item).name + " to collection."));
				}
				if (recipeModificationCollection.RecipeModifications.ContainsKey(((Object)item).name))
				{
					try
					{
						int num = Random.Range(0, 1000);
						recipeModificationCollection.RecipeModifications.Add(((Object)item).name + $"_{num}", recipeModification);
						Logger.LogWarning((object)$"{((Object)item).name} was already added to the list of recipes and will be renamed {((Object)item).name}_{num}, please use unique recipe names.");
					}
					catch
					{
						Logger.LogWarning((object)(((Object)item).name + " was already added to the list of recipes and will be skipped, please use unique recipe names."));
					}
				}
				else
				{
					recipeModificationCollection.RecipeModifications.Add(((Object)item).name, recipeModification);
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Recipe " + ((Object)item).name + " Added."));
				}
			}
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Serializing and printing recipes.");
			}
			string value = Config.yamlserializer.Serialize(recipeModificationCollection);
			streamWriter.WriteLine(value);
			Logger.LogInfo((object)("Recipes dumped to file " + text));
		}
	}
	[BepInPlugin("MidnightsFX.RecipeManager", "RecipeManager", "0.3.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class RecipeManager : BaseUnityPlugin
	{
		public const string PluginGUID = "MidnightsFX.RecipeManager";

		public const string PluginName = "RecipeManager";

		public const string PluginVersion = "0.3.3";

		public Config cfg;

		private void Awake()
		{
			cfg = new Config(((BaseUnityPlugin)this).Config);
			ItemManager.OnItemsRegistered += RecipeUpdater.InitialRecipesAndSynchronize;
			MinimapManager.OnVanillaMapDataLoaded += RecipeUpdater.SecondaryRecipeSync;
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipeReloadCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipePrintCommand());
		}
	}
	internal class RecipeUpdater
	{
		public static Dictionary<string, DataObjects.RecipeModification> RecipesToModify = new Dictionary<string, DataObjects.RecipeModification>();

		public static List<DataObjects.TrackedRecipe> TrackedRecipes = new List<DataObjects.TrackedRecipe>();

		public static void SecondaryRecipeSync()
		{
			foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
			{
				if (!CheckIfRecipeWasModified(trackedRecipe))
				{
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)("Tracked " + trackedRecipe.prefab + " recipe still has its original recipe in the db. Modifying."));
					}
					ApplyRecipeModifcations(trackedRecipe);
				}
			}
		}

		public static void RecipeRevert()
		{
			foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
			{
				ReverseRecipeModifications(trackedRecipe);
			}
		}

		public static void InitialRecipesAndSynchronize()
		{
			BuildRecipesForTracking();
			RecipeUpdateRunner();
		}

		public static void RecipeUpdateRunner()
		{
			foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
			{
				ApplyRecipeModifcations(trackedRecipe);
			}
		}

		public static void ApplyRecipeModifcations(DataObjects.TrackedRecipe tracked_recipe)
		{
			if (Config.EnableDebugMode.Value)
			{
				if ((Object)(object)tracked_recipe.updatedRecipe != (Object)null)
				{
					string text = "";
					Requirement[] resources = tracked_recipe.updatedRecipe.m_resources;
					foreach (Requirement val in resources)
					{
						text += $" {val.m_resItem},{val.m_amount},{val.m_amountPerLevel}";
					}
					Logger.LogInfo((object)("Applying Updated Recipe: " + ((Object)tracked_recipe.updatedRecipe).name + "\n" + $"amount:{tracked_recipe.updatedRecipe.m_amount}\n" + $"enabled:{tracked_recipe.updatedRecipe.m_enabled}\n" + $"craftingStation:{tracked_recipe.updatedRecipe.m_craftingStation}\n" + $"reqStationLevel:{tracked_recipe.updatedRecipe.m_minStationLevel}\n" + $"reqOneIngrediant:{tracked_recipe.updatedRecipe.m_requireOnlyOneIngredient}\n" + "resources:" + text));
				}
				if ((Object)(object)tracked_recipe.originalRecipe != (Object)null)
				{
					string text2 = "";
					Requirement[] resources2 = tracked_recipe.originalRecipe.m_resources;
					foreach (Requirement val2 in resources2)
					{
						text2 += $" {val2.m_resItem},{val2.m_amount},{val2.m_amountPerLevel}";
					}
					Logger.LogInfo((object)("Targeting Original Recipe: " + ((Object)tracked_recipe.originalRecipe).name + "\n" + $"amount:{tracked_recipe.originalRecipe.m_amount}\n" + $"enabled:{tracked_recipe.originalRecipe.m_enabled}\n" + $"amount:{tracked_recipe.originalRecipe.m_amount}\n" + $"craftingStation:{tracked_recipe.originalRecipe.m_craftingStation}\n" + $"reqStationLevel:{tracked_recipe.originalRecipe.m_minStationLevel}\n" + $"reqOneIngrediant:{tracked_recipe.originalRecipe.m_requireOnlyOneIngredient}\n" + "resources:" + text2));
				}
			}
			bool flag = false;
			if (tracked_recipe.action == DataObjects.Action.Disable)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Disable Action called for " + tracked_recipe.prefab + " recipe"));
				}
				flag = DisableRecipe(tracked_recipe.originalRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Delete)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Delete Action called for " + tracked_recipe.prefab + " recipe"));
				}
				flag = DeleteRecipe(tracked_recipe.originalRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Modify)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Modify Action called for " + tracked_recipe.prefab + " recipe"));
				}
				if (ObjectDB.instance.m_recipes.Contains(tracked_recipe.updatedRecipe))
				{
					DeleteRecipe(tracked_recipe.originalRecipe);
					flag = true;
				}
				else
				{
					flag = ModifyRecipeInODB(tracked_recipe.originalRecipe, tracked_recipe.updatedRecipe);
					ModifyRecipeInJotunnManager(tracked_recipe.originalCustomRecipe, tracked_recipe.updatedCustomRecipe);
				}
			}
			if (tracked_recipe.action == DataObjects.Action.Add)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Add Action called for " + tracked_recipe.prefab + " recipe"));
				}
				flag = AddRecipe(tracked_recipe.updatedRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Enable)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogWarning((object)("Enable Action called for " + tracked_recipe.prefab + " recipe. Are you sure you wanted that? Most recipes are already enabled."));
				}
				flag = EnableRecipe(tracked_recipe.originalRecipe);
			}
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"{tracked_recipe.prefab} recipe update applied? {flag}");
			}
		}

		public static void ReverseRecipeModifications(DataObjects.TrackedRecipe tracked_recipe)
		{
			bool flag = false;
			if (tracked_recipe.action == DataObjects.Action.Disable)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Reverting disable for " + tracked_recipe.prefab + " recipe"));
				}
				flag = EnableRecipe(tracked_recipe.originalRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Delete)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Reverting delete for " + tracked_recipe.prefab + " recipe"));
				}
				flag = AddRecipe(tracked_recipe.originalRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Modify)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Reversing modify for " + tracked_recipe.prefab + " recipe"));
				}
				flag = ModifyRecipeInODB(tracked_recipe.updatedRecipe, tracked_recipe.originalRecipe);
				ModifyRecipeInJotunnManager(tracked_recipe.updatedCustomRecipe, tracked_recipe.originalCustomRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Add)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Reverting add for " + tracked_recipe.prefab + " recipe"));
				}
				flag = DeleteRecipe(tracked_recipe.updatedRecipe);
			}
			if (tracked_recipe.action == DataObjects.Action.Enable)
			{
				flag = DisableRecipe(tracked_recipe.originalRecipe);
			}
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"{tracked_recipe.prefab} recipe modification reverted? {flag}");
			}
		}

		public static bool CheckIfRecipeWasModified(DataObjects.TrackedRecipe trackedRecipe)
		{
			if (trackedRecipe.action == DataObjects.Action.Modify || trackedRecipe.action == DataObjects.Action.Delete || trackedRecipe.action == DataObjects.Action.Disable)
			{
				int num = ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.originalRecipe);
				if (num > 0)
				{
					return false;
				}
			}
			if (trackedRecipe.action == DataObjects.Action.Add)
			{
				int num2 = ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.updatedRecipe);
				if (num2 > 0)
				{
					return true;
				}
				return false;
			}
			return false;
		}

		public static void BuildRecipesForTracking()
		{
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			TrackedRecipes.Clear();
			foreach (KeyValuePair<string, DataObjects.RecipeModification> item2 in RecipesToModify)
			{
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Constructing modification details for " + item2.Key));
				}
				DataObjects.TrackedRecipe trackedRecipe = new DataObjects.TrackedRecipe();
				trackedRecipe.action = item2.Value.action;
				trackedRecipe.prefab = item2.Value.prefab;
				int num = -1;
				if (item2.Value.recipeName != null)
				{
					num = RecipeIndexForRecipeName(item2.Value.recipeName);
					trackedRecipe.recipeName = item2.Value.recipeName;
				}
				if (num == -1)
				{
					num = RecipeIndexForPrefab(item2.Value.prefab);
				}
				if (num > -1)
				{
					trackedRecipe.originalRecipe = ObjectDB.instance.m_recipes[num];
				}
				else if (Config.EnableDebugMode.Value)
				{
					Logger.LogWarning((object)("Could not find recipe for: " + item2.Value.prefab));
				}
				if (item2.Value.recipe != null)
				{
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Found custom recipe modifications, building out definition.");
					}
					RequirementConfig[] array = (RequirementConfig[])(object)new RequirementConfig[item2.Value.recipe.ingredients.Count];
					int num2 = 0;
					foreach (DataObjects.Ingrediant ingredient in item2.Value.recipe.ingredients)
					{
						array[num2] = new RequirementConfig
						{
							Item = ingredient.prefab,
							Amount = ingredient.craftCost,
							AmountPerLevel = ingredient.upgradeCost,
							Recover = ingredient.refund
						};
						num2++;
					}
					CustomRecipe val2 = new CustomRecipe(new RecipeConfig
					{
						Name = ((trackedRecipe.recipeName != null) ? trackedRecipe.recipeName : ("Recipe_" + item2.Value.prefab)),
						Amount = item2.Value.craftAmount,
						CraftingStation = item2.Value.craftedAt,
						MinStationLevel = item2.Value.minStationLevel,
						Enabled = ((item2.Value.action != 0) ? true : false),
						Requirements = array
					});
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Built new custom recipe.");
					}
					Recipe recipe = val2.Recipe;
					CustomItem item = ItemManager.Instance.GetItem(item2.Value.prefab);
					if (item != null)
					{
						if (Config.EnableDebugMode.Value)
						{
							Logger.LogInfo((object)"Found existing custom item, storing for comparision.");
						}
						trackedRecipe.originalCustomRecipe = item.Recipe;
					}
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Resolving references on custom recipe.");
					}
					if (item2.Value.craftedAt != null)
					{
						try
						{
							GameObject prefab = PrefabManager.Instance.GetPrefab(item2.Value.craftedAt);
							recipe.m_craftingStation = (recipe.m_repairStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null));
						}
						catch
						{
							Logger.LogWarning((object)("Crafting station (" + item2.Value.craftedAt + ") could not be resolved or did not have a craftingStation component"));
						}
					}
					try
					{
						GameObject prefab2 = PrefabManager.Instance.GetPrefab(item2.Value.prefab);
						ItemDrop component = prefab2.GetComponent<ItemDrop>();
						if (!((Object)(object)component != (Object)null))
						{
							Logger.LogWarning((object)$"Could not find a prefab ({item2.Value.prefab}) GO ({prefab2}) with an ItemDrop ({component}) component to reference. This recipe will not have a target and will be skipped.");
							continue;
						}
						recipe.m_item = component;
					}
					catch
					{
						Logger.LogWarning((object)("Could not find a prefab (" + item2.Value.prefab + ") with an ItemDrop component to reference. This recipe will not have a target and will be skipped."));
						continue;
					}
					((Object)recipe).name = "Recipe_" + item2.Key;
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Resolving resource requirement references.");
					}
					Requirement[] resources = recipe.m_resources;
					foreach (Requirement val3 in resources)
					{
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val3.m_resItem).name.Replace("JVLmock_", ""));
						if ((Object)(object)itemPrefab != (Object)null)
						{
							val3.m_resItem = itemPrefab.GetComponent<ItemDrop>();
						}
						else
						{
							Logger.LogWarning((object)("Could not resolve itemdrop reference for: " + ((Object)val3.m_resItem).name + ". This requirement will be deleted."));
						}
					}
					recipe.m_resources.Where((Requirement val) => ((object)val.m_resItem).GetType() == typeof(ItemDrop)).ToArray();
					trackedRecipe.updatedRecipe = recipe;
					trackedRecipe.updatedCustomRecipe = val2;
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Set updated recipe and updatedCustomRecipe.");
					}
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)"Adding tracked Recipe");
				}
				TrackedRecipes.Add(trackedRecipe);
			}
		}

		public static int RecipeIndexForPrefab(string prefab)
		{
			return ObjectDB.instance.m_recipes.FindIndex((Recipe m) => (Object)(object)m.m_item != (Object)null && ((Object)m.m_item).name == prefab);
		}

		public static int RecipeIndexForRecipeName(string recipe_name)
		{
			return ObjectDB.instance.m_recipes.FindIndex((Recipe m) => ((Object)m).name != null && ((Object)m).name == recipe_name);
		}

		public static bool ModifyRecipeInJotunnManager(CustomRecipe recipe, CustomRecipe newRecipe)
		{
			if (AccessTools.Field(typeof(ItemManager), "Recipes").GetValue(ItemManager.Instance) is HashSet<CustomRecipe> hashSet)
			{
				hashSet.Remove(recipe);
				hashSet.Add(newRecipe);
				return true;
			}
			return false;
		}

		public static bool ModifyRecipeInODB(Recipe recipe, Recipe newRecipe)
		{
			int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
			if (num > -1)
			{
				ObjectDB.instance.m_recipes[num] = newRecipe;
				return true;
			}
			return false;
		}

		public static bool DisableRecipe(Recipe recipe)
		{
			int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
			if (num > -1)
			{
				ObjectDB.instance.m_recipes[num].m_enabled = false;
				return true;
			}
			return false;
		}

		public static bool EnableRecipe(Recipe recipe)
		{
			int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
			if (num > -1)
			{
				ObjectDB.instance.m_recipes[num].m_enabled = true;
				return true;
			}
			return false;
		}

		public static bool DeleteRecipe(Recipe recipe)
		{
			return ObjectDB.instance.m_recipes.Remove(recipe);
		}

		public static bool AddRecipe(Recipe recipe)
		{
			if (!ObjectDB.instance.m_recipes.Contains(recipe))
			{
				ObjectDB.instance.m_recipes.Add(recipe);
			}
			return true;
		}

		public static void UpdateRecipeModifications(DataObjects.RecipeModificationCollection recipeMods)
		{
			RecipesToModify.Clear();
			foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in recipeMods.RecipeModifications)
			{
				RecipesToModify.Add(recipeModification.Key, recipeModification.Value);
			}
		}
	}
}
namespace RecipeManager.Common
{
	internal class Config
	{
		public static ConfigFile cfg;

		public static ConfigEntry<bool> EnableDebugMode;

		public static string recipeConfigFilePath = Path.Combine(Paths.ConfigPath, "RecipeManager", "Recipes.yaml");

		public static IDeserializer yamldeserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();

		public static ISerializer yamlserializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).DisableAliases().Build();

		private static CustomRPC RecipeConfigRPC;

		public Config(ConfigFile cfgref)
		{
			cfg = cfgref;
			cfg.SaveOnConfigSet = true;
			CreateConfigValues(cfgref);
			string configPath = Paths.ConfigPath;
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
			fileSystemWatcher.Path = configPath;
			fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
			fileSystemWatcher.Filter = "MidnightsFX.RecipeManager.cfg";
			fileSystemWatcher.Changed += UpdateMainConfigFile;
			fileSystemWatcher.Created += UpdateMainConfigFile;
			fileSystemWatcher.Renamed += UpdateMainConfigFile;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			Logger.LogInfo((object)"Config filewatcher initialized.");
			SetupSecondaryConfigFile();
			SetupConfigRPCs();
		}

		private void CreateConfigValues(ConfigFile Config)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging for Recipe Manager. This is client side and is not syncd with the server.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = false,
				IsAdvanced = true
			} }));
		}

		private static void UpdateMainConfigFile(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(Paths.ConfigPath))
			{
				return;
			}
			try
			{
				cfg.SaveOnConfigSet = false;
				cfg.Reload();
				cfg.SaveOnConfigSet = true;
			}
			catch
			{
				Logger.LogError((object)"There was an issue reloading MidnightsFX.RecipeManager.cfg.");
			}
		}

		private static void SetupSecondaryConfigFile()
		{
			string secondaryConfigDirectoryPath = GetSecondaryConfigDirectoryPath();
			bool flag = false;
			string[] files = Directory.GetFiles(secondaryConfigDirectoryPath);
			string[] array = files;
			foreach (string text in array)
			{
				if (text.Contains("Recipes.yaml"))
				{
					if (EnableDebugMode.Value)
					{
						Logger.LogInfo((object)("Found recipe configuration yaml: " + text));
					}
					recipeConfigFilePath = text;
					flag = true;
				}
			}
			if (!flag)
			{
				Logger.LogInfo((object)"Recipe file missing, recreating.");
				using StreamWriter streamWriter = new StreamWriter(recipeConfigFilePath);
				string value = "#################################################\r\n# Recipe Manipulation Config\r\n#################################################\r\n# recipeModifications:                     # <- This is the top level key, all modifications live under this, it is required.\r\n#   DisableWoodArrow:                      # <- This is the modification name, its primarily for you to understand what this modification does SHOULD BE UNIQUE\r\n#     action: Disable                      # <- This is the action it should be one of [Disable, Delete, Modify, Add, Enable]\r\n#     prefab: ArrowWood                    # <- This is the prefab that the modification will target\r\n#   AddNewWoodArrowRecipe:\r\n#     action: Add\r\n#     prefab: ArrowWood\r\n#     recipeName: Recipe_ArrowWood         # <- optional, specifying the recipe name allows multiple mutating multiple recipes targeting the same prefab\r\n#     craftedAt: Workbench                 # <- The crafting station that should craft this recipe, leave it empty or invalid for handcrafting\r\n#     minStationLevel: 2                   # <- This is the required crafting station level for discovery AND crafting\r\n#     recipe:                              # <- When performing [Modify] or [Add] you should define a recipe\r\n#       anyOneResource: false              # <- This makes the recipe only require one ingrediant, first from the top will be used.\r\n#       ingredients:                       # <- Ingrediants in the recipe, is an array\r\n#         - prefab: Wood                   # <- Prefab that this ingrediant requires\r\n#           craftCost: 2                   # <- The amount of this ingrediant it takes to craft the recipe  \r\n#           upgradeCost: 0                 # <- The amount of this ingrediant it takes to upgrade the item \r\n#           refund: false                  # <- Whether or not this recipe refunds  \r\n#         - prefab: Feathers\r\n#           craftCost: 2\r\n#           upgradeCost: 0\r\n#           refund: true\r\n#   DeleteTrollHideArmorRecipe:\r\n#     action: Delete\r\n#     prefab: CapeTrollHide\r\n#   ModifyTrollHideChestRecipe:\r\n#     action: Modify\r\n#     prefab: ArmorTrollLeatherChest\r\n#     craftedAt: Workbench\r\n#     minStationLevel: 1\r\n#     recipe:\r\n#       anyOneResource: false\r\n#       ingredients:\r\n#         - prefab: TrollHide\r\n#           craftCost: 4\r\n#           upgradeCost: 2\r\n#           refund: false\r\n";
				streamWriter.WriteLine(value);
				streamWriter.WriteLine(YamlRecipeConfigDefinition());
			}
			string input = File.ReadAllText(recipeConfigFilePath);
			try
			{
				DataObjects.RecipeModificationCollection recipeMods = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
				RecipeUpdater.UpdateRecipeModifications(recipeMods);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"There was an error updating the RecipeConfig values, defaults will be used. Exception: {arg}");
			}
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
			fileSystemWatcher.Path = secondaryConfigDirectoryPath;
			fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
			fileSystemWatcher.Filter = "WildShrines.yaml";
			fileSystemWatcher.Changed += UpdateRecipeConfigFileOnChange;
			fileSystemWatcher.Created += UpdateRecipeConfigFileOnChange;
			fileSystemWatcher.Renamed += UpdateRecipeConfigFileOnChange;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private static void UpdateRecipeConfigFileOnChange(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(recipeConfigFilePath))
			{
				return;
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"{e} Recipe filewatcher called, updating recipe Modification values.");
			}
			string input = File.ReadAllText(recipeConfigFilePath);
			DataObjects.RecipeModificationCollection recipeMods;
			try
			{
				recipeMods = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"RecipeModifications failed deserializing, skipping update: {arg}");
				return;
			}
			RecipeUpdater.RecipeRevert();
			RecipeUpdater.UpdateRecipeModifications(recipeMods);
			RecipeUpdater.BuildRecipesForTracking();
			RecipeUpdater.SecondaryRecipeSync();
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Updated RecipeModifications in-memory values.");
			}
			if (GUIManager.IsHeadless())
			{
				try
				{
					RecipeConfigRPC.SendPackage(ZNet.instance.m_peers, SendRecipeConfigs());
					if (EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Sent levels configs to clients.");
					}
					return;
				}
				catch (Exception arg2)
				{
					Logger.LogError((object)$"Error while server syncing recipeModification configs: {arg2}");
					return;
				}
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogDebug((object)"Instance is not a server, and will not send znet recipeModification updates.");
			}
		}

		public static string GetSecondaryConfigDirectoryPath()
		{
			string path = Path.Combine(Paths.ConfigPath, "RecipeManager");
			DirectoryInfo directoryInfo = Directory.CreateDirectory(path);
			return directoryInfo.FullName;
		}

		public void SetupConfigRPCs()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0028: Expected O, but got Unknown
			RecipeConfigRPC = NetworkManager.Instance.AddRPC("recipeManager_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveYamlConfigs));
			SynchronizationManager.Instance.AddInitialSynchronization(RecipeConfigRPC, (Func<ZPackage>)SendRecipeConfigs);
		}

		public static IEnumerator OnServerRecieveConfigs(long sender, ZPackage package)
		{
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Server recieved config from client, rejecting due to being the server.");
			}
			yield return null;
		}

		private static ZPackage SendRecipeConfigs()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			string text = File.ReadAllText(recipeConfigFilePath);
			ZPackage val = new ZPackage();
			val.Write(text);
			return val;
		}

		private static IEnumerator OnClientReceiveYamlConfigs(long sender, ZPackage package)
		{
			string yaml = package.ReadString();
			RecipeUpdater.RecipeRevert();
			try
			{
				DataObjects.RecipeModificationCollection recipeFileData = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(yaml);
				RecipeUpdater.UpdateRecipeModifications(recipeFileData);
			}
			catch
			{
				Logger.LogWarning((object)("Could not reload the recipe file from disk: " + recipeConfigFilePath));
			}
			RecipeUpdater.BuildRecipesForTracking();
			RecipeUpdater.SecondaryRecipeSync();
			yield return null;
		}

		public static string YamlRecipeConfigDefinition()
		{
			DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
			recipeModificationCollection.RecipeModifications = RecipeUpdater.RecipesToModify;
			return yamlserializer.Serialize(recipeModificationCollection);
		}

		public ConfigEntry<bool> BindServerConfig(string catagory, string key, bool value, string description, bool advanced = false)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			return cfg.Bind<bool>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public ConfigEntry<string> BindServerConfig(string catagory, string key, string value, string description, bool advanced = false)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			return cfg.Bind<string>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public ConfigEntry<short> BindServerConfig(string catagory, string key, short value, string description, bool advanced = false, short valmin = 0, short valmax = 150)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			return cfg.Bind<short>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<short>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public ConfigEntry<float> BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			return cfg.Bind<float>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}
	}
	internal class DataObjects
	{
		public enum Action
		{
			Disable,
			Delete,
			Modify,
			Add,
			Enable
		}

		public class TrackedRecipe
		{
			public Action action { get; set; }

			public string prefab { get; set; }

			public string recipeName { get; set; }

			public Recipe originalRecipe { get; set; }

			public Recipe updatedRecipe { get; set; }

			public CustomRecipe updatedCustomRecipe { get; set; }

			public CustomRecipe originalCustomRecipe { get; set; }
		}

		[DataContract]
		public class RecipeModificationCollection
		{
			public Dictionary<string, RecipeModification> RecipeModifications { get; set; } = new Dictionary<string, RecipeModification>();

		}

		[DataContract]
		public class RecipeModification
		{
			public Action action { get; set; }

			public string prefab { get; set; }

			public string recipeName { get; set; }

			public string craftedAt { get; set; }

			public short minStationLevel { get; set; } = 1;


			public short craftAmount { get; set; } = 1;


			public SimpleRecipe recipe { get; set; }
		}

		[DataContract]
		public class SimpleRecipe
		{
			public bool anyOneResource { get; set; } = false;


			public List<Ingrediant> ingredients { get; set; } = new List<Ingrediant>();

		}

		[DataContract]
		public class Ingrediant
		{
			public string prefab { get; set; }

			public short craftCost { get; set; }

			public short upgradeCost { get; set; }

			public bool refund { get; set; } = false;

		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace 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 PropertyInfoExtensions
	{
		public static object? ReadValue(this PropertyInfo property, object target)
		{
			return property.GetValue(target, null);
		}
	}
	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)
		{
			BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
			if (allowPrivateConstructors)
			{
				bindingFlags |= BindingFlags.NonPublic;
			}
			if (!type.IsValueType)
			{
				return type.GetConstructor(bindingFlags, null, Type.EmptyTypes, null) != null;
			}
			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)
		{
			string name2 = name;
			return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => !m.IsPublic && m.IsStatic && m.Name.Equals(name2)) ?? throw new MissingMethodException("Expected to find a method named '" + name2 + "' in '" + type.FullName + "'.");
		}

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

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

		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 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 StandardRegexOptions
	{
		public const RegexOptions Compiled = RegexOptions.Compiled;
	}
}
namespace YamlDotNet.Serialization
{
	internal abstract class BuilderSkeleton<TBuilder> where TBuilder : BuilderSkeleton<TBuilder>
	{
		internal INamingConvention namingConvention = NullNamingConvention.Instance;

		internal INamingConvention enumNamingConvention = 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 WithEnumNamingConvention(INamingConvention enumNamingConvention)
		{
			this.enumNamingConvention = enumNamingConvention;
			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)
		{
			IYamlTypeConverter typeConverter2 = typeConverter;
			if (typeConverter2 == null)
			{
				throw new ArgumentNullException("typeConverter");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2));
			return Self;
		}

		public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter
		{
			WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory2 = typeConverterFactory;
			if (typeConverterFactory2 == null)
			{
				throw new ArgumentNullException("typeConverterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(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
		{
			Func<ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory;
			if (typeInspectorFactory2 == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner)));
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory;
			if (typeInspectorFactory2 == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(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();
		}
	}
	internal delegate TComponent WrapperFactory<TComponentBase, TComponent>(TComponentBase wrapped) where TComponent : TComponentBase;
	internal delegate TComponent WrapperFactory<TArgument, TComponentBase, TComponent>(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase;
	[Flags]
	internal enum DefaultValuesHandling
	{
		Preserve = 0,
		OmitNull = 1,
		OmitDefaults = 2,
		OmitEmptyCollections = 4
	}
	internal 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;
		}
	}
	internal 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, enumNamingConvention)
				},
				{
					typeof(ArrayNodeDeserializer),
					(Nothing _) => new ArrayNodeDeserializer(enumNamingConvention)
				},
				{
					typeof(DictionaryNodeDeserializer),
					(Nothing _) => new DictionaryNodeDeserializer(objectFactory.Value, duplicateKeyChecking)
				},
				{
					typeof(CollectionNodeDeserializer),
					(Nothing _) => new CollectionNodeDeserializer(objectFactory.Value, enumNamingConvention)
				},
				{
					typeof(EnumerableNodeDeserializer),
					(Nothing _) => new EnumerableNodeDeserializer()
				},
				{
					typeof(ObjectNodeDeserializer),
					(Nothing _) => new ObjectNodeDeserializer(objectFactory.Value, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention)
				}
			};
			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)
		{
			IObjectFactory objectFactory2 = objectFactory;
			if (objectFactory2 == null)
			{
				throw new ArgumentNullException("objectFactory");
			}
			this.objectFactory = new Lazy<IObjectFactory>(() => objectFactory2, 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)
		{
			INodeDeserializer nodeDeserializer2 = nodeDeserializer;
			if (nodeDeserializer2 == null)
			{
				throw new ArgumentNullException("nodeDeserializer");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer2.GetType(), (Nothing _) => nodeDeserializer2));
			return this;
		}

		public DeserializerBuilder WithNodeDeserializer<TNodeDeserializer>(WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeDeserializer>> where) where TNodeDeserializer : INodeDeserializer
		{
			WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory2 = nodeDeserializerFactory;
			if (nodeDeserializerFactory2 == null)
			{
				throw new ArgumentNullException("nodeDeserializerFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory2(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)
		{
			INodeTypeResolver nodeTypeResolver2 = nodeTypeResolver;
			if (nodeTypeResolver2 == null)
			{
				throw new ArgumentNullException("nodeTypeResolver");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver2.GetType(), (Nothing _) => nodeTypeResolver2));
			return this;
		}

		public DeserializerBuilder WithNodeTypeResolver<TNodeTypeResolver>(WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) where TNodeTypeResolver : INodeTypeResolver
		{
			WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory2 = nodeTypeResolverFactory;
			if (nodeTypeResolverFactory2 == null)
			{
				throw new ArgumentNullException("nodeTypeResolverFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory2(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, enumNamingConvention));
		}
	}
	internal 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();
		}
	}
	internal abstract class EventInfo
	{
		public IObjectDescriptor Source { get; }

		protected EventInfo(IObjectDescriptor source)
		{
			Source = source ?? throw new ArgumentNullException("source");
		}
	}
	internal 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;
		}
	}
	internal class ObjectEventInfo : EventInfo
	{
		public AnchorName Anchor { get; set; }

		public TagName Tag { get; set; }

		protected ObjectEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	internal 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;
		}
	}
	internal sealed class MappingStartEventInfo : ObjectEventInfo
	{
		public bool IsImplicit { get; set; }

		public MappingStyle Style { get; set; }

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

		public SequenceStyle Style { get; set; }

		public SequenceStartEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	internal sealed class SequenceEndEventInfo : EventInfo
	{
		public SequenceEndEventInfo(IObjectDescriptor source)
			: base(source)
		{
		}
	}
	internal interface IAliasProvider
	{
		AnchorName GetAlias(object target);
	}
	internal 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);
	}
	internal 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);
	}
	internal interface INamingConvention
	{
		string Apply(string value);

		string Reverse(string value);
	}
	internal interface INodeDeserializer
	{
		bool Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value);
	}
	internal interface INodeTypeResolver
	{
		bool Resolve(NodeEvent? nodeEvent, ref Type currentType);
	}
	internal interface IObjectAccessor
	{
		void Set(string name, object target, object value);

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

		Type Type { get; }

		Type StaticType { get; }

		ScalarStyle ScalarStyle { get; }
	}
	internal 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.");
		}
	}
	internal 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);
	}
	internal interface IObjectGraphTraversalStrategy
	{
		void Traverse<TContext>(IObjectDescriptor graph, IObjectGraphVisitor<TContext> visitor, TContext context);
	}
	internal 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);
	}
	internal 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);
	}
	internal 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();
	}
	internal interface ITrackingRegistrationLocationSelectionSyntax<TBaseRegistrationType>
	{
		void InsteadOf<TRegistrationType>() where TRegistrationType : TBaseRegistrationType;
	}
	internal 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);
	}
	internal interface ITypeInspector
	{
		IEnumerable<IPropertyDescriptor> GetProperties(Type type, object? container);

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

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

		void WriteYaml(IEmitter emitter);
	}
	internal 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)
		{
			Func<TComponent, TArgument> argumentBuilder2 = argumentBuilder;
			return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func<TArgument, TComponent> factory) => factory(argumentBuilder2(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)
		{
			TArgument argument2 = argument;
			return registrations.Select((Func<TArgument, TComponent> factory) => factory(argument2)).ToList();
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	internal struct Nothing
	{
	}
	internal 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;
		}
	}
	internal delegate IObjectGraphTraversalStrategy ObjectGraphTraversalStrategyFactory(ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion);
	internal 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);
		}
	}
	internal 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());
		}
	}
	internal 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)
			{
				IEmitter emitter2 = emitter;
				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, emitter2);
				void NestedObjectSerializer(object? v, Type? t)
				{
					SerializeValue(emitter2, 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, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention)
			} };
			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
		{
			Func<IEventEmitter, TEventEmitter> eventEmitterFactory2 = eventEmitterFactory;
			if (eventEmitterFactory2 == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory2(inner)));
			return Self;
		}

		public SerializerBuilder WithEventEmitter<TEventEmitter>(WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter
		{
			WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory2 = eventEmitterFactory;
			if (eventEmitterFactory2 == null)
			{
				throw new ArgumentNullException("eventEmitterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory2(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;
		}