Decompiled source of RecipeManager v0.4.1

plugins/RecipeManager.dll

Decompiled 2 weeks 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.IgnoreSymbolStoreSequencePoints)]
[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 PieceReloadCommand : ConsoleCommand
	{
		public override string Name => "RM_Pieces_Reload";

		public override string Help => "Resynchronizes piece modifications.";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			PieceUpdater.RevertPieceModifications();
			Config.ReloadPieceFiles();
			PieceUpdater.BuildPieceTracker();
			PieceUpdater.PieceUpdateRunner();
		}
	}
	internal class PiecePrintCommand : ConsoleCommand
	{
		public override string Name => "RM_Pieces_PrintAll";

		public override string Help => "Prints all the Pieces found.";

		public override void Run(string[] args)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Starting to dump piece list");
			}
			string text = Path.Combine(Paths.ConfigPath, "RecipeManager", "AllPiecesDebug.yaml");
			DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
			using StreamWriter streamWriter = new StreamWriter(text);
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Gathering Pieces");
			}
			foreach (Piece item in (from pc in Resources.FindObjectsOfTypeAll<Piece>()
				where !((Object)pc).name.EndsWith("(Clone)") && !Regex.IsMatch(((Object)pc).name.Trim(), "\\(\\d+\\)")
				select pc).ToList())
			{
				if ((Object)(object)item == (Object)null || ((Object)item).name == null)
				{
					continue;
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Building Recipe " + item.m_name));
				}
				DataObjects.PieceModification pieceModification = new DataObjects.PieceModification();
				pieceModification.action = DataObjects.PieceAction.Enable;
				pieceModification.EnablePiece = ((Behaviour)item).enabled;
				pieceModification.CanBeDeconstructed = item.m_canBeRemoved;
				pieceModification.CultivatedGroundOnly = item.m_cultivatedGroundOnly;
				pieceModification.ComfortGroup = item.m_comfortGroup;
				pieceModification.ComfortAmount = item.m_comfort;
				pieceModification.GroundPlacement = item.m_groundPiece;
				pieceModification.SpaceRequired = item.m_spaceRequirement;
				pieceModification.AllowedInDungeon = item.m_allowedInDungeons;
				pieceModification.CraftingStationConnectionRadius = item.m_connectRadius;
				pieceModification.MustBeAvobeConnectedStation = item.m_mustBeAboveConnected;
				pieceModification.OnlyInSelectBiome = item.m_onlyInBiome;
				pieceModification.PieceCategory = item.m_category;
				pieceModification.PieceDescription = item.m_description;
				pieceModification.PieceName = item.m_name;
				pieceModification.prefab = ((Object)((Component)item).gameObject).name;
				if ((Object)(object)item.m_craftingStation != (Object)null)
				{
					pieceModification.RequiredToPlaceCraftingStation = ((Object)item.m_craftingStation).name;
				}
				pieceModification.IsUpgradeForStation = item.m_isUpgrade;
				List<DataObjects.SimpleRequirement> list = new List<DataObjects.SimpleRequirement>();
				if (item.m_resources != null && item.m_resources.Length != 0)
				{
					Requirement[] resources = item.m_resources;
					foreach (Requirement val in resources)
					{
						try
						{
							list.Add(new DataObjects.SimpleRequirement
							{
								amount = val.m_amount,
								Prefab = ((Object)val.m_resItem).name
							});
						}
						catch (Exception arg)
						{
							if (Config.EnableDebugMode.Value)
							{
								Logger.LogWarning((object)$"Piece requirement setup error {val} \n{arg}");
							}
						}
					}
				}
				pieceModification.requirements = list;
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Adding " + pieceModification.prefab + " to collection."));
				}
				if (!pieceModificationCollection.PieceModifications.ContainsKey(pieceModification.prefab))
				{
					pieceModificationCollection.PieceModifications.Add(pieceModification.prefab, pieceModification);
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Piece " + pieceModification.prefab + " Added."));
				}
			}
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Serializing and printing recipes.");
			}
			string value = Config.yamlserializer.Serialize(pieceModificationCollection);
			streamWriter.WriteLine(value);
			Logger.LogInfo((object)("Recipes dumped to file " + text));
		}
	}
	internal class PieceUpdater
	{
		public static Dictionary<string, DataObjects.PieceModification> PiecesToModify = new Dictionary<string, DataObjects.PieceModification>();

		public static List<DataObjects.TrackedPiece> TrackedPieces = new List<DataObjects.TrackedPiece>();

		public static void InitialSychronization()
		{
			BuildPieceTracker();
			PieceUpdateRunner();
		}

		public static void PieceUpdateRunner()
		{
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"Applying {TrackedPieces.Count} piece modifications");
			}
			foreach (DataObjects.TrackedPiece trackedPiece in TrackedPieces)
			{
				ApplyPieceModifications(trackedPiece);
			}
		}

		public static void ApplyPieceModifications(DataObjects.TrackedPiece piece)
		{
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"Applying piece ({piece.prefab}) modification action: {piece.action}");
			}
			switch (piece.action)
			{
			case DataObjects.PieceAction.Disable:
				DisablePiece(piece);
				break;
			case DataObjects.PieceAction.Modify:
				ModifyPiece(piece);
				break;
			case DataObjects.PieceAction.Enable:
				EnablePiece(piece);
				break;
			}
		}

		public static void RevertPieceModifications()
		{
			foreach (DataObjects.TrackedPiece trackedPiece in TrackedPieces)
			{
				RevertPiece(trackedPiece);
			}
		}

		public static void EnablePiece(DataObjects.TrackedPiece piece)
		{
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)("Enabling " + piece.prefab));
			}
			PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>().m_enabled = true;
		}

		private static void RevertPiece(DataObjects.TrackedPiece tpiece)
		{
			PrefabManager.Instance.GetPrefab(tpiece.prefab).GetComponent<Piece>();
			_ = tpiece.originalPiece;
		}

		private static void ModifyPiece(DataObjects.TrackedPiece piece)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)("Modifying " + piece.prefab));
			}
			Piece component = PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				if (piece.updatedRequirements != null)
				{
					component.m_resources = piece.updatedRequirements;
				}
				component.m_craftingStation = piece.RequiredToPlaceCraftingStation;
				component.m_allowedInDungeons = piece.AllowedInDungeon;
				component.m_canBeRemoved = piece.CanBeDeconstructed;
				if ((int)piece.PieceCategory != 100)
				{
					component.m_category = piece.PieceCategory;
				}
				if (piece.ComfortAmount != -1)
				{
					component.m_comfort = piece.ComfortAmount;
				}
				if ((int)piece.ComfortGroup != 0)
				{
					component.m_comfortGroup = piece.ComfortGroup;
				}
				if (piece.CraftingStationConnectionRadius != -1f)
				{
					component.m_connectRadius = piece.CraftingStationConnectionRadius;
				}
				if (piece.PieceDescription != null)
				{
					component.m_description = piece.PieceDescription;
				}
				component.m_enabled = piece.EnablePiece;
				if (piece.PieceName != null)
				{
					component.m_name = piece.PieceName;
				}
				component.m_onlyInBiome = piece.OnlyInBiome;
				component.m_isUpgrade = piece.IsUpgradeForStation;
				component.m_cultivatedGroundOnly = piece.CultivatedGroundOnly;
				component.m_mustBeAboveConnected = piece.MustBeAvobeConnectedStation;
				if (piece.SpaceRequired != -1f)
				{
					component.m_spaceRequirement = piece.SpaceRequired;
				}
				component.m_groundPiece = piece.GroundPlacement;
			}
		}

		private static void DisablePiece(DataObjects.TrackedPiece piece)
		{
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)("Modifying " + piece.prefab));
			}
			PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>().m_enabled = false;
		}

		public static void BuildPieceTracker()
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			TrackedPieces.Clear();
			foreach (KeyValuePair<string, DataObjects.PieceModification> item in PiecesToModify)
			{
				if (item.Key == null)
				{
					continue;
				}
				if (Config.EnableDebugMode.Value)
				{
					Logger.LogInfo((object)("Constructing piece modification for " + item.Key));
				}
				DataObjects.TrackedPiece trackedPiece = new DataObjects.TrackedPiece();
				trackedPiece.action = item.Value.action;
				trackedPiece.prefab = item.Value.prefab;
				try
				{
					Piece component = PrefabManager.Instance.GetPrefab(item.Value.prefab).GetComponent<Piece>();
					trackedPiece.originalPiece = component;
				}
				catch (Exception)
				{
					Logger.LogWarning((object)"Could not find entries referenced piece, this modification will be skipped. Define a prefab to modify to fix this.");
				}
				if (item.Value.action == DataObjects.PieceAction.Enable || item.Value.action == DataObjects.PieceAction.Disable)
				{
					TrackedPieces.Add(trackedPiece);
					continue;
				}
				List<Requirement> list = new List<Requirement>();
				foreach (DataObjects.SimpleRequirement requirement in item.Value.requirements)
				{
					try
					{
						ItemDrop component2 = PrefabManager.Instance.GetPrefab(requirement.Prefab).GetComponent<ItemDrop>();
						list.Add(new Requirement
						{
							m_amount = requirement.amount,
							m_resItem = component2
						});
						Logger.LogInfo((object)$"Building requirement with res:{((Object)component2).name} amount:{requirement.amount}");
					}
					catch
					{
						Logger.LogWarning((object)("Could not find an itemDrop for resource with name: " + requirement.Prefab));
					}
				}
				trackedPiece.updatedRequirements = list.ToArray();
				if (item.Value.RequiredToPlaceCraftingStation != null && item.Value.RequiredToPlaceCraftingStation != "")
				{
					if (item.Value.RequiredToPlaceCraftingStation.ToLower() == "none")
					{
						trackedPiece.RequiredToPlaceCraftingStation = null;
					}
					else
					{
						GameObject prefab = PrefabManager.Instance.GetPrefab(item.Value.RequiredToPlaceCraftingStation);
						CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
						if ((Object)(object)val != (Object)null)
						{
							trackedPiece.RequiredToPlaceCraftingStation = val;
						}
						else
						{
							Logger.LogWarning((object)$"Could not link required crafting station, are you sure a crafting station exists with piecename: {val}");
						}
					}
				}
				else
				{
					trackedPiece.RequiredToPlaceCraftingStation = PrefabManager.Instance.GetPrefab(item.Value.prefab).GetComponent<Piece>().m_craftingStation;
				}
				trackedPiece.IsUpgradeForStation = item.Value.IsUpgradeForStation;
				trackedPiece.AllowedInDungeon = item.Value.AllowedInDungeon;
				trackedPiece.CanBeDeconstructed = item.Value.CanBeDeconstructed;
				trackedPiece.ComfortAmount = item.Value.ComfortAmount;
				trackedPiece.ComfortGroup = item.Value.ComfortGroup;
				trackedPiece.CraftingStationConnectionRadius = item.Value.CraftingStationConnectionRadius;
				trackedPiece.PieceDescription = item.Value.PieceDescription;
				trackedPiece.PieceName = item.Value.PieceName;
				trackedPiece.EnablePiece = item.Value.EnablePiece;
				trackedPiece.CultivatedGroundOnly = item.Value.CultivatedGroundOnly;
				trackedPiece.MustBeAvobeConnectedStation = item.Value.MustBeAvobeConnectedStation;
				trackedPiece.SpaceRequired = item.Value.SpaceRequired;
				trackedPiece.GroundPlacement = item.Value.GroundPlacement;
				TrackedPieces.Add(trackedPiece);
			}
		}

		public static void UpdateRecipeModificationsFromList(List<DataObjects.PieceModificationCollection> lPieceMods)
		{
			PiecesToModify.Clear();
			foreach (DataObjects.PieceModificationCollection lPieceMod in lPieceMods)
			{
				foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in lPieceMod.PieceModifications)
				{
					PiecesToModify.Add(pieceModification.Key, pieceModification.Value);
				}
			}
		}

		public static void UpdateRecipeModifications(DataObjects.PieceModificationCollection PieceMods)
		{
			PiecesToModify.Clear();
			foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in PieceMods.PieceModifications)
			{
				PiecesToModify.Add(pieceModification.Key, pieceModification.Value);
			}
		}
	}
	internal class RecipeReloadCommand : ConsoleCommand
	{
		public override string Name => "RM_Recipes_Reload";

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

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			RecipeUpdater.RecipeRevert();
			Config.ReloadRecipeFiles();
			RecipeUpdater.BuildRecipesForTracking();
			RecipeUpdater.SecondaryRecipeSync();
		}
	}
	internal class RecipePrintCommand : ConsoleCommand
	{
		public override string Name => "RM_Recipes_PrintAll";

		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_repairStation != (Object)null)
				{
					if (Config.EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Adding repair station");
					}
					recipeModification.repairAt = ((Object)item.m_repairStation).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 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.4.1")]
	[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.4.1";

		public Config cfg;

		private void Awake()
		{
			cfg = new Config(((BaseUnityPlugin)this).Config);
			ItemManager.OnItemsRegistered += RecipeUpdater.InitialRecipesAndSynchronize;
			ItemManager.OnItemsRegistered += PieceUpdater.InitialSychronization;
			MinimapManager.OnVanillaMapDataLoaded += RecipeUpdater.SecondaryRecipeSync;
			MinimapManager.OnVanillaMapDataLoaded += PieceUpdater.PieceUpdateRunner;
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipeReloadCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipePrintCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PiecePrintCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PieceReloadCommand());
		}
	}
	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()
		{
			if (TrackedRecipes.Count == 0)
			{
				return;
			}
			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[] resources = tracked_recipe.originalRecipe.m_resources;
					foreach (Requirement val2 in resources)
					{
						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)
		{
			bool flag = true;
			if ((trackedRecipe.action == DataObjects.Action.Modify || trackedRecipe.action == DataObjects.Action.Delete) && ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.originalRecipe) > 0)
			{
				flag = false;
			}
			if (trackedRecipe.action == DataObjects.Action.Add && ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.updatedRecipe) < 0)
			{
				flag = false;
			}
			if (trackedRecipe.action == DataObjects.Action.Enable || trackedRecipe.action == DataObjects.Action.Disable)
			{
				flag = false;
			}
			if (Config.EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"recipe {trackedRecipe.recipeName} already modified? {flag}");
			}
			return flag;
		}

		public static void BuildRecipesForTracking()
		{
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Expected O, but got Unknown
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			if (RecipesToModify.Count == 0)
			{
				return;
			}
			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[0];
					if (!item2.Value.recipe.noRecipeCost)
					{
						if (Config.EnableDebugMode.Value)
						{
							Logger.LogInfo((object)"Setting recipe cost requirements.");
						}
						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 = false
							};
							num2++;
						}
					}
					if (item2.Value.repairAt == null)
					{
						item2.Value.repairAt = item2.Value.craftedAt;
					}
					CustomRecipe val2 = new CustomRecipe(new RecipeConfig
					{
						Name = ((trackedRecipe.recipeName != null) ? trackedRecipe.recipeName : ("Recipe_" + item2.Value.prefab)),
						Amount = item2.Value.craftAmount,
						CraftingStation = item2.Value.craftedAt,
						RepairStation = item2.Value.repairAt,
						MinStationLevel = item2.Value.minStationLevel,
						Enabled = (item2.Value.action != DataObjects.Action.Disable),
						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);
							CraftingStation val3 = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
							if (item2.Value.craftedAt != item2.Value.repairAt)
							{
								GameObject prefab2 = PrefabManager.Instance.GetPrefab(item2.Value.repairAt);
								if (prefab2 != null)
								{
									prefab2.GetComponent<CraftingStation>();
								}
							}
							recipe.m_repairStation = val3;
							recipe.m_craftingStation = val3;
						}
						catch
						{
							Logger.LogWarning((object)("Crafting station (" + item2.Value.craftedAt + ") or repair station (" + item2.Value.repairAt + ") could not be resolved or did not have a craftingStation component"));
						}
					}
					try
					{
						GameObject prefab3 = PrefabManager.Instance.GetPrefab(item2.Value.prefab);
						ItemDrop component = prefab3.GetComponent<ItemDrop>();
						if (!((Object)(object)component != (Object)null))
						{
							Logger.LogWarning((object)$"Could not find a prefab ({item2.Value.prefab}) GO ({prefab3}) 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 val4 in resources)
					{
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val4.m_resItem).name.Replace("JVLmock_", ""));
						if ((Object)(object)itemPrefab != (Object)null)
						{
							val4.m_resItem = itemPrefab.GetComponent<ItemDrop>();
						}
						else
						{
							Logger.LogWarning((object)("Could not resolve itemdrop reference for: " + ((Object)val4.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)
			{
				if (hashSet.Contains(newRecipe))
				{
					return true;
				}
				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);
			}
		}

		public static void UpdateRecipeModificationsFromList(List<DataObjects.RecipeModificationCollection> lRecipeMods)
		{
			RecipesToModify.Clear();
			foreach (DataObjects.RecipeModificationCollection lRecipeMod in lRecipeMods)
			{
				foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in lRecipeMod.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 List<string> RecipeConfigFilePaths = new List<string>();

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

		public static List<string> PieceConfigFilePaths = new List<string>();

		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;

		private static CustomRPC PiecesConfigRPC;

		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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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
			{
				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;
			bool flag2 = false;
			string[] files = Directory.GetFiles(secondaryConfigDirectoryPath);
			foreach (string text in files)
			{
				if (text.Contains("Recipes.yaml") && !text.Contains("ObjectDBRecipes.yaml"))
				{
					if (EnableDebugMode.Value)
					{
						Logger.LogInfo((object)("Found recipe configuration yaml: " + text));
					}
					RecipeConfigFilePaths.Add(text);
					flag = true;
				}
				if (text.Contains("Pieces.yaml"))
				{
					if (EnableDebugMode.Value)
					{
						Logger.LogInfo((object)("Found pieces configuration yaml: " + text));
					}
					PieceConfigFilePaths.Add(text);
					flag2 = true;
				}
			}
			if (!flag)
			{
				Logger.LogInfo((object)"Recipe file missing, recreating.");
				using StreamWriter streamWriter = new StreamWriter(recipeConfigFilePath);
				string value = "#################################################\n# Recipe Manipulation Config\n#################################################\n# recipeModifications:                     # <- This is the top level key, all modifications live under this, it is required.\n#   DisableWoodArrow:                      # <- This is the modification name, its primarily for you to understand what this modification does SHOULD BE UNIQUE\n#     action: Disable                      # <- This is the action it should be one of [Disable, Delete, Modify, Add, Enable]\n#     prefab: ArrowWood                    # <- This is the prefab that the modification will target\n#   AddNewWoodArrowRecipe:\n#     action: Add\n#     prefab: ArrowWood\n#     recipeName: Recipe_ArrowWood         # <- optional, specifying the recipe name allows matching and mutating multiple recipes targeting the same prefab\n#     craftedAt: Workbench                 # <- The crafting station that should craft this recipe, leave it empty or invalid for handcrafting\n#     minStationLevel: 2                   # <- This is the required crafting station level for discovery AND crafting\n#     recipe:                              # <- When performing [Modify] or [Add] you should define a recipe\n#       anyOneResource: false              # <- This makes the recipe only require one ingrediant, first from the top will be used.\n#       noRecipeCost: false                # <- This makes the recipe not require any resources to craft, if this is used the ingredients list will be ignored\n#       ingredients:                       # <- Ingrediants in the recipe, is an array\n#         - prefab: Wood                   # <- Prefab that this ingrediant requires\n#           craftCost: 2                   # <- The amount of this ingrediant it takes to craft the recipe  \n#           upgradeCost: 0                 # <- The amount of this ingrediant it takes to upgrade the item \n#         - prefab: Feathers\n#           craftCost: 2\n#           upgradeCost: 0\n#   DeleteTrollHideArmorRecipe:\n#     action: Delete\n#     prefab: CapeTrollHide\n#   ModifyTrollHideChestRecipe:\n#     action: Modify\n#     prefab: ArmorTrollLeatherChest\n#     craftedAt: Workbench\n#     minStationLevel: 1\n#     recipe:\n#       anyOneResource: false\n#       ingredients:\n#         - prefab: TrollHide\n#           craftCost: 4\n#           upgradeCost: 2\n";
				streamWriter.WriteLine(value);
				streamWriter.WriteLine(YamlRecipeConfigDefinition());
			}
			if (!flag2)
			{
				Logger.LogInfo((object)"Pieces file missing, recreating.");
				using StreamWriter streamWriter2 = new StreamWriter(pieceConfigFilePath);
				string value2 = "############################################################################\n# Piece Manipulation Config\n############################################################################\n# pieceModifications:                                      # <- This is the top level key, it is required\n#  modify_the_bed:                                         # <- REQUIRED The name of this modification, it should be unique but is for your information\n#    action: Enable                                        # <- REQUIRED This is the action applied can be [Enable, Disable, Modify]\n#    prefab: bed                                           # <- REQUIRED This is the prefab that the action will be applied to\n#    requirements:                                         # <- If the piece is being modified, you can set requirements which will be the cost to build this\n#    - prefab: Wood                                        # <- Each requirement entry requires a prefab name, you can find item prefabs on the valheim wiki\n#      amount: 8                                           # <- The amount of the prefab required\n#    requiredToPlaceCraftingStation: piece_workbench       # <- The crafting station used to place this item, if it is set to 'none' it will remove the station requirement\n#    allowedInDungeon: false                               # <- If you can build this inside dungeons\n#    canBeDeconstructed: true                              # <- If this can be broken with middle mouse\n#    pieceCategory: Furniture                              # <- The category tab this will be placed in. This can be any of the categories across any available tools\n#    comfortAmount: 1                                      # <- If above 0 this item will provide comfort\n#    comfortGroup: Bed                                     # <- The comfort group this is a part of\n#    isUpgradeForStation: false                            # <- If this piece is considered an upgrade for a crafting station\n#    craftingStationConnectionRadius: 0                    # <- The radius that this will connect to a crafting station\n#    mustBeAvobeConnectedStation: false                    # <- If this upgrade must be placed ABOVE its crafting station- this is normally only used for hanging upgrades for the cooking station\n#    spaceRequired: 0                                      # <- How much space is required for this item\n#    pieceName: $piece_bed                                 # <- The localizable name for this, setting \"My Bed\" will make this piece called \"My Bed\"\n#    pieceDescription: ''                                  # <- The description for this piece, many pieces do not have this\n#    enablePiece: true                                     # <- Whether or not this piece is enabled\n#    onlyInSelectBiome: None                               # <- Whether or not this can be placed in only one biome, in vanilla this is used for plants\n#    cultivatedGroundOnly: false                           # <- Whether this piece needs to be placed on cultivated ground\n#    groundPlacement: false                                # <- Whether this piece needs to be placed on ground (stone is also considered ground)";
				streamWriter2.WriteLine(value2);
				streamWriter2.WriteLine(YamlPieceConfigDefinition());
			}
			List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
			foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
			{
				string input = File.ReadAllText(recipeConfigFilePath);
				try
				{
					DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
					list.Add(item);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
				}
				FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
				fileSystemWatcher.Path = secondaryConfigDirectoryPath;
				fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
				fileSystemWatcher.Filter = DetermineFileName(recipeConfigFilePath) ?? "";
				fileSystemWatcher.Changed += UpdateRecipeConfigFilesOnChange;
				fileSystemWatcher.Created += UpdateRecipeConfigFilesOnChange;
				fileSystemWatcher.Renamed += UpdateRecipeConfigFilesOnChange;
				fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
				fileSystemWatcher.EnableRaisingEvents = true;
			}
			RecipeUpdater.UpdateRecipeModificationsFromList(list);
			List<DataObjects.PieceModificationCollection> list2 = new List<DataObjects.PieceModificationCollection>();
			foreach (string pieceConfigFilePath in PieceConfigFilePaths)
			{
				string input2 = File.ReadAllText(pieceConfigFilePath);
				try
				{
					DataObjects.PieceModificationCollection item2 = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(input2);
					list2.Add(item2);
				}
				catch (Exception arg2)
				{
					Logger.LogError((object)$"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg2}");
				}
				FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher();
				fileSystemWatcher2.Path = secondaryConfigDirectoryPath;
				fileSystemWatcher2.NotifyFilter = NotifyFilters.LastWrite;
				fileSystemWatcher2.Filter = DetermineFileName(pieceConfigFilePath) ?? "";
				fileSystemWatcher2.Changed += UpdatePieceConfigFilesOnChange;
				fileSystemWatcher2.Created += UpdatePieceConfigFilesOnChange;
				fileSystemWatcher2.Renamed += UpdatePieceConfigFilesOnChange;
				fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject;
				fileSystemWatcher2.EnableRaisingEvents = true;
			}
			PieceUpdater.UpdateRecipeModificationsFromList(list2);
		}

		internal static void ReloadPieceFiles()
		{
			List<DataObjects.PieceModificationCollection> list = new List<DataObjects.PieceModificationCollection>();
			foreach (string pieceConfigFilePath in PieceConfigFilePaths)
			{
				string input = File.ReadAllText(pieceConfigFilePath);
				try
				{
					DataObjects.PieceModificationCollection item = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(input);
					list.Add(item);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg}");
				}
			}
			PieceUpdater.UpdateRecipeModificationsFromList(list);
		}

		internal static void ReloadRecipeFiles()
		{
			List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
			foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
			{
				string input = File.ReadAllText(recipeConfigFilePath);
				try
				{
					DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
					list.Add(item);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
				}
			}
			RecipeUpdater.UpdateRecipeModificationsFromList(list);
		}

		private static string DetermineFileName(string fullfilepath)
		{
			return fullfilepath.Split(new char[1] { '\\' })[^2];
		}

		private static void UpdateRecipeConfigFilesOnChange(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(recipeConfigFilePath))
			{
				return;
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"{e} Recipe filewatcher called, updating recipe Modification values.");
			}
			RecipeUpdater.RecipeRevert();
			RecipeUpdater.UpdateRecipeModifications(ReadAllRecipeConfigs());
			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 recipe configs to clients.");
					}
					return;
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"Error while server syncing recipeModification configs: {arg}");
					return;
				}
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogDebug((object)"Instance is not a server, and will not send znet recipeModification updates.");
			}
		}

		private static void UpdatePieceConfigFilesOnChange(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(pieceConfigFilePath))
			{
				return;
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)$"{e} Piece filewatcher called, updating piece Modification values.");
			}
			PieceUpdater.RevertPieceModifications();
			PieceUpdater.UpdateRecipeModifications(ReadAllPieceConfigs());
			PieceUpdater.BuildPieceTracker();
			PieceUpdater.PieceUpdateRunner();
			if (EnableDebugMode.Value)
			{
				Logger.LogInfo((object)"Updated RecipeModifications in-memory values.");
			}
			if (GUIManager.IsHeadless())
			{
				try
				{
					RecipeConfigRPC.SendPackage(ZNet.instance.m_peers, SendPieceConfigs());
					if (EnableDebugMode.Value)
					{
						Logger.LogInfo((object)"Sent levels configs to clients.");
					}
					return;
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"Error while server syncing recipeModification configs: {arg}");
					return;
				}
			}
			if (EnableDebugMode.Value)
			{
				Logger.LogDebug((object)"Instance is not a server, and will not send znet recipeModification updates.");
			}
		}

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

		public void SetupConfigRPCs()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0027: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_006e: Expected O, but got Unknown
			RecipeConfigRPC = NetworkManager.Instance.AddRPC("recipeManager_recipes_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveRecipeConfigs));
			SynchronizationManager.Instance.AddInitialSynchronization(RecipeConfigRPC, (Func<ZPackage>)SendRecipeConfigs);
			PiecesConfigRPC = NetworkManager.Instance.AddRPC("recipeManager_pieces_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceivePieceConfigs));
			SynchronizationManager.Instance.AddInitialSynchronization(PiecesConfigRPC, (Func<ZPackage>)SendPieceConfigs);
		}

		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_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(ReadAllRecipeConfigs().ToString());
			return val;
		}

		private static ZPackage SendPieceConfigs()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(ReadAllPieceConfigs().ToString());
			return val;
		}

		private static DataObjects.RecipeModificationCollection ReadAllRecipeConfigs()
		{
			List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
			foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
			{
				if (EnableDebugMode.Value)
				{
					Logger.LogDebug((object)("Loading values from " + recipeConfigFilePath + "."));
				}
				string input = File.ReadAllText(recipeConfigFilePath);
				try
				{
					DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input);
					list.Add(item);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
				}
			}
			DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
			foreach (DataObjects.RecipeModificationCollection item2 in list)
			{
				foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in item2.RecipeModifications)
				{
					recipeModificationCollection.RecipeModifications.Add(recipeModification.Key, recipeModification.Value);
				}
			}
			return recipeModificationCollection;
		}

		private static DataObjects.PieceModificationCollection ReadAllPieceConfigs()
		{
			List<DataObjects.PieceModificationCollection> list = new List<DataObjects.PieceModificationCollection>();
			foreach (string pieceConfigFilePath in PieceConfigFilePaths)
			{
				if (EnableDebugMode.Value)
				{
					Logger.LogDebug((object)("Loading values from " + pieceConfigFilePath + "."));
				}
				string input = File.ReadAllText(pieceConfigFilePath);
				try
				{
					DataObjects.PieceModificationCollection item = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(input);
					list.Add(item);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg}");
				}
			}
			DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
			foreach (DataObjects.PieceModificationCollection item2 in list)
			{
				foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in item2.PieceModifications)
				{
					pieceModificationCollection.PieceModifications.Add(pieceModification.Key, pieceModification.Value);
				}
			}
			return pieceModificationCollection;
		}

		private static IEnumerator OnClientReceiveRecipeConfigs(long sender, ZPackage package)
		{
			string input = package.ReadString();
			RecipeUpdater.RecipeRevert();
			try
			{
				RecipeUpdater.UpdateRecipeModifications(yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(input));
			}
			catch
			{
				Logger.LogWarning((object)"Recieved invalid configuration, all recipes reverted.");
			}
			RecipeUpdater.BuildRecipesForTracking();
			RecipeUpdater.SecondaryRecipeSync();
			yield return null;
		}

		private static IEnumerator OnClientReceivePieceConfigs(long sender, ZPackage package)
		{
			string input = package.ReadString();
			PieceUpdater.RevertPieceModifications();
			try
			{
				PieceUpdater.UpdateRecipeModifications(yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(input));
			}
			catch
			{
				Logger.LogWarning((object)"Recieved invalid configuration, all pieces reverted.");
			}
			PieceUpdater.BuildPieceTracker();
			PieceUpdater.PieceUpdateRunner();
			yield return null;
		}

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

		public static string YamlPieceConfigDefinition()
		{
			DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
			pieceModificationCollection.PieceModifications = PieceUpdater.PiecesToModify;
			return yamlserializer.Serialize(pieceModificationCollection);
		}

		public ConfigEntry<bool> BindServerConfig(string catagory, string key, bool value, string description, bool advanced = false)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_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_0027: 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
			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_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_0027: 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
			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 enum PieceAction
		{
			Disable,
			Modify,
			Enable
		}

		public class TrackedPiece
		{
			public PieceAction action { get; set; }

			public string prefab { get; set; }

			public Piece originalPiece { get; set; }

			public Requirement[] updatedRequirements { get; set; }

			public CraftingStation RequiredToPlaceCraftingStation { get; set; }

			public bool AllowedInDungeon { get; set; }

			public bool CanBeDeconstructed { get; set; } = true;


			public PieceCategory PieceCategory { get; set; } = (PieceCategory)100;


			public int ComfortAmount { get; set; } = -1;


			public ComfortGroup ComfortGroup { get; set; }

			public bool IsUpgradeForStation { get; set; }

			public float CraftingStationConnectionRadius { get; set; } = -1f;


			public bool MustBeAvobeConnectedStation { get; set; }

			public float SpaceRequired { get; set; } = -1f;


			public string PieceName { get; set; }

			public string PieceDescription { get; set; }

			public bool EnablePiece { get; set; } = true;


			public Biome OnlyInBiome { get; set; } = (Biome)895;


			public bool CultivatedGroundOnly { get; set; }

			public bool GroundPlacement { get; set; } = true;

		}

		[DataContract]
		public class PieceModificationCollection
		{
			public Dictionary<string, PieceModification> PieceModifications { get; set; } = new Dictionary<string, PieceModification>();

		}

		[DataContract]
		public class PieceModification
		{
			public PieceAction action { get; set; }

			public string prefab { get; set; }

			public List<SimpleRequirement> requirements { get; set; } = new List<SimpleRequirement>();


			public string RequiredToPlaceCraftingStation { get; set; }

			public bool AllowedInDungeon { get; set; }

			public bool CanBeDeconstructed { get; set; } = true;


			public PieceCategory PieceCategory { get; set; } = (PieceCategory)100;


			public int ComfortAmount { get; set; } = -1;


			public ComfortGroup ComfortGroup { get; set; }

			public bool IsUpgradeForStation { get; set; }

			public float CraftingStationConnectionRadius { get; set; } = -1f;


			public bool MustBeAvobeConnectedStation { get; set; }

			public float SpaceRequired { get; set; } = -1f;


			public string PieceName { get; set; }

			public string PieceDescription { get; set; }

			public bool EnablePiece { get; set; } = true;


			public Biome OnlyInSelectBiome { get; set; } = (Biome)895;


			public bool CultivatedGroundOnly { get; set; }

			public bool GroundPlacement { get; set; } = true;

		}

		[DataContract]
		public class SimpleRequirement
		{
			public string Prefab { get; set; }

			public int amount { get; set; }
		}

		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 string repairAt { 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; }

			public bool noRecipeCost { get; set; }

			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; }
		}
	}
}
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 ?? thro