Decompiled source of balrond BannerColorizer v1.0.7

plugins/BalrondBannerColorizer.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using HarmonyLib;
using LitJson2;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ProjectAshlands")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProjectAshlands")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f405ea1c-ac25-47a3-9aa2-a8f56c14bfd6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace BalrondBannerColorizer
{
	public class BalrondTranslator
	{
		public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>();

		public static Dictionary<string, string> getLanguage(string language)
		{
			if (string.IsNullOrEmpty(language))
			{
				return null;
			}
			if (translations.TryGetValue(language, out var value))
			{
				return value;
			}
			return null;
		}
	}
	public class ModResourceLoader
	{
		public AssetBundle assetBundle;

		public List<GameObject> items = new List<GameObject>();

		public ShaderReplacment shaderReplacment = new ShaderReplacment();

		public Material crystal01black;

		public Material crystal01blue;

		public Material crystal01green;

		public Material crystal01orange;

		public Material crystal01purple;

		public Material crystal01red;

		public Material crystal01white;

		public Material crystal01yellow;

		public Material banner01black;

		public Material banner01blue;

		public Material banner01green;

		public Material banner01orange;

		public Material banner01purple;

		public Material banner01red;

		public Material banner01white;

		public Material banner01yellow;

		public Material banner02black;

		public Material banner02blue;

		public Material banner02green;

		public Material banner02orange;

		public Material banner02purple;

		public Material banner02red;

		public Material banner02white;

		public Material banner02yellow;

		public Material banner03black;

		public Material banner03blue;

		public Material banner03green;

		public Material banner03orange;

		public Material banner03purple;

		public Material banner03red;

		public Material banner03white;

		public Material banner03yellow;

		public Material banner04black;

		public Material banner04blue;

		public Material banner04green;

		public Material banner04orange;

		public Material banner04purple;

		public Material banner04red;

		public Material banner04white;

		public Material banner04yellow;

		public Material banner05black;

		public Material banner05blue;

		public Material banner05green;

		public Material banner05orange;

		public Material banner05purple;

		public Material banner05red;

		public Material banner05white;

		public Material banner05yellow;

		public Material banner06black;

		public Material banner06blue;

		public Material banner06green;

		public Material banner06orange;

		public Material banner06purple;

		public Material banner06red;

		public Material banner06white;

		public Material banner06yellow;

		public Material banner07black;

		public Material banner07blue;

		public Material banner07green;

		public Material banner07orange;

		public Material banner07purple;

		public Material banner07red;

		public Material banner07white;

		public Material banner07yellow;

		public Material banner08black;

		public Material banner08blue;

		public Material banner08green;

		public Material banner08orange;

		public Material banner08purple;

		public Material banner08red;

		public Material banner08white;

		public Material banner08yellow;

		public Material banner09black;

		public Material banner09blue;

		public Material banner09green;

		public Material banner09orange;

		public Material banner09purple;

		public Material banner09red;

		public Material banner09white;

		public Material banner09yellow;

		public Material banner10black;

		public Material banner10blue;

		public Material banner10green;

		public Material banner10orange;

		public Material banner10purple;

		public Material banner10red;

		public Material banner10white;

		public Material banner10yellow;

		public Material banner11black;

		public Material banner11blue;

		public Material banner11green;

		public Material banner11orange;

		public Material banner11purple;

		public Material banner11red;

		public Material banner11white;

		public Material banner11yellow;

		public Material bannerHangingblack;

		public Material bannerHangingblue;

		public Material bannerHanginggreen;

		public Material bannerHangingorange;

		public Material bannerHangingpurple;

		public Material bannerHangingred;

		public Material bannerHangingwhite;

		public Material bannerHangingyellow;

		public Material bannerHanging2black;

		public Material bannerHanging2blue;

		public Material bannerHanging2green;

		public Material bannerHanging2orange;

		public Material bannerHanging2purple;

		public Material bannerHanging2red;

		public Material bannerHanging2white;

		public Material bannerHanging2yellow;

		public Material bannerHanging3black;

		public Material bannerHanging3blue;

		public Material bannerHanging3green;

		public Material bannerHanging3orange;

		public Material bannerHanging3purple;

		public Material bannerHanging3red;

		public Material bannerHanging3white;

		public Material bannerHanging3yellow;

		public Material juteCarpetblack;

		public Material juteCarpetblue;

		public Material juteCarpetgreen;

		public Material juteCarpetorange;

		public Material juteCarpetpurple;

		public Material juteCarpetred;

		public Material juteCarpetwhite;

		public Material juteCarpetyellow;

		public Material juteCarpetMainblack;

		public Material juteCarpetMainblue;

		public Material juteCarpetMaingreen;

		public Material juteCarpetMainorange;

		public Material juteCarpetMainpurple;

		public Material juteCarpetMainred;

		public Material juteCarpetMainwhite;

		public Material juteCarpetMainyellow;

		public Material juteCarpetDestructionblack;

		public Material juteCarpetDestructionblue;

		public Material juteCarpetDestructiongreen;

		public Material juteCarpetDestructionorange;

		public Material juteCarpetDestructionpurple;

		public Material juteCarpetDestructionred;

		public Material juteCarpetDestructionwhite;

		public Material juteCarpetDestructionyellow;

		public Material juteCarpet2black;

		public Material juteCarpet2blue;

		public Material juteCarpet2green;

		public Material juteCarpet2orange;

		public Material juteCarpet2purple;

		public Material juteCarpet2red;

		public Material juteCarpet2white;

		public Material juteCarpet2yellow;

		public Material juteCarpetMain2black;

		public Material juteCarpetMain2blue;

		public Material juteCarpetMain2green;

		public Material juteCarpetMain2orange;

		public Material juteCarpetMain2purple;

		public Material juteCarpetMain2red;

		public Material juteCarpetMain2white;

		public Material juteCarpetMain2yellow;

		public Material juteCarpetDestruction2black;

		public Material juteCarpetDestruction2blue;

		public Material juteCarpetDestruction2green;

		public Material juteCarpetDestruction2orange;

		public Material juteCarpetDestruction2purple;

		public Material juteCarpetDestruction2red;

		public Material juteCarpetDestruction2white;

		public Material juteCarpetDestruction2yellow;

		public Material roofDarkMain2black;

		public Material roofDarkMain2blue;

		public Material roofDarkMain2green;

		public Material roofDarkMain2orange;

		public Material roofDarkMain2purple;

		public Material roofDarkMain2red;

		public Material roofDarkMain2white;

		public Material roofDarkMain2yellow;

		public Material roofDarkDestructionblack;

		public Material roofDarkDestructionblue;

		public Material roofDarkDestructiongreen;

		public Material roofDarkDestructionorange;

		public Material roofDarkDestructionpurple;

		public Material roofDarkDestructionred;

		public Material roofDarkDestructionwhite;

		public Material roofDarkDestructionyellow;

		public static string[] prefabNames = new string[8] { "DyeBlack", "DyeBlue", "DyeGreen", "DyeOrange", "DyePurple", "DyeRed", "DyeWhite", "DyeYellow" };

		private static readonly Dictionary<string, string> prefabTranslationTag = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			{ "DyeBlack", "$tag_dyeblack_bal" },
			{ "DyeBlue", "$tag_dyeblue_bal" },
			{ "DyeGreen", "$tag_dyegreen_bal" },
			{ "DyeOrange", "$tag_dyeorange_bal" },
			{ "DyePurple", "$tag_dyepurple_bal" },
			{ "DyeRed", "$tag_dyered_bal" },
			{ "DyeWhite", "$tag_dyewhite_bal" },
			{ "DyeYellow", "$tag_dyeyellow_bal" }
		};

		public static readonly string[] colorNames = new string[8] { "black", "blue", "green", "orange", "purple", "red", "white", "yellow" };

		public GameObject dyeTable;

		public void loadAssets()
		{
			assetBundle = GetAssetBundleFromResources("bannercolorizer");
			string mainPath = "Assets/Custom/BalrondBannerColorizer/";
			LoadPrefabs(mainPath);
			LoadDyeTable(mainPath);
			LoadMaterialSet("crystalWall1", mainPath, AssignCrystalWall1);
			LoadMaterialSet("banner01", mainPath, AssignBanner01);
			LoadMaterialSet("banner02", mainPath, AssignBanner02);
			LoadMaterialSet("banner03", mainPath, AssignBanner03);
			LoadMaterialSet("banner04", mainPath, AssignBanner04);
			LoadMaterialSet("banner05", mainPath, AssignBanner05);
			LoadMaterialSet("banner06", mainPath, AssignBanner06);
			LoadMaterialSet("banner07", mainPath, AssignBanner07);
			LoadMaterialSet("banner08", mainPath, AssignBanner08);
			LoadMaterialSet("banner09", mainPath, AssignBanner09);
			LoadMaterialSet("banner10", mainPath, AssignBanner10);
			LoadMaterialSet("banner11", mainPath, AssignBanner11);
			LoadMaterialSet("bannerHanging", mainPath, AssignBannerHanging);
			LoadMaterialSet("bannerHanging2", mainPath, AssignBannerHanging2);
			LoadMaterialSet("bannerHanging3", mainPath, AssignBannerHanging3);
			LoadMaterialSet("juteCarpet", mainPath, AssignJuteCarpet);
			LoadMaterialSet("juteCarpetMain", mainPath, AssignJuteCarpetMain);
			LoadMaterialSet("juteCarpetDestruction", mainPath, AssignJuteCarpetDestruction);
			LoadMaterialSet("juteCarpet2", mainPath, AssignJuteCarpet2);
			LoadMaterialSet("juteCarpetMain2", mainPath, AssignJuteCarpetMain2);
			LoadMaterialSet("juteCarpetDestruction2", mainPath, AssignJuteCarpetDestruction2);
			LoadMaterialSet("roofNew", mainPath, AssignRoofDarkMain2);
			LoadMaterialSet("roofWorn", mainPath, AssignRoofDarkDestruction);
		}

		private void LoadPrefabs(string mainPath)
		{
			items.Clear();
			string[] array = prefabNames;
			foreach (string text in array)
			{
				string text2 = mainPath + "prefabs/" + text + ".prefab";
				GameObject val = assetBundle.LoadAsset<GameObject>(text2);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Prefab not found: " + text2));
					continue;
				}
				setTranslationTags(val);
				items.Add(val);
			}
		}

		private void setTranslationTags(GameObject prefab)
		{
			string value = "";
			prefabTranslationTag.TryGetValue(((Object)prefab).name, out value);
			if (value != "" && value != null)
			{
				prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name = value;
			}
			prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_description = "$tag_dyedescription_bal";
		}

		private void LoadDyeTable(string mainPath)
		{
			string text = mainPath + "prefabs/piece_dyestation.prefab";
			dyeTable = assetBundle.LoadAsset<GameObject>(text);
			if ((Object)(object)dyeTable == (Object)null)
			{
				Debug.LogWarning((object)("Dye table prefab not found: " + text));
				return;
			}
			dyeTable.GetComponent<Piece>().m_name = "$tag_dyetable_bal";
			dyeTable.GetComponent<Piece>().m_description = "$tag_dyetable_bal_description";
			dyeTable.GetComponent<CraftingStation>().m_name = "$tag_dyetable_bal";
		}

		private void LoadMaterialSet(string folderName, string mainPath, Action<Material[]> assignAction)
		{
			Material[] obj = LoadColorMaterials(folderName, mainPath);
			assignAction?.Invoke(obj);
		}

		private Material[] LoadColorMaterials(string folderName, string mainPath)
		{
			Material[] array = (Material[])(object)new Material[colorNames.Length];
			for (int i = 0; i < colorNames.Length; i++)
			{
				string text = mainPath + folderName + "/" + colorNames[i] + ".mat";
				Material val = assetBundle.LoadAsset<Material>(text);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Material not found: " + text));
					array[i] = null;
				}
				else
				{
					ShaderReplacment.ReplaceMaterial(val);
					array[i] = val;
				}
			}
			return array;
		}

		private void AssignCrystalWall1(Material[] mats)
		{
			crystal01black = mats[0];
			crystal01blue = mats[1];
			crystal01green = mats[2];
			crystal01orange = mats[3];
			crystal01purple = mats[4];
			crystal01red = mats[5];
			crystal01white = mats[6];
			crystal01yellow = mats[7];
		}

		private void AssignBanner01(Material[] mats)
		{
			banner01black = mats[0];
			banner01blue = mats[1];
			banner01green = mats[2];
			banner01orange = mats[3];
			banner01purple = mats[4];
			banner01red = mats[5];
			banner01white = mats[6];
			banner01yellow = mats[7];
		}

		private void AssignBanner02(Material[] mats)
		{
			banner02black = mats[0];
			banner02blue = mats[1];
			banner02green = mats[2];
			banner02orange = mats[3];
			banner02purple = mats[4];
			banner02red = mats[5];
			banner02white = mats[6];
			banner02yellow = mats[7];
		}

		private void AssignBanner03(Material[] mats)
		{
			banner03black = mats[0];
			banner03blue = mats[1];
			banner03green = mats[2];
			banner03orange = mats[3];
			banner03purple = mats[4];
			banner03red = mats[5];
			banner03white = mats[6];
			banner03yellow = mats[7];
		}

		private void AssignBanner04(Material[] mats)
		{
			banner04black = mats[0];
			banner04blue = mats[1];
			banner04green = mats[2];
			banner04orange = mats[3];
			banner04purple = mats[4];
			banner04red = mats[5];
			banner04white = mats[6];
			banner04yellow = mats[7];
		}

		private void AssignBanner05(Material[] mats)
		{
			banner05black = mats[0];
			banner05blue = mats[1];
			banner05green = mats[2];
			banner05orange = mats[3];
			banner05purple = mats[4];
			banner05red = mats[5];
			banner05white = mats[6];
			banner05yellow = mats[7];
		}

		private void AssignBanner06(Material[] mats)
		{
			banner06black = mats[0];
			banner06blue = mats[1];
			banner06green = mats[2];
			banner06orange = mats[3];
			banner06purple = mats[4];
			banner06red = mats[5];
			banner06white = mats[6];
			banner06yellow = mats[7];
		}

		private void AssignBanner07(Material[] mats)
		{
			banner07black = mats[0];
			banner07blue = mats[1];
			banner07green = mats[2];
			banner07orange = mats[3];
			banner07purple = mats[4];
			banner07red = mats[5];
			banner07white = mats[6];
			banner07yellow = mats[7];
		}

		private void AssignBanner08(Material[] mats)
		{
			banner08black = mats[0];
			banner08blue = mats[1];
			banner08green = mats[2];
			banner08orange = mats[3];
			banner08purple = mats[4];
			banner08red = mats[5];
			banner08white = mats[6];
			banner08yellow = mats[7];
		}

		private void AssignBanner09(Material[] mats)
		{
			banner09black = mats[0];
			banner09blue = mats[1];
			banner09green = mats[2];
			banner09orange = mats[3];
			banner09purple = mats[4];
			banner09red = mats[5];
			banner09white = mats[6];
			banner09yellow = mats[7];
		}

		private void AssignBanner10(Material[] mats)
		{
			banner10black = mats[0];
			banner10blue = mats[1];
			banner10green = mats[2];
			banner10orange = mats[3];
			banner10purple = mats[4];
			banner10red = mats[5];
			banner10white = mats[6];
			banner10yellow = mats[7];
		}

		private void AssignBanner11(Material[] mats)
		{
			banner11black = mats[0];
			banner11blue = mats[1];
			banner11green = mats[2];
			banner11orange = mats[3];
			banner11purple = mats[4];
			banner11red = mats[5];
			banner11white = mats[6];
			banner11yellow = mats[7];
		}

		private void AssignBannerHanging(Material[] mats)
		{
			bannerHangingblack = mats[0];
			bannerHangingblue = mats[1];
			bannerHanginggreen = mats[2];
			bannerHangingorange = mats[3];
			bannerHangingpurple = mats[4];
			bannerHangingred = mats[5];
			bannerHangingwhite = mats[6];
			bannerHangingyellow = mats[7];
		}

		private void AssignBannerHanging2(Material[] mats)
		{
			bannerHanging2black = mats[0];
			bannerHanging2blue = mats[1];
			bannerHanging2green = mats[2];
			bannerHanging2orange = mats[3];
			bannerHanging2purple = mats[4];
			bannerHanging2red = mats[5];
			bannerHanging2white = mats[6];
			bannerHanging2yellow = mats[7];
		}

		private void AssignBannerHanging3(Material[] mats)
		{
			bannerHanging3black = mats[0];
			bannerHanging3blue = mats[1];
			bannerHanging3green = mats[2];
			bannerHanging3orange = mats[3];
			bannerHanging3purple = mats[4];
			bannerHanging3red = mats[5];
			bannerHanging3white = mats[6];
			bannerHanging3yellow = mats[7];
		}

		private void AssignJuteCarpet(Material[] mats)
		{
			juteCarpetblack = mats[0];
			juteCarpetblue = mats[1];
			juteCarpetgreen = mats[2];
			juteCarpetorange = mats[3];
			juteCarpetpurple = mats[4];
			juteCarpetred = mats[5];
			juteCarpetwhite = mats[6];
			juteCarpetyellow = mats[7];
		}

		private void AssignJuteCarpetMain(Material[] mats)
		{
			juteCarpetMainblack = mats[0];
			juteCarpetMainblue = mats[1];
			juteCarpetMaingreen = mats[2];
			juteCarpetMainorange = mats[3];
			juteCarpetMainpurple = mats[4];
			juteCarpetMainred = mats[5];
			juteCarpetMainwhite = mats[6];
			juteCarpetMainyellow = mats[7];
		}

		private void AssignJuteCarpetDestruction(Material[] mats)
		{
			juteCarpetDestructionblack = mats[0];
			juteCarpetDestructionblue = mats[1];
			juteCarpetDestructiongreen = mats[2];
			juteCarpetDestructionorange = mats[3];
			juteCarpetDestructionpurple = mats[4];
			juteCarpetDestructionred = mats[5];
			juteCarpetDestructionwhite = mats[6];
			juteCarpetDestructionyellow = mats[7];
		}

		private void AssignJuteCarpet2(Material[] mats)
		{
			juteCarpet2black = mats[0];
			juteCarpet2blue = mats[1];
			juteCarpet2green = mats[2];
			juteCarpet2orange = mats[3];
			juteCarpet2purple = mats[4];
			juteCarpet2red = mats[5];
			juteCarpet2white = mats[6];
			juteCarpet2yellow = mats[7];
		}

		private void AssignJuteCarpetMain2(Material[] mats)
		{
			juteCarpetMain2black = mats[0];
			juteCarpetMain2blue = mats[1];
			juteCarpetMain2green = mats[2];
			juteCarpetMain2orange = mats[3];
			juteCarpetMain2purple = mats[4];
			juteCarpetMain2red = mats[5];
			juteCarpetMain2white = mats[6];
			juteCarpetMain2yellow = mats[7];
		}

		private void AssignJuteCarpetDestruction2(Material[] mats)
		{
			juteCarpetDestruction2black = mats[0];
			juteCarpetDestruction2blue = mats[1];
			juteCarpetDestruction2green = mats[2];
			juteCarpetDestruction2orange = mats[3];
			juteCarpetDestruction2purple = mats[4];
			juteCarpetDestruction2red = mats[5];
			juteCarpetDestruction2white = mats[6];
			juteCarpetDestruction2yellow = mats[7];
		}

		private void AssignRoofDarkMain2(Material[] mats)
		{
			roofDarkMain2black = mats[0];
			roofDarkMain2blue = mats[1];
			roofDarkMain2green = mats[2];
			roofDarkMain2orange = mats[3];
			roofDarkMain2purple = mats[4];
			roofDarkMain2red = mats[5];
			roofDarkMain2white = mats[6];
			roofDarkMain2yellow = mats[7];
		}

		private void AssignRoofDarkDestruction(Material[] mats)
		{
			roofDarkDestructionblack = mats[0];
			roofDarkDestructionblue = mats[1];
			roofDarkDestructiongreen = mats[2];
			roofDarkDestructionorange = mats[3];
			roofDarkDestructionpurple = mats[4];
			roofDarkDestructionred = mats[5];
			roofDarkDestructionwhite = mats[6];
			roofDarkDestructionyellow = mats[7];
		}

		private AssetBundle GetAssetBundleFromResources(string filename)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().SingleOrDefault((string str) => str.EndsWith(filename, StringComparison.OrdinalIgnoreCase));
			if (string.IsNullOrEmpty(text))
			{
				Debug.LogError((object)("Embedded asset bundle not found: " + filename));
				return null;
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				Debug.LogError((object)("Could not open resource stream for: " + text));
				return null;
			}
			AssetBundle val = AssetBundle.LoadFromStream(stream);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)("Failed to load AssetBundle from resource: " + text));
			}
			return val;
		}
	}
	public class ShaderReplacment
	{
		public static List<GameObject> prefabsToReplaceShader = new List<GameObject>();

		public static List<Material> materialsInPrefabs = new List<Material>();

		public string[] shaderlist = new string[49]
		{
			"Custom/AlphaParticle", "Custom/Blob", "Custom/Bonemass", "Custom/Clouds", "Custom/Creature", "Custom/Decal", "Custom/Distortion", "Custom/Flow", "Custom/FlowOpaque", "Custom/Grass",
			"Custom/GuiScroll", "Custom/Heightmap", "Custom/icon", "Custom/InteriorSide", "Custom/LitGui", "Custom/LitParticles", "Custom/mapshader", "Custom/ParticleDecal", "Custom/Piece", "Custom/Player",
			"Custom/Rug", "Custom/ShadowBlob", "Custom/SkyboxProcedural", "Custom/SkyObject", "Custom/StaticRock", "Custom/Tar", "Custom/Trilinearmap", "Custom/UI/BGBlur", "Custom/Vegetation", "Custom/Water",
			"Custom/WaterBottom", "Custom/WaterMask", "Custom/Yggdrasil", "Custom/Yggdrasil/root", "Hidden/BlitCopyHDRTonemap", "Hidden/Dof/DepthOfFieldHdr", "Hidden/Dof/DX11Dof", "Hidden/Internal-Loading", "Hidden/Internal-UIRDefaultWorld", "Hidden/SimpleClear",
			"Hidden/SunShaftsComposite", "Lux Lit Particles/ Bumped", "Lux Lit Particles/ Tess Bumped", "Particles/Standard Surface2", "Particles/Standard Unlit2", "Standard TwoSided", "ToonDeferredShading2017", "Unlit/DepthWrite", "Unlit/Lighting"
		};

		public static List<Shader> shaders = new List<Shader>();

		private static readonly HashSet<Shader> CachedShaders = new HashSet<Shader>();

		public static bool debug = true;

		public static void ReplaceMaterial(Material material)
		{
			materialsInPrefabs.Add(material);
		}

		public static Shader findShader(string name)
		{
			Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
			if (array.Length == 0)
			{
				Debug.LogWarning((object)"SHADER LIST IS EMPTY!");
				return null;
			}
			if (debug)
			{
			}
			return shaders.Find((Shader x) => ((Object)x).name == name);
		}

		public static Shader GetShaderByName(string name)
		{
			return shaders.Find((Shader x) => ((Object)x).name == name.Trim());
		}

		public static void debugShaderList(List<Shader> shadersRes)
		{
			foreach (Shader shadersRe in shadersRes)
			{
				Debug.LogWarning((object)("SHADER NAME IS: " + ((Object)shadersRe).name));
			}
			debug = false;
		}

		public static void Replace(GameObject gameObject)
		{
			prefabsToReplaceShader.Add(gameObject);
			GetMaterialsInPrefab(gameObject);
		}

		public static void GetMaterialsInPrefab(GameObject gameObject)
		{
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					continue;
				}
				Material[] array2 = sharedMaterials;
				foreach (Material val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						materialsInPrefabs.Add(val2);
					}
				}
			}
		}

		public static void getMeShaders()
		{
			AssetBundle[] array = Resources.FindObjectsOfTypeAll<AssetBundle>();
			AssetBundle[] array2 = array;
			foreach (AssetBundle val in array2)
			{
				IEnumerable<Shader> enumerable3;
				try
				{
					IEnumerable<Shader> enumerable2;
					if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val))
					{
						IEnumerable<Shader> enumerable = val.LoadAllAssets<Shader>();
						enumerable2 = enumerable;
					}
					else
					{
						enumerable2 = from shader in ((IEnumerable<string>)val.GetAllAssetNames()).Select((Func<string, Shader>)val.LoadAsset<Shader>)
							where (Object)(object)shader != (Object)null
							select shader;
					}
					enumerable3 = enumerable2;
				}
				catch (Exception)
				{
					continue;
				}
				if (enumerable3 == null)
				{
					continue;
				}
				foreach (Shader item in enumerable3)
				{
					CachedShaders.Add(item);
				}
			}
		}

		public static void runMaterialFix()
		{
			getMeShaders();
			shaders.AddRange(CachedShaders);
			foreach (Material materialsInPrefab in materialsInPrefabs)
			{
				Shader shader = materialsInPrefab.shader;
				if (!((Object)(object)shader == (Object)null))
				{
					string name = ((Object)shader).name;
					if (!(name == "Standard") && name.Contains("Balrond"))
					{
						setProperValue(materialsInPrefab, name);
					}
				}
			}
		}

		private static void setProperValue(Material material, string shaderName)
		{
			string name = shaderName.Replace("Balrond", "Custom");
			name = checkNaming(name);
			Shader shaderByName = GetShaderByName(name);
			if ((Object)(object)shaderByName == (Object)null)
			{
				Debug.LogWarning((object)("Shader not found " + name));
			}
			else
			{
				material.shader = shaderByName;
			}
		}

		private static string checkNaming(string name)
		{
			string result = name;
			if (name.Contains("Bumped"))
			{
				result = name.Replace("Custom", "Lux Lit Particles");
			}
			if (name.Contains("Tess Bumped"))
			{
				result = name.Replace("Custom", "Lux Lit Particles");
			}
			if (name.Contains("Standard Surface"))
			{
				result = name.Replace("Custom", "Particles");
				result = result.Replace("Standard Surface2", "Standard Surface");
			}
			if (name.Contains("Standard Unlit"))
			{
				result = name.Replace("Custom", "Particles");
				result = result.Replace("Standard Unlit", "Standard Unlit2");
				result = result.Replace("Standard Unlit22", "Standard Unlit2");
			}
			return result;
		}
	}
	[Serializable]
	public class BannerColorizer : MonoBehaviour, Hoverable, Interactable
	{
		private const string ZdoColorKey = "colorizerSet";

		private const string ZdoActiveKey = "colorizerIsActive";

		private static readonly HashSet<string> RoofPrefabNames = new HashSet<string>(StringComparer.Ordinal) { "darkwood_roof_icorner", "darkwood_roof_icorner_45", "darkwood_roof_ocorner", "darkwood_roof_ocorner_45", "darkwood_roof_top", "darkwood_roof_top_45", "darkwood_roof_45", "darkwood_roof" };

		private static readonly Dictionary<string, string> DefaultSkinByPrefab = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			{ "darkwood_roof_icorner", "black" },
			{ "darkwood_roof_icorner_45", "black" },
			{ "darkwood_roof_ocorner", "black" },
			{ "darkwood_roof_ocorner_45", "black" },
			{ "darkwood_roof_top", "black" },
			{ "darkwood_roof_top_45", "black" },
			{ "darkwood_roof_45", "black" },
			{ "darkwood_roof", "black" },
			{ "crystal_wall_1x1", "white" },
			{ "piece_banner01", "black" },
			{ "piece_banner02", "blue" },
			{ "piece_banner03", "red" },
			{ "piece_banner04", "red" },
			{ "piece_banner05", "green" },
			{ "piece_banner06", "blue" },
			{ "piece_banner07", "blue" },
			{ "piece_banner08", "yellow" },
			{ "piece_banner09", "purple" },
			{ "piece_banner10", "orange" },
			{ "piece_banner11", "white" },
			{ "piece_cloth_hanging_door", "red" },
			{ "piece_cloth_hanging_door_blue", "blue" },
			{ "piece_cloth_hanging_door_blue2", "blue" },
			{ "jute_carpet", "red" },
			{ "jute_carpet_blue", "blue" }
		};

		private ZNetView m_zview;

		private Piece m_piece;

		public List<ColorizerPack> m_packs;

		private string skinName = "";

		public string defaultSkinName = "";

		public static ModResourceLoader modResourceLoader = Launch.modResourceLoader;

		private List<ColorizerPack> colorizerPacks = new List<ColorizerPack>();

		private ColorizerPack m_colorizerPack;

		public List<MeshRenderer> banner = new List<MeshRenderer>();

		private List<MeshRenderer> m_destruction = new List<MeshRenderer>();

		private MeshRenderer main;

		private string m_useItemText = "Add dye";

		private List<ColorizerPack> colorizerPacksFull => Launch.colorizerPacks;

		private void Awake()
		{
			if (!validatePrefab())
			{
				Debug.LogWarning((object)("I should not be randomized: " + ((Object)((Component)this).gameObject).name));
				return;
			}
			filterPacks();
			m_zview = ((Component)this).GetComponent<ZNetView>();
			m_piece = ((Component)this).GetComponent<Piece>();
			if ((Object)(object)m_zview == (Object)null || !m_zview.IsValid() || m_zview.GetZDO() == null)
			{
				return;
			}
			m_zview.Register<string>("RPC_Paint", (Action<long, string>)RPC_Paint);
			setDefaulDyeName();
			if (!setupColorizer())
			{
				Debug.LogWarning((object)("Unable to setup colorizer for: " + ((Object)((Component)this).gameObject).name));
				return;
			}
			if (m_packs == null || m_packs.Count == 0)
			{
				Debug.LogWarning((object)("Material list is empty for: " + ((Object)((Component)this).gameObject).name));
			}
			bool dye = IsColorizerActive();
			setDye(dye);
		}

		public string GetHoverText()
		{
			string text = (((Object)(object)m_piece != (Object)null) ? m_piece.m_name : ((Object)((Component)this).gameObject).name);
			return Localization.instance.Localize(text + "\n[<color=yellow><b>1-8</b></color>] " + m_useItemText + "\n[Current dye] " + skinName + "\n[<color=yellow>Default dye</color>] " + defaultSkinName);
		}

		public string GetHoverName()
		{
			return ((Object)(object)m_piece != (Object)null) ? m_piece.m_name : ((Object)((Component)this).gameObject).name;
		}

		public bool Interact(Humanoid character, bool repeat, bool alt)
		{
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)user == (Object)null || item == null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return true;
			}
			ColorizerPack colorPackByItemData = getColorPackByItemData(item);
			if (colorPackByItemData == null)
			{
				((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null);
				return false;
			}
			if (skinName == colorPackByItemData.skin)
			{
				((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null);
				return false;
			}
			((Character)user).Message((MessageType)2, "$msg_added " + item.m_shared.m_name, 0, (Sprite)null);
			user.GetInventory().RemoveItem(item.m_shared.m_name, 1, -1, true);
			Paint(colorPackByItemData.skin);
			return true;
		}

		private void Paint(string dyeName)
		{
			if (!((Object)(object)m_zview == (Object)null) && m_zview.IsValid())
			{
				m_zview.InvokeRPC(ZNetView.Everybody, "RPC_Paint", new object[1] { dyeName });
			}
		}

		private void RPC_Paint(long caller, string dyeName)
		{
			if (string.IsNullOrWhiteSpace(dyeName))
			{
				dyeName = defaultSkinName;
			}
			setColorizerId(dyeName);
			ColorizerPack colorizerPack = findDyeByName(dyeName);
			if (colorizerPack == null)
			{
				Debug.LogWarning((object)("Colorizer pack not found for dye: " + dyeName + " on " + ((Object)((Component)this).gameObject).name));
			}
			else
			{
				useDye(colorizerPack);
			}
		}

		public void filterPacks()
		{
			colorizerPacks.Clear();
			string text = editZnetName(((Object)this).name);
			List<ColorizerPack> list = colorizerPacksFull;
			if (list == null)
			{
				return;
			}
			foreach (ColorizerPack item in list)
			{
				if (item != null && text == item.buildPieceName)
				{
					colorizerPacks.Add(item);
				}
			}
		}

		private void setColorizerId(string id)
		{
			if ((Object)(object)m_zview != (Object)null && m_zview.IsValid() && m_zview.m_zdo != null)
			{
				m_zview.m_zdo.Set("colorizerSet", id);
				m_zview.m_zdo.Set("colorizerIsActive", true);
			}
		}

		private bool IsColorizerActive()
		{
			if ((Object)(object)m_zview == (Object)null || m_zview.m_zdo == null)
			{
				return false;
			}
			return m_zview.m_zdo.GetBool("colorizerIsActive", false);
		}

		private bool validatePrefab()
		{
			string value = editZnetName(((Object)((Component)this).gameObject).name);
			return Launch.buildPieceNames.Contains(value);
		}

		private void setDefaulDyeName()
		{
			string key = editZnetName(((Object)((Component)this).gameObject).name);
			if (DefaultSkinByPrefab.TryGetValue(key, out var value))
			{
				defaultSkinName = value;
			}
			else
			{
				defaultSkinName = "black";
			}
		}

		private string editZnetName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			value = value.Replace("(Clone)", "");
			int num = value.IndexOf("(");
			if (num >= 0)
			{
				value = value.Substring(0, num);
			}
			return value.Trim();
		}

		private void setDye(bool isColorizerActive)
		{
			string @string = defaultSkinName;
			if (isColorizerActive && (Object)(object)m_zview != (Object)null && m_zview.m_zdo != null)
			{
				@string = m_zview.m_zdo.GetString("colorizerSet", "");
			}
			if (string.IsNullOrWhiteSpace(@string))
			{
				@string = defaultSkinName;
			}
			Paint(@string);
		}

		private ColorizerPack findDyeByName(string name)
		{
			string text = editZnetName(((Object)this).name);
			foreach (ColorizerPack colorizerPack in colorizerPacks)
			{
				if (colorizerPack != null && name == colorizerPack.skin && text == colorizerPack.buildPieceName)
				{
					return colorizerPack;
				}
			}
			return null;
		}

		private ColorizerPack getColorPackByItemData(ItemData itemData)
		{
			if (itemData == null || (Object)(object)itemData.m_dropPrefab == (Object)null)
			{
				return null;
			}
			string name = ((Object)itemData.m_dropPrefab).name;
			foreach (ColorizerPack colorizerPack in colorizerPacks)
			{
				if (colorizerPack != null && (Object)(object)colorizerPack.dyeItem != (Object)null && name == ((Object)colorizerPack.dyeItem).name)
				{
					return colorizerPack;
				}
			}
			return null;
		}

		private void useDye(ColorizerPack colorizerPack)
		{
			if (colorizerPack != null)
			{
				ApplyMaterialList(banner, colorizerPack.body);
				skinName = colorizerPack.skin;
				m_colorizerPack = colorizerPack;
				if ((Object)(object)main != (Object)null && (Object)(object)colorizerPack.rugmain != (Object)null)
				{
					ApplyMaterial(main, colorizerPack.rugmain);
				}
				if ((Object)(object)colorizerPack.rugdestruction != (Object)null)
				{
					ApplyMaterialList(m_destruction, colorizerPack.rugdestruction);
				}
			}
		}

		private bool setupColorizer()
		{
			banner.Clear();
			m_destruction.Clear();
			main = null;
			string prefabName = editZnetName(((Object)((Component)this).gameObject).name);
			m_packs = colorizerPacks.FindAll((ColorizerPack x) => x != null && x.buildPieceName == prefabName);
			if (RoofPrefabNames.Contains(prefabName))
			{
				Transform val = ((Component)this).transform.Find("New");
				Transform source = ((Component)this).transform.Find("Worn");
				Transform source2 = ((Component)this).transform.Find("Broken");
				Transform source3 = ((Component)this).transform.Find("Destruction");
				if ((Object)(object)val != (Object)null)
				{
					AddRendererFromChild(val, 0, banner);
					AddRendererFromChild(val, 1, banner);
				}
				AddRenderersFromTransform(source, m_destruction);
				AddRenderersFromTransform(source2, m_destruction);
				AddRenderersFromTransform(source3, m_destruction);
				return banner.Count > 0;
			}
			switch (prefabName)
			{
			case "crystal_wall_1x1":
			{
				Transform val2 = ((Component)this).transform.Find("New");
				if ((Object)(object)val2 != (Object)null)
				{
					AddRendererFromChild(val2, 0, banner);
					AddRendererFromChild(val2, 1, banner);
				}
				return banner.Count > 0;
			}
			case "piece_banner01":
			case "piece_banner02":
			case "piece_banner03":
			case "piece_banner04":
			case "piece_banner05":
			case "piece_banner06":
			case "piece_banner07":
			case "piece_banner08":
			case "piece_banner09":
			case "piece_banner10":
			case "piece_banner11":
				AddRendererFromPath("default", banner);
				return banner.Count > 0;
			case "piece_cloth_hanging_door":
				AddRendererFromPath("new/cloth", banner);
				return banner.Count > 0;
			case "piece_cloth_hanging_door_blue":
			{
				Transform val7 = ((Component)this).transform.Find("new");
				if ((Object)(object)val7 != (Object)null)
				{
					AddRendererFromChild(val7, 0, banner);
					AddRendererFromChild(val7, 1, banner);
				}
				return banner.Count > 0;
			}
			case "piece_cloth_hanging_door_blue2":
			{
				Transform val3 = ((Component)this).transform.Find("new");
				Transform val4 = ((Component)this).transform.Find("worn");
				Transform val5 = ((Component)this).transform.Find("broken");
				Transform val6 = ((Component)this).transform.Find("destruction");
				if ((Object)(object)val3 != (Object)null)
				{
					AddRendererFromChild(val3, 1, banner);
					AddRendererFromChild(val3, 2, banner);
				}
				if ((Object)(object)val4 != (Object)null)
				{
					AddRendererFromChild(val4, 1, banner);
					AddRendererFromChild(val4, 2, banner);
				}
				if ((Object)(object)val5 != (Object)null)
				{
					AddRendererFromChild(val5, 1, banner);
					AddRendererFromChild(val5, 2, banner);
				}
				if ((Object)(object)val6 != (Object)null)
				{
					AddRendererFromChild(val6, 0, banner);
				}
				return banner.Count > 0;
			}
			case "jute_carpet":
			case "jute_carpet_blue":
			{
				main = GetRendererFromChildIndex(((Component)this).transform, 1);
				AddRendererFromRootChildIndex(2, banner);
				AddRendererFromRootChildIndex(3, banner);
				Transform source4 = ((Component)this).transform.Find("destruction");
				AddRenderersFromTransform(source4, m_destruction);
				return banner.Count > 0 || (Object)(object)main != (Object)null;
			}
			default:
				return false;
			}
		}

		private void ApplyMaterialList(List<MeshRenderer> renderers, Material sourceMaterial)
		{
			if (renderers == null || (Object)(object)sourceMaterial == (Object)null)
			{
				return;
			}
			foreach (MeshRenderer renderer in renderers)
			{
				ApplyMaterial(renderer, sourceMaterial);
			}
		}

		private void ApplyMaterial(MeshRenderer renderer, Material sourceMaterial)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (!((Object)(object)renderer == (Object)null) && !((Object)(object)sourceMaterial == (Object)null))
			{
				Material sharedMaterial = (((Renderer)renderer).material = new Material(sourceMaterial));
				((Renderer)renderer).sharedMaterial = sharedMaterial;
			}
		}

		private void AddRendererFromPath(string path, List<MeshRenderer> target)
		{
			Transform val = ((Component)this).transform.Find(path);
			if (!((Object)(object)val == (Object)null))
			{
				MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					target.Add(component);
				}
			}
		}

		private void AddRendererFromChild(Transform parent, int childIndex, List<MeshRenderer> target)
		{
			if (!((Object)(object)parent == (Object)null) && childIndex >= 0 && childIndex < parent.childCount)
			{
				MeshRenderer component = ((Component)parent.GetChild(childIndex)).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					target.Add(component);
				}
			}
		}

		private void AddRendererFromRootChildIndex(int childIndex, List<MeshRenderer> target)
		{
			MeshRenderer rendererFromChildIndex = GetRendererFromChildIndex(((Component)this).transform, childIndex);
			if ((Object)(object)rendererFromChildIndex != (Object)null)
			{
				target.Add(rendererFromChildIndex);
			}
		}

		private MeshRenderer GetRendererFromChildIndex(Transform parent, int childIndex)
		{
			if ((Object)(object)parent == (Object)null || childIndex < 0 || childIndex >= parent.childCount)
			{
				return null;
			}
			return ((Component)parent.GetChild(childIndex)).GetComponent<MeshRenderer>();
		}

		private void AddRenderersFromTransform(Transform source, List<MeshRenderer> target)
		{
			if (!((Object)(object)source == (Object)null))
			{
				MeshRenderer[] componentsInChildren = ((Component)source).GetComponentsInChildren<MeshRenderer>();
				if (componentsInChildren != null && componentsInChildren.Length != 0)
				{
					target.AddRange(componentsInChildren);
				}
			}
		}
	}
	public class ItemSetBuilder
	{
		public List<GameObject> prefabs = new List<GameObject>();

		public ModResourceLoader modResourceLoader = null;

		public static List<ColorizerPack> colorizerPacks = new List<ColorizerPack>();

		public static List<ColorizerPack> createColorPacks(ModResourceLoader modResourceLoader)
		{
			if (modResourceLoader == null)
			{
				Debug.LogError((object)"ItemSetBuilder.createColorPacks: modResourceLoader is null.");
				return colorizerPacks;
			}
			colorizerPacks.Clear();
			Dictionary<string, GameObject> dyeLookup = BuildDyeLookup(modResourceLoader);
			AddSimpleSet(modResourceLoader, dyeLookup, "crystal_wall_1x1", (Material[])(object)new Material[8] { modResourceLoader.crystal01black, modResourceLoader.crystal01blue, modResourceLoader.crystal01green, modResourceLoader.crystal01orange, modResourceLoader.crystal01purple, modResourceLoader.crystal01red, modResourceLoader.crystal01white, modResourceLoader.crystal01yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner01", (Material[])(object)new Material[8] { modResourceLoader.banner01black, modResourceLoader.banner01blue, modResourceLoader.banner01green, modResourceLoader.banner01orange, modResourceLoader.banner01purple, modResourceLoader.banner01red, modResourceLoader.banner01white, modResourceLoader.banner01yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner02", (Material[])(object)new Material[8] { modResourceLoader.banner02black, modResourceLoader.banner02blue, modResourceLoader.banner02green, modResourceLoader.banner02orange, modResourceLoader.banner02purple, modResourceLoader.banner02red, modResourceLoader.banner02white, modResourceLoader.banner02yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner03", (Material[])(object)new Material[8] { modResourceLoader.banner03black, modResourceLoader.banner03blue, modResourceLoader.banner03green, modResourceLoader.banner03orange, modResourceLoader.banner03purple, modResourceLoader.banner03red, modResourceLoader.banner03white, modResourceLoader.banner03yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner04", (Material[])(object)new Material[8] { modResourceLoader.banner04black, modResourceLoader.banner04blue, modResourceLoader.banner04green, modResourceLoader.banner04orange, modResourceLoader.banner04purple, modResourceLoader.banner04red, modResourceLoader.banner04white, modResourceLoader.banner04yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner05", (Material[])(object)new Material[8] { modResourceLoader.banner05black, modResourceLoader.banner05blue, modResourceLoader.banner05green, modResourceLoader.banner05orange, modResourceLoader.banner05purple, modResourceLoader.banner05red, modResourceLoader.banner05white, modResourceLoader.banner05yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner06", (Material[])(object)new Material[8] { modResourceLoader.banner06black, modResourceLoader.banner06blue, modResourceLoader.banner06green, modResourceLoader.banner06orange, modResourceLoader.banner06purple, modResourceLoader.banner06red, modResourceLoader.banner06white, modResourceLoader.banner06yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner07", (Material[])(object)new Material[8] { modResourceLoader.banner07black, modResourceLoader.banner07blue, modResourceLoader.banner07green, modResourceLoader.banner07orange, modResourceLoader.banner07purple, modResourceLoader.banner07red, modResourceLoader.banner07white, modResourceLoader.banner07yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner08", (Material[])(object)new Material[8] { modResourceLoader.banner08black, modResourceLoader.banner08blue, modResourceLoader.banner08green, modResourceLoader.banner08orange, modResourceLoader.banner08purple, modResourceLoader.banner08red, modResourceLoader.banner08white, modResourceLoader.banner08yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner09", (Material[])(object)new Material[8] { modResourceLoader.banner09black, modResourceLoader.banner09blue, modResourceLoader.banner09green, modResourceLoader.banner09orange, modResourceLoader.banner09purple, modResourceLoader.banner09red, modResourceLoader.banner09white, modResourceLoader.banner09yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner10", (Material[])(object)new Material[8] { modResourceLoader.banner10black, modResourceLoader.banner10blue, modResourceLoader.banner10green, modResourceLoader.banner10orange, modResourceLoader.banner10purple, modResourceLoader.banner10red, modResourceLoader.banner10white, modResourceLoader.banner10yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_banner11", (Material[])(object)new Material[8] { modResourceLoader.banner11black, modResourceLoader.banner11blue, modResourceLoader.banner11green, modResourceLoader.banner11orange, modResourceLoader.banner11purple, modResourceLoader.banner11red, modResourceLoader.banner11white, modResourceLoader.banner11yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_cloth_hanging_door", (Material[])(object)new Material[8] { modResourceLoader.bannerHangingblack, modResourceLoader.bannerHangingblue, modResourceLoader.bannerHanginggreen, modResourceLoader.bannerHangingorange, modResourceLoader.bannerHangingpurple, modResourceLoader.bannerHangingred, modResourceLoader.bannerHangingwhite, modResourceLoader.bannerHangingyellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_cloth_hanging_door_blue", (Material[])(object)new Material[8] { modResourceLoader.bannerHanging2black, modResourceLoader.bannerHanging2blue, modResourceLoader.bannerHanging2green, modResourceLoader.bannerHanging2orange, modResourceLoader.bannerHanging2purple, modResourceLoader.bannerHanging2red, modResourceLoader.bannerHanging2white, modResourceLoader.bannerHanging2yellow });
			AddSimpleSet(modResourceLoader, dyeLookup, "piece_cloth_hanging_door_blue2", (Material[])(object)new Material[8] { modResourceLoader.bannerHanging3black, modResourceLoader.bannerHanging3blue, modResourceLoader.bannerHanging3green, modResourceLoader.bannerHanging3orange, modResourceLoader.bannerHanging3purple, modResourceLoader.bannerHanging3red, modResourceLoader.bannerHanging3white, modResourceLoader.bannerHanging3yellow });
			AddComplexSet(modResourceLoader, dyeLookup, "jute_carpet", (Material[])(object)new Material[8] { modResourceLoader.juteCarpetblack, modResourceLoader.juteCarpetblue, modResourceLoader.juteCarpetgreen, modResourceLoader.juteCarpetorange, modResourceLoader.juteCarpetpurple, modResourceLoader.juteCarpetred, modResourceLoader.juteCarpetwhite, modResourceLoader.juteCarpetyellow }, (Material[])(object)new Material[8] { modResourceLoader.juteCarpetMainblack, modResourceLoader.juteCarpetMainblue, modResourceLoader.juteCarpetMaingreen, modResourceLoader.juteCarpetMainorange, modResourceLoader.juteCarpetMainpurple, modResourceLoader.juteCarpetMainred, modResourceLoader.juteCarpetMainwhite, modResourceLoader.juteCarpetMainyellow }, (Material[])(object)new Material[8] { modResourceLoader.juteCarpetDestructionblack, modResourceLoader.juteCarpetDestructionblue, modResourceLoader.juteCarpetDestructiongreen, modResourceLoader.juteCarpetDestructionorange, modResourceLoader.juteCarpetDestructionpurple, modResourceLoader.juteCarpetDestructionred, modResourceLoader.juteCarpetDestructionwhite, modResourceLoader.juteCarpetDestructionyellow });
			AddComplexSet(modResourceLoader, dyeLookup, "jute_carpet_blue", (Material[])(object)new Material[8] { modResourceLoader.juteCarpet2black, modResourceLoader.juteCarpet2blue, modResourceLoader.juteCarpet2green, modResourceLoader.juteCarpet2orange, modResourceLoader.juteCarpet2purple, modResourceLoader.juteCarpet2red, modResourceLoader.juteCarpet2white, modResourceLoader.juteCarpet2yellow }, (Material[])(object)new Material[8] { modResourceLoader.juteCarpetMain2black, modResourceLoader.juteCarpetMain2blue, modResourceLoader.juteCarpetMain2green, modResourceLoader.juteCarpetMain2orange, modResourceLoader.juteCarpetMain2purple, modResourceLoader.juteCarpetMain2red, modResourceLoader.juteCarpetMain2white, modResourceLoader.juteCarpetMain2yellow }, (Material[])(object)new Material[8] { modResourceLoader.juteCarpetDestruction2black, modResourceLoader.juteCarpetDestruction2blue, modResourceLoader.juteCarpetDestruction2green, modResourceLoader.juteCarpetDestruction2orange, modResourceLoader.juteCarpetDestruction2purple, modResourceLoader.juteCarpetDestruction2red, modResourceLoader.juteCarpetDestruction2white, modResourceLoader.juteCarpetDestruction2yellow });
			string[] array = new string[8] { "darkwood_roof_icorner", "darkwood_roof_icorner_45", "darkwood_roof_ocorner", "darkwood_roof_ocorner_45", "darkwood_roof_top", "darkwood_roof_top_45", "darkwood_roof_45", "darkwood_roof" };
			Material[] array2 = (Material[])(object)new Material[8] { modResourceLoader.roofDarkMain2black, modResourceLoader.roofDarkMain2blue, modResourceLoader.roofDarkMain2green, modResourceLoader.roofDarkMain2orange, modResourceLoader.roofDarkMain2purple, modResourceLoader.roofDarkMain2red, modResourceLoader.roofDarkMain2white, modResourceLoader.roofDarkMain2yellow };
			Material[] destructionMaterials = (Material[])(object)new Material[8] { modResourceLoader.roofDarkDestructionblack, modResourceLoader.roofDarkDestructionblue, modResourceLoader.roofDarkDestructiongreen, modResourceLoader.roofDarkDestructionorange, modResourceLoader.roofDarkDestructionpurple, modResourceLoader.roofDarkDestructionred, modResourceLoader.roofDarkDestructionwhite, modResourceLoader.roofDarkDestructionyellow };
			for (int i = 0; i < array.Length; i++)
			{
				AddComplexSet(modResourceLoader, dyeLookup, array[i], array2, array2, destructionMaterials);
			}
			return colorizerPacks;
		}

		private static Dictionary<string, GameObject> BuildDyeLookup(ModResourceLoader modResourceLoader)
		{
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);
			if (modResourceLoader.items == null)
			{
				Debug.LogWarning((object)"ItemSetBuilder: modResourceLoader.items is null.");
				return dictionary;
			}
			foreach (GameObject item in modResourceLoader.items)
			{
				if (!((Object)(object)item == (Object)null) && !dictionary.ContainsKey(((Object)item).name))
				{
					dictionary.Add(((Object)item).name, item);
				}
			}
			return dictionary;
		}

		private static void AddSimpleSet(ModResourceLoader modResourceLoader, Dictionary<string, GameObject> dyeLookup, string targetName, Material[] bodyMaterials)
		{
			for (int i = 0; i < ModResourceLoader.colorNames.Length; i++)
			{
				GameObject dyeItem = GetDyeItem(dyeLookup, ModResourceLoader.prefabNames[i]);
				buildPack(bodyMaterials[i], dyeItem, targetName, ModResourceLoader.colorNames[i]);
			}
		}

		private static void AddComplexSet(ModResourceLoader modResourceLoader, Dictionary<string, GameObject> dyeLookup, string targetName, Material[] bodyMaterials, Material[] rugMaterials, Material[] destructionMaterials)
		{
			for (int i = 0; i < ModResourceLoader.colorNames.Length; i++)
			{
				GameObject dyeItem = GetDyeItem(dyeLookup, ModResourceLoader.prefabNames[i]);
				buildPack(bodyMaterials[i], dyeItem, targetName, ModResourceLoader.colorNames[i], rugMaterials[i], destructionMaterials[i]);
			}
		}

		private static GameObject GetDyeItem(Dictionary<string, GameObject> dyeLookup, string dyePrefabName)
		{
			if (dyeLookup.TryGetValue(dyePrefabName, out var value))
			{
				return value;
			}
			Debug.LogWarning((object)("ItemSetBuilder: dye item not found: " + dyePrefabName));
			return null;
		}

		private static void buildPack(Material body, GameObject dyeItem, string name, string skin, Material rug = null, Material rugdestruction = null)
		{
			colorizerPacks.Add(new ColorizerPack(body, name, dyeItem, skin, rug, rugdestruction));
		}

		public void setupColorizer(GameObject piece)
		{
			if ((Object)(object)piece == (Object)null)
			{
				Debug.LogWarning((object)"ItemSetBuilder.setupColorizer: piece is null.");
				return;
			}
			BannerColorizer bannerColorizer = piece.GetComponent<BannerColorizer>();
			if ((Object)(object)bannerColorizer == (Object)null)
			{
				bannerColorizer = piece.AddComponent<BannerColorizer>();
			}
			bannerColorizer.filterPacks();
		}
	}
	[Serializable]
	public class ColorizerPack
	{
		public Material body;

		public string buildPieceName;

		public GameObject dyeItem;

		public string skin;

		public Material rugmain;

		public Material rugdestruction;

		public ColorizerPack(Material body, string buildPieceName, GameObject dyeItem, string skin, Material rugmain = null, Material rugdestruction = null)
		{
			this.buildPieceName = buildPieceName;
			this.body = body;
			this.skin = skin;
			this.dyeItem = dyeItem;
			this.rugmain = rugmain;
			this.rugdestruction = rugdestruction;
		}
	}
	public class DatabaseAddMethods
	{
		public void AddItems(List<GameObject> items)
		{
			foreach (GameObject item in items)
			{
				AddItem(item);
			}
		}

		public void AddRecipes(List<Recipe> recipes)
		{
			foreach (Recipe recipe in recipes)
			{
				AddRecipe(recipe);
			}
		}

		public void AddStatuseffects(List<StatusEffect> statusEffects)
		{
			foreach (StatusEffect statusEffect in statusEffects)
			{
				AddStatus(statusEffect);
			}
		}

		private bool IsObjectDBValid()
		{
			return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null;
		}

		private void AddStatus(StatusEffect status)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			if ((Object)(object)status != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.GetStatusEffect(((object)status).GetHashCode()) == (Object)null)
				{
					ObjectDB.instance.m_StatusEffects.Add(status);
				}
			}
			else
			{
				Debug.LogError((object)("BalrondBannerColorizer:  " + ((Object)status).name + " - Status not found"));
			}
		}

		private void AddRecipe(Recipe recipe)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			if ((Object)(object)recipe != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.GetRecipe(recipe.m_item.m_itemData) == (Object)null)
				{
					ObjectDB.instance.m_recipes.Add(recipe);
				}
			}
			else
			{
				Debug.LogError((object)("BalrondBannerColorizer:  " + ((Object)recipe).name + " - Recipe not found"));
			}
		}

		private void AddItem(GameObject newPrefab)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			ItemDrop component = newPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)newPrefab).name) == (Object)null)
				{
					ObjectDB.instance.m_items.Add(newPrefab);
					Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ObjectDB.instance);
					dictionary[((Object)newPrefab).name.GetHashCode()] = newPrefab;
				}
			}
			else
			{
				Debug.LogError((object)("BalrondBannerColorizer:  " + ((Object)newPrefab).name + " - ItemDrop not found on prefab"));
			}
		}
	}
	public class JsonLoader
	{
		public string defaultPath = string.Empty;

		public void loadJson()
		{
			LoadTranslations();
			justDefaultPath();
		}

		public void justDefaultPath()
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondBannerColorizer-translation/");
			defaultPath = text;
		}

		public void createDefaultPath()
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondBannerColorizer-translation/");
			if (!Directory.Exists(text))
			{
				CreateFolder(text);
			}
			else
			{
				Debug.Log((object)("BalrondBannerColorizer: Folder already exists: " + text));
			}
			defaultPath = text;
		}

		private string[] jsonFilePath(string folderName, string extension)
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondBannerColorizer-translation/");
			if (!Directory.Exists(text))
			{
				CreateFolder(text);
			}
			else
			{
				Debug.Log((object)("BalrondBannerColorizer: Folder already exists: " + text));
			}
			string[] files = Directory.GetFiles(text, extension);
			Debug.Log((object)("BalrondBannerColorizer:" + folderName + " Json Files Found: " + files.Length));
			return files;
		}

		private static void CreateFolder(string path)
		{
			try
			{
				Directory.CreateDirectory(path);
				Debug.Log((object)"BalrondBannerColorizer: Folder created successfully.");
			}
			catch (Exception ex)
			{
				Debug.Log((object)("BalrondBannerColorizer: Error creating folder: " + ex.Message));
			}
		}

		private void LoadTranslations()
		{
			int num = 0;
			string[] array = jsonFilePath("Translation", "*.json");
			foreach (string text in array)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
				string json = File.ReadAllText(text);
				JsonData jsonData = JsonMapper.ToObject(json);
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				foreach (string key in jsonData.Keys)
				{
					dictionary[key] = jsonData[key].ToString();
				}
				if (dictionary != null)
				{
					BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary);
					Debug.Log((object)("BalrondBannerColorizer: Json Files Language: " + fileNameWithoutExtension));
					num++;
				}
				else
				{
					Debug.LogError((object)("BalrondBannerColorizer: Loading FAILED file: " + text));
				}
			}
			Debug.Log((object)("BalrondBannerColorizer: Translation JsonFiles Loaded: " + num));
		}
	}
	[BepInPlugin("balrond.astafaraios.BalrondBannerColorizer", "BalrondBannerColorizer", "1.0.7")]
	public class Launch : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		public static class Object_CopyOtherDB_Path
		{
			public static void Postfix()
			{
				SetupObjectDbContent();
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		public static class ObjectDB_Awake_Path
		{
			public static void Postfix()
			{
				SetupObjectDbContent();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ZNetScene_Awake_Path
		{
			public static void Prefix(ZNetScene __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					Debug.LogWarning((object)"BalrondBannerColorizer: No ZNetScene found");
					return;
				}
				AddMissingPrefabs(__instance);
				if (!hasSpawned)
				{
					SetupDyeTable(__instance);
					AddDyeTableToHammer(__instance);
					colorizerPacks = ItemSetBuilder.createColorPacks(modResourceLoader);
					SetupBuildPieceColorizers(__instance);
					if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
					{
						hasSpawned = true;
						return;
					}
					ShaderReplacment.runMaterialFix();
					hasSpawned = true;
				}
			}
		}

		private readonly Harmony harmony = new Harmony("balrond.astafaraios.BalrondBannerColorizer");

		public const string PluginGUID = "balrond.astafaraios.BalrondBannerColorizer";

		public const string PluginName = "BalrondBannerColorizer";

		public const string PluginVersion = "1.0.7";

		public static JsonLoader jsonLoader = new JsonLoader();

		public static ModResourceLoader modResourceLoader = new ModResourceLoader();

		public static DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods();

		public static ItemSetBuilder itemSetBuilder = new ItemSetBuilder();

		public static GameObject RootObject;

		public static GameObject PrefabContainer;

		public static List<ColorizerPack> colorizerPacks = new List<ColorizerPack>();

		public static bool hasSpawned = false;

		public static string[] buildPieceNames = new string[25]
		{
			"piece_banner01", "piece_banner02", "piece_banner03", "piece_banner04", "piece_banner05", "piece_banner06", "piece_banner07", "piece_banner08", "piece_banner09", "piece_banner10",
			"piece_banner11", "piece_cloth_hanging_door", "piece_cloth_hanging_door_blue", "piece_cloth_hanging_door_blue2", "jute_carpet", "jute_carpet_blue", "crystal_wall_1x1", "darkwood_roof_icorner", "darkwood_roof_icorner_45", "darkwood_roof_ocorner",
			"darkwood_roof_ocorner_45", "darkwood_roof_top", "darkwood_roof_top_45", "darkwood_roof_45", "darkwood_roof"
		};

		private static readonly Dictionary<string, Func<ModResourceLoader, Material>> DefaultTextureMap = new Dictionary<string, Func<ModResourceLoader, Material>>(StringComparer.Ordinal)
		{
			{
				"piece_banner08",
				(ModResourceLoader x) => x.banner08yellow
			},
			{
				"piece_banner05",
				(ModResourceLoader x) => x.banner05green
			},
			{
				"piece_banner07",
				(ModResourceLoader x) => x.banner07blue
			},
			{
				"piece_banner09",
				(ModResourceLoader x) => x.banner09purple
			},
			{
				"piece_banner10",
				(ModResourceLoader x) => x.banner10orange
			},
			{
				"piece_banner11",
				(ModResourceLoader x) => x.banner11white
			}
		};

		private void Awake()
		{
			jsonLoader.loadJson();
			createPrefabContainer();
			modResourceLoader.loadAssets();
			harmony.PatchAll();
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}

		public void createPrefabContainer()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			if (!((Object)(object)RootObject != (Object)null) || !((Object)(object)PrefabContainer != (Object)null))
			{
				RootObject = new GameObject("_ValheimReforgedRoot");
				Object.DontDestroyOnLoad((Object)(object)RootObject);
				PrefabContainer = new GameObject("Prefabs");
				PrefabContainer.transform.SetParent(RootObject.transform, false);
				PrefabContainer.SetActive(false);
			}
		}

		public static GameObject cloneMe(GameObject source, string name)
		{
			if ((Object)(object)source == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: cloneMe source is null");
				return null;
			}
			if ((Object)(object)PrefabContainer == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: PrefabContainer is null");
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(source, PrefabContainer.transform);
			((Object)val).name = name;
			return val;
		}

		private static bool IsObjectDBValid()
		{
			return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes != null && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null;
		}

		private static void SetupObjectDbContent()
		{
			if (IsObjectDBValid())
			{
				databaseAddMethods.AddItems(modResourceLoader.items);
				List<Recipe> recipes = createRecipesForDye(ObjectDB.instance.m_items);
				databaseAddMethods.AddRecipes(recipes);
			}
		}

		private static void AddMissingPrefabs(ZNetScene scene)
		{
			foreach (GameObject item in modResourceLoader.items)
			{
				if ((Object)(object)item != (Object)null && !scene.m_prefabs.Contains(item))
				{
					scene.m_prefabs.Add(item);
				}
			}
			if ((Object)(object)modResourceLoader.dyeTable != (Object)null && !scene.m_prefabs.Contains(modResourceLoader.dyeTable))
			{
				scene.m_prefabs.Add(modResourceLoader.dyeTable);
			}
		}

		private static void SetupDyeTable(ZNetScene scene)
		{
			if ((Object)(object)modResourceLoader.dyeTable == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: dyeTable is null");
				return;
			}
			Piece component = modResourceLoader.dyeTable.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: dyeTable Piece component missing");
				return;
			}
			List<Requirement> list = new List<Requirement>
			{
				createReq("Wood", 5, 0, scene.m_prefabs),
				createReq("Resin", 5, 0, scene.m_prefabs)
			};
			component.m_resources = list.ToArray();
			setupRavenGuide(modResourceLoader.dyeTable, scene.m_prefabs);
		}

		private static void AddDyeTableToHammer(ZNetScene scene)
		{
			GameObject val = scene.m_prefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == "Hammer");
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Hammer prefab not found");
				return;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Hammer ItemDrop missing");
				return;
			}
			PieceTable val2 = component.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Hammer build piece table missing");
				return;
			}
			GameObject val3 = val2.m_pieces.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == ((Object)modResourceLoader.dyeTable).name);
			if ((Object)(object)val3 == (Object)null)
			{
				val2.m_pieces.Add(modResourceLoader.dyeTable);
			}
		}

		private static void SetupBuildPieceColorizers(ZNetScene scene)
		{
			string[] array = buildPieceNames;
			foreach (string name in array)
			{
				GameObject val = scene.m_prefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name);
				if (!((Object)(object)val == (Object)null))
				{
					itemSetBuilder.setupColorizer(val);
					swapBasicTexture(val);
				}
			}
		}

		public static void swapBasicTexture(GameObject gameObject)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			if ((Object)(object)gameObject == (Object)null || !DefaultTextureMap.TryGetValue(((Object)gameObject).name, out var value))
			{
				return;
			}
			Transform val = gameObject.transform.Find("default");
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: default child not found on " + ((Object)gameObject).name));
				return;
			}
			MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: MeshRenderer not found on default child of " + ((Object)gameObject).name));
				return;
			}
			Material val2 = value(modResourceLoader);
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: source material missing for " + ((Object)gameObject).name));
				return;
			}
			Material sharedMaterial = (((Renderer)component).material = new Material(val2));
			((Renderer)component).sharedMaterial = sharedMaterial;
		}

		public static void setupRavenGuide(GameObject gameObject, List<GameObject> gameObjects)
		{
			if ((Object)(object)gameObject == (Object)null || gameObjects == null)
			{
				return;
			}
			Transform val = gameObject.transform.Find("GuidePoint");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GameObject val2 = gameObjects.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == "piece_workbench");
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Workbench not found for raven guide setup");
				return;
			}
			Transform val3 = val2.transform.Find("GuidePoint");
			if ((Object)(object)val3 == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Workbench GuidePoint not found");
				return;
			}
			GuidePoint component = ((Component)val3).GetComponent<GuidePoint>();
			GuidePoint component2 = ((Component)val).GetComponent<GuidePoint>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: GuidePoint component missing");
			}
			else if ((Object)(object)component.m_ravenPrefab == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: Raven prefab not found");
			}
			else
			{
				component2.m_ravenPrefab = component.m_ravenPrefab;
			}
		}

		public static List<Recipe> createRecipesForDye(List<GameObject> items)
		{
			List<Recipe> list = new List<Recipe>();
			if (modResourceLoader.items == null || (Object)(object)modResourceLoader.dyeTable == (Object)null)
			{
				return list;
			}
			CraftingStation component = modResourceLoader.dyeTable.GetComponent<CraftingStation>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: CraftingStation missing on dyeTable");
				return list;
			}
			foreach (GameObject item in modResourceLoader.items)
			{
				if (!((Object)(object)item == (Object)null))
				{
					ItemDrop component2 = item.GetComponent<ItemDrop>();
					if ((Object)(object)component2 == (Object)null)
					{
						Debug.LogWarning((object)("BalrondBannerColorizer: ItemDrop missing on " + ((Object)item).name));
						continue;
					}
					Recipe val = ScriptableObject.CreateInstance<Recipe>();
					((Object)val).name = "Recipe_" + ((Object)item).name;
					val.m_minStationLevel = 1;
					val.m_craftingStation = component;
					val.m_repairStation = component;
					val.m_item = component2;
					val.m_resources = createRecipeResource(item, items);
					list.Add(val);
				}
			}
			return list;
		}

		public static Requirement[] createRecipeResource(GameObject item, List<GameObject> items)
		{
			List<Requirement> list = new List<Requirement>();
			if ((Object)(object)item == (Object)null)
			{
				return list.ToArray();
			}
			switch (((Object)item).name)
			{
			case "DyeBlack":
				list.Add(createReq("Coal", 1, 0, items));
				break;
			case "DyeBlue":
				list.Add(createReq("Blueberries", 2, 0, items));
				break;
			case "DyeGreen":
				list.Add(createReq("Guck", 1, 0, items));
				break;
			case "DyeOrange":
				list.Add(createReq("Raspberry", 1, 0, items));
				list.Add(createReq("Cloudberry", 1, 0, items));
				break;
			case "DyePurple":
				list.Add(createReq("Raspberry", 1, 0, items));
				list.Add(createReq("Blueberries", 1, 0, items));
				break;
			case "DyeRed":
				list.Add(createReq("Bloodbag", 1, 0, items));
				break;
			case "DyeWhite":
				list.Add(createReq("BoneFragments", 2, 0, items));
				break;
			case "DyeYellow":
				list.Add(createReq("Cloudberry", 2, 0, items));
				break;
			}
			return list.ToArray();
		}

		public static Requirement createReq(string name, int amount, int amountPerLevel, List<GameObject> items)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Requirement val = new Requirement();
			val.m_recover = true;
			GameObject val2 = FindItem(name, items);
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: Could not create requirement for " + name));
				return val;
			}
			ItemDrop component = val2.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: ItemDrop missing for requirement item " + name));
				return val;
			}
			val.m_resItem = component;
			val.m_amount = amount;
			val.m_amountPerLevel = amountPerLevel;
			return val;
		}

		public static GameObject FindItem(string name, List<GameObject> items)
		{
			if (items == null)
			{
				Debug.LogWarning((object)("BalrondBannerColorizer: item list is null while searching for " + name));
				return null;
			}
			GameObject val = items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Debug.LogWarning((object)("Item Not Found - " + name + ", Replaced With Wood"));
			GameObject val2 = items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == "Wood");
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			Debug.LogWarning((object)("Item Not Found At All - " + name + ", and Wood fallback missing"));
			return null;
		}
	}
	[HarmonyPatch]
	internal static class TranslationPatches
	{
		[HarmonyPatch(typeof(FejdStartup), "SetupGui")]
		private class FejdStartup_SetupGUI
		{
			private static void Postfix()
			{
				string selectedLanguage = Localization.instance.GetSelectedLanguage();
				Dictionary<string, string> translations = GetTranslations(selectedLanguage);
				AddTranslations(translations);
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private class Translation_SetupLanguage
		{
			private static void Prefix(Localization __instance, string language)
			{
				Dictionary<string, string> translations = GetTranslations(language);
				AddTranslations(translations, __instance);
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(Localization), "LoadCSV")]
		private class Translation_LoadCSV
		{
			private static void Prefix(Localization __instance, string language)
			{
				Dictionary<string, string> translations = GetTranslations(language);
				AddTranslations(translations, __instance);
			}
		}

		private static Dictionary<string, string> GetTranslations(string language)
		{
			Dictionary<string, string> result = BalrondTranslator.getLanguage("English");
			if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase))
			{
				Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language);
				if (language2 != null)
				{
					result = language2;
				}
				else
				{
					Debug.Log((object)("BalrondBannerColorizer: Did not find translation file for '" + language + "', loading English"));
				}
			}
			return result;
		}

		private static void AddTranslations(Dictionary<string, string> translations, Localization localizationInstance = null)
		{
			if (translations == null)
			{
				Debug.LogWarning((object)"BalrondBannerColorizer: No translation file found!");
				return;
			}
			if (localizationInstance != null)
			{
				foreach (KeyValuePair<string, string> translation in translations)
				{
					localizationInstance.AddWord(translation.Key, translation.Value);
				}
				return;
			}
			foreach (KeyValuePair<string, string> translation2 in translations)
			{
				Localization.instance.AddWord(translation2.Key, translation2.Value);
			}
		}
	}
}
namespace LitJson2
{
	internal enum JsonType
	{
		None,
		Object,
		Array,
		String,
		Int,
		Long,
		Double,
		Boolean
	}
	internal interface IJsonWrapper : IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable
	{
		bool IsArray { get; }

		bool IsBoolean { get; }

		bool IsDouble { get; }

		bool IsInt { get; }

		bool IsLong { get; }

		bool IsObject { get; }

		bool IsString { get; }

		bool GetBoolean();

		double GetDouble();

		int GetInt();

		JsonType GetJsonType();

		long GetLong();

		string GetString();

		void SetBoolean(bool val);

		void SetDouble(double val);

		void SetInt(int val);

		void SetJsonType(JsonType type);

		void SetLong(long val);

		void SetString(string val);

		string ToJson();

		void ToJson(JsonWriter writer);
	}
	internal class JsonData : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable, IEquatable<JsonData>
	{
		private IList<JsonData> inst_array;

		private bool inst_boolean;

		private double inst_double;

		private int inst_int;

		private long inst_long;

		private IDictionary<string, JsonData> inst_object;

		private string inst_string;

		private string json;

		private JsonType type;

		private IList<KeyValuePair<string, JsonData>> object_list;

		public int Count => EnsureCollection().Count;

		public bool IsArray => type == JsonType.Array;

		public bool IsBoolean => type == JsonType.Boolean;

		public bool IsDouble => type == JsonType.Double;

		public bool IsInt => type == JsonType.Int;

		public bool IsLong => type == JsonType.Long;

		public bool IsObject => type == JsonType.Object;

		public bool IsString => type == JsonType.String;

		public ICollection<string> Keys
		{
			get
			{
				EnsureDictionary();
				return inst_object.Keys;
			}
		}

		int ICollection.Count => Count;

		bool ICollection.IsSynchronized => EnsureCollection().IsSynchronized;

		object ICollection.SyncRoot => EnsureCollection().SyncRoot;

		bool IDictionary.IsFixedSize => EnsureDictionary().IsFixedSize;

		bool IDictionary.IsReadOnly => EnsureDictionary().IsReadOnly;

		ICollection IDictionary.Keys
		{
			get
			{
				EnsureDictionary();
				IList<string> list = new List<string>();
				foreach (KeyValuePair<string, JsonData> item in object_list)
				{
					list.Add(item.Key);
				}
				return (ICollection)list;
			}
		}

		ICollection IDictionary.Values
		{
			get
			{
				EnsureDictionary();
				IList<JsonData> list = new List<JsonData>();
				foreach (KeyValuePair<string, JsonData> item in object_list)
				{
					list.Add(item.Value);
				}
				return (ICollection)list;
			}
		}

		bool IJsonWrapper.IsArray => IsArray;

		bool IJsonWrapper.IsBoolean => IsBoolean;

		bool IJsonWrapper.IsDouble => IsDouble;

		bool IJsonWrapper.IsInt => IsInt;

		bool IJsonWrapper.IsLong => IsLong;

		bool IJsonWrapper.IsObject => IsObject;

		bool IJsonWrapper.IsString => IsString;

		bool IList.IsFixedSize => EnsureList().IsFixedSize;

		bool IList.IsReadOnly => EnsureList().IsReadOnly;

		object IDictionary.this[object key]
		{
			get
			{
				return EnsureDictionary()[key];
			}
			set
			{
				if (!(key is string))
				{
					throw new ArgumentException("The key has to be a string");
				}
				JsonData value2 = ToJsonData(value);
				this[(string)key] = value2;
			}
		}

		object IOrderedDictionary.this[int idx]
		{
			get
			{
				EnsureDictionary();
				return object_list[idx].Value;
			}
			set
			{
				EnsureDictionary();
				JsonData value2 = ToJsonData(value);
				KeyValuePair<string, JsonData> keyValuePair = object_list[idx];
				inst_object[keyValuePair.Key] = value2;
				KeyValuePair<string, JsonData> value3 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value2);
				object_list[idx] = value3;
			}
		}

		object IList.this[int index]
		{
			get
			{
				return EnsureList()[index];
			}
			set
			{
				EnsureList();
				JsonData value2 = ToJsonData(value);
				this[index] = value2;
			}
		}

		public JsonData this[string prop_name]
		{
			get
			{
				EnsureDictionary();
				return inst_object[prop_name];
			}
			set
			{
				EnsureDictionary();
				KeyValuePair<string, JsonData> keyValuePair = new KeyValuePair<string, JsonData>(prop_name, value);
				if (inst_object.ContainsKey(prop_name))
				{
					for (int i = 0; i < object_list.Count; i++)
					{
						if (object_list[i].Key == prop_name)
						{
							object_list[i] = keyValuePair;
							break;
						}
					}
				}
				else
				{
					object_list.Add(keyValuePair);
				}
				inst_object[prop_name] = value;
				json = null;
			}
		}

		public JsonData this[int index]
		{
			get
			{
				EnsureCollection();
				if (type == JsonType.Array)
				{
					return inst_array[index];
				}
				return object_list[index].Value;
			}
			set
			{
				EnsureCollection();
				if (type == JsonType.Array)
				{
					inst_array[index] = value;
				}
				else
				{
					KeyValuePair<string, JsonData> keyValuePair = object_list[index];
					KeyValuePair<string, JsonData> value2 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value);
					object_list[index] = value2;
					inst_object[keyValuePair.Key] = value;
				}
				json = null;
			}
		}

		public JsonData()
		{
		}

		public JsonData(bool boolean)
		{
			type = JsonType.Boolean;
			inst_boolean = boolean;
		}

		public JsonData(double number)
		{
			type = JsonType.Double;
			inst_double = number;
		}

		public JsonData(int number)
		{
			type = JsonType.Int;
			inst_int = number;
		}

		public JsonData(long number)
		{
			type = JsonType.Long;
			inst_long = number;
		}

		public JsonData(object obj)
		{
			if (obj is bool)
			{
				type = JsonType.Boolean;
				inst_boolean = (bool)obj;
				return;
			}
			if (obj is double)
			{
				type = JsonType.Double;
				inst_double = (double)obj;
				return;
			}
			if (obj is int)
			{
				type = JsonType.Int;
				inst_int = (int)obj;
				return;
			}
			if (obj is long)
			{
				type = JsonType.Long;
				inst_long = (long)obj;
				return;
			}
			if (obj is string)
			{
				type = JsonType.String;
				inst_string = (string)obj;
				return;
			}
			throw new ArgumentException("Unable to wrap the given object with JsonData");
		}

		public JsonData(string str)
		{
			type = JsonType.String;
			inst_string = str;
		}

		public static implicit operator JsonData(bool data)
		{
			return new JsonData(data);
		}

		public static implicit operator JsonData(double data)
		{
			return new JsonData(data);
		}

		public static implicit operator JsonData(int data)
		{
			return new JsonData(data);
		}

		public static implicit operator JsonData(long data)
		{
			return new JsonData(data);
		}

		public static implicit operator JsonData(string data)
		{
			return new JsonData(data);
		}

		public static explicit operator bool(JsonData data)
		{
			if (data.type != JsonType.Boolean)
			{
				throw new InvalidCastException("Instance of JsonData doesn't hold a double");
			}
			return data.inst_boolean;
		}

		public static explicit operator double(JsonData data)
		{
			if (data.type != JsonType.Double)
			{
				throw new InvalidCastException("Instance of JsonData doesn't hold a double");
			}
			return data.inst_double;
		}

		public static explicit operator int(JsonData data)
		{
			if (data.type != JsonType.Int)
			{
				throw new InvalidCastException("Instance of JsonData doesn't hold an int");
			}
			return data.inst_int;
		}

		public static explicit operator long(JsonData data)
		{
			if (data.type != JsonType.Long)
			{
				throw new InvalidCastException("Instance of JsonData doesn't hold an int");
			}
			return data.inst_long;
		}

		public static explicit operator string(JsonData data)
		{
			if (data.type != JsonType.String)
			{
				throw new InvalidCastException("Instance of JsonData doesn't hold a string");
			}
			return data.inst_string;
		}

		void ICollection.CopyTo(Array array, int index)
		{
			EnsureCollection().CopyTo(array, index);
		}

		void IDictionary.Add(object key, object value)
		{
			JsonData value2 = ToJsonData(value);
			EnsureDictionary().Add(key, value2);
			KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>((string)key, value2);
			object_list.Add(item);
			json = null;
		}

		void IDictionary.Clear()
		{
			EnsureDictionary().Clear();
			object_list.Clear();
			json = null;
		}

		bool IDictionary.Contains(object key)
		{
			return EnsureDictionary().Contains(key);
		}

		IDictionaryEnumerator IDictionary.GetEnumerator()
		{
			return ((IOrderedDictionary)this).GetEnumerator();
		}

		void IDictionary.Remove(object key)
		{
			EnsureDictionary().Remove(key);
			for (int i = 0; i < object_list.Count; i++)
			{
				if (object_list[i].Key == (string)key)
				{
					object_list.RemoveAt(i);
					break;
				}
			}
			json = null;
		}

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

		bool IJsonWrapper.GetBoolean()
		{
			if (type != JsonType.Boolean)
			{
				throw new InvalidOperationException("JsonData instance doesn't hold a boolean");
			}
			return inst_boolean;
		}

		double IJsonWrapper.GetDouble()
		{
			if (type != JsonType.Double)
			{
				throw new InvalidOperationException("JsonData instance doesn't hold a double");
			}
			return inst_double;
		}

		int IJsonWrapper.GetInt()
		{
			if (type != JsonType.Int)
			{
				throw new InvalidOperationException("JsonData instance doesn't hold an int");
			}
			return inst_int;
		}

		long IJsonWrapper.GetLong()
		{
			if (type != JsonType.Long)
			{
				throw new InvalidOperationException("JsonData instance doesn't hold a long");
			}
			return inst_long;
		}

		string IJsonWrapper.GetString()
		{
			if (type != JsonType.String)
			{
				throw new InvalidOperationException("JsonData instance doesn't hold a string");
			}
			return inst_string;
		}

		void IJsonWrapper.SetBoolean(bool val)
		{
			type = JsonType.Boolean;
			inst_boolean = val;
			json = null;
		}

		void IJsonWrapper.SetDouble(double val)
		{
			type = JsonType.Double;
			inst_double = val;
			json = null;
		}

		void IJsonWrapper.SetInt(int val)
		{
			type = JsonType.Int;
			inst_int = val;
			json = null;
		}

		void IJsonWrapper.SetLong(long val)
		{
			type = JsonType.Long;
			inst_long = val;
			json = null;
		}

		void IJsonWrapper.SetString(string val)
		{
			type = JsonType.String;
			inst_string = val;
			json = null;
		}

		string IJsonWrapper.ToJson()
		{
			return ToJson();
		}

		void IJsonWrapper.ToJson(JsonWriter writer)
		{
			ToJson(writer);
		}

		int IList.Add(object value)
		{
			return Add(value);
		}

		void IList.Clear()
		{
			EnsureList().Clear();
			json = null;
		}

		bool IList.Contains(object value)
		{
			return EnsureList().Contains(value);
		}

		int IList.IndexOf(object value)
		{
			return EnsureList().IndexOf(value);
		}

		void IList.Insert(int index, object value)
		{
			EnsureList().Insert(index, value);
			json = null;
		}

		void IList.Remove(object value)
		{
			EnsureList().Remove(value);
			json = null;
		}

		void IList.RemoveAt(int index)
		{
			EnsureList().RemoveAt(index);
			json = null;
		}

		IDictionaryEnumerator IOrderedDictionary.GetEnumerator()
		{
			EnsureDictionary();
			return new OrderedDictionaryEnumerator(object_list.GetEnumerator());
		}

		void IOrderedDictionary.Insert(int idx, object key, object value)
		{
			string text = (string)key;
			JsonData value2 = (this[text] = ToJsonData(value));
			KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>(text, value2);
			object_list.Insert(idx, item);
		}

		void IOrderedDictionary.RemoveAt(int idx)
		{
			EnsureDictionary();
			inst_object.Remove(object_list[idx].Key);
			object_list.RemoveAt(idx);
		}

		private ICollection EnsureCollection()
		{
			if (type == JsonType.Array)
			{
				return (ICollection)inst_array;
			}
			if (type == JsonType.Object)
			{
				return (ICollection)inst_object;
			}
			throw new InvalidOperationException("The JsonData instance has to be initialized first");
		}

		private IDictionary EnsureDictionary()
		{
			if (type == JsonType.Object)
			{
				return (IDictionary)inst_object;
			}
			if (type != 0)
			{
				throw new InvalidOperationException("Instance of JsonData is not a dictionary");
			}
			type = JsonType.Object;
			inst_object = new Dictionary<string, JsonData>();
			object_list = new List<KeyValuePair<string, JsonData>>();
			return (IDictionary)inst_object;
		}

		private IList EnsureList()
		{
			if (type == JsonType.Array)
			{
				return (IList)inst_array;
			}
			if (type != 0)
			{
				throw new InvalidOperationException("Instance of JsonData is not a list");
			}
			type = JsonType.Array;
			inst_array = new List<JsonData>();
			return (IList)inst_array;
		}

		private JsonData ToJsonData(object obj)
		{
			if (obj == null)
			{
				return null;
			}
			if (obj is JsonData)
			{
				return (JsonData)obj;
			}
			return new JsonData(obj);
		}

		private static void WriteJson(IJsonWrapper obj, JsonWriter writer)
		{
			if (obj == null)
			{
				writer.Write(null);
			}
			else if (obj.IsString)
			{
				writer.Write(obj.GetString());
			}
			else if (obj.IsBoolean)
			{
				writer.Write(obj.GetBoolean());
			}
			else if (obj.IsDouble)
			{
				writer.Write(obj.GetDouble());
			}
			else if (obj.IsInt)
			{
				writer.Write(obj.GetInt());
			}
			else if (obj.IsLong)
			{
				writer.Write(obj.GetLong());
			}
			else if (obj.IsArray)
			{
				writer.WriteArrayStart();
				foreach (object item in (IEnumerable)obj)
				{
					WriteJson((JsonData)item, writer);
				}
				writer.WriteArrayEnd();
			}
			else
			{
				if (!obj.IsObject)
				{
					return;
				}
				writer.WriteObjectStart();
				foreach (DictionaryEntry item2 in (IDictionary)obj)
				{
					writer.WritePropertyName((string)item2.Key);
					WriteJson((JsonData)item2.Value, writer);
				}
				writer.WriteObjectEnd();
			}
		}

		public int Add(object value)
		{
			JsonData value2 = ToJsonData(value);
			json = null;
			return EnsureList().Add(value2);
		}

		public void Clear()
		{
			if (IsObject)
			{
				((IDictionary)this).Clear();
			}
			else if (IsArray)
			{
				((IList)this).Clear();
			}
		}

		public bool Equals(JsonData x)
		{
			if (x == null)
			{
				return false;
			}
			if (x.type != type)
			{
				return false;
			}
			return type switch
			{
				JsonType.None => true, 
				JsonType.Object => inst_object.Equals(x.inst_object), 
				JsonType.Array => inst_array.Equals(x.inst_array), 
				JsonType.String => inst_string.Equals(x.inst_string), 
				JsonType.Int => inst_int.Equals(x.inst_int), 
				JsonType.Long => inst_long.Equals(x.inst_long), 
				JsonType.Double => inst_double.Equals(x.inst_double), 
				JsonType.Boolean => inst_boolean.Equals(x.inst_boolean), 
				_ => false, 
			};
		}

		public JsonType GetJsonType()
		{
			return type;
		}

		public void SetJsonType(JsonType type)
		{
			if (this.type != type)
			{
				switch (type)
				{
				case JsonType.Object:
					inst_object = new Dictionary<string, JsonData>();
					object_list = new List<KeyValuePair<string, JsonData>>();
					break;
				case JsonType.Array:
					inst_array = new List<JsonData>();
					break;
				case JsonType.String:
					inst_string = null;
					break;
				case JsonType.Int:
					inst_int = 0;
					break;
				case JsonType.Long:
					inst_long = 0L;
					break;
				case JsonType.Double:
					inst_double = 0.0;
					break;
				case JsonType.Boolean:
					inst_boolean = false;
					break;
				}
				this.type = type;
			}
		}

		public string ToJson()
		{
			if (json != null)
			{
				return json;
			}
			StringWriter stringWriter = new StringWriter();
			JsonWriter jsonWriter = new JsonWriter(stringWriter);
			jsonWriter.Validate = false;
			WriteJson(this, jsonWriter);
			json = stringWriter.ToString();
			return json;
		}

		public void ToJson(JsonWriter writer)
		{
			bool validate = writer.Validate;
			writer.Validate = false;
			WriteJson(this, writer);
			writer.Validate = validate;
		}

		public override string ToString()
		{
			return type switch
			{
				JsonType.Array => "JsonData array", 
				JsonType.Boolean => inst_boolean.ToString(), 
				JsonType.Double => inst_double.ToString(), 
				JsonType.Int => inst_int.ToString(), 
				JsonType.Long => inst_long.ToString(), 
				JsonType.Object => "JsonData object", 
				JsonType.String => inst_string, 
				_ => "Uninitialized JsonData", 
			};
		}
	}
	internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator
	{
		private IEnumerator<KeyValuePair<string, JsonData>> list_enumerator;

		public object Current => Entry;

		public DictionaryEntry Entry
		{
			get
			{
				KeyValuePair<string, JsonData> current = list_enumerator.Current;
				return new DictionaryEntry(current.Key, current.Value);
			}
		}

		public object Key => list_enumerator.Current.Key;

		public object Value => list_enumerator.Current.Value;

		public OrderedDictionaryEnumerator(IEnumerator<KeyValuePair<string, JsonData>> enumerator)
		{
			list_enumerator = enumerator;
		}

		public bool MoveNext()
		{
			return list_enumerator.MoveNext();
		}

		public void Reset()
		{
			list_enumerator.Reset();
		}
	}
	internal class JsonException : ApplicationException
	{
		public JsonException()
		{
		}

		internal JsonException(ParserToken token)
			: base($"Invalid token '{token}' in input string")
		{
		}

		internal JsonException(ParserToken token, Exception inner_exception)
			: base($"Invalid token '{token}' in input string", inner_exception)
		{
		}

		internal JsonException(int c)
			: base($"Invalid character '{(char)c}' in input string")
		{
		}

		internal JsonException(int c, Exception inner_exception)
			: base($"Invalid character '{(char)c}' in input string", inner_exception)
		{
		}

		public JsonException(string message)
			: base(message)
		{
		}

		public JsonException(string message, Exception inner_exception)
			: base(message, inner_exception)
		{
		}
	}
	internal struct PropertyMetadata
	{
		public MemberInfo Info;

		public bool IsField;

		public Type Type;
	}
	internal struct ArrayMetadata
	{
		private Type element_type;

		private bool is_array;

		private bool is_list;

		public Type ElementType
		{
			get
			{
				if (element_type == null)
				{
					return typeof(JsonData);
				}
				return element_type;
			}
			set
			{
				element_type = value;
			}
		}

		public bool IsArray
		{
			get
			{
				return is_array;
			}
			set
			{
				is_array = value;
			}
		}

		public bool IsList
		{
			get
			{
				return is_list;
			}
			set
			{
				is_list = value;
			}
		}
	}
	internal struct ObjectMetadata
	{
		private Type element_type;

		private bool is_dictionary;

		private IDictionary<string, PropertyMetadata> properties;

		public Type ElementType
		{
			get
			{
				if (element_type == null)
				{
					return typeof(JsonData);
				}
				return element_type;
			}
			set
			{
				element_type = value;
			}
		}

		public bool IsDictionary
		{
			get
			{
				return is_dictionary;
			}
			set
			{
				is_dictionary = value;
			}
		}

		public IDictionary<string, PropertyMetadata> Properties
		{
			get
			{
				return properties;
			}
			set
			{
				properties = value;
			}
		}
	}
	internal delegate void ExporterFunc(object obj, JsonWriter writer);
	internal delegate void ExporterFunc<T>(T obj, JsonWriter writer);
	internal delegate object ImporterFunc(object input);
	internal delegate TValue ImporterFunc<TJson, TValue>(TJson input);
	internal delegate IJsonWrapper WrapperFactory();
	internal class JsonMapper
	{
		private static int max_nesting_depth;

		private static IFormatProvider datetime_format;

		private static IDictionary<Type, ExporterFunc> base_exporters_table;

		private static IDictionary<Type, ExporterFunc> custom_exporters_table;

		private static IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table;

		private static IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table;

		private static IDictionary<Type, ArrayMetadata> array_metadata;

		private static readonly object array_metadata_lock;

		private static IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops;

		private static readonly object conv_ops_lock;

		private static IDictionary<Type, ObjectMetadata> object_metadata;

		private static readonly object object_metadata_lock;

		private static IDictionary<Type, IList<PropertyMetadata>> type_properties;

		private static readonly object type_properties_lock;

		private static JsonWriter static_writer;

		private static readonly object static_writer_lock;

		static JsonMapper()
		{
			array_metadata_lock = new object();
			conv_ops_lock = new object();
			object_metadata_lock = new object();
			type_properties_lock = new object();
			static_writer_lock = new object();
			max_nesting_depth = 100;
			array_metadata = new Dictionary<Type, ArrayMetadata>();
			conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>();
			object_metadata = new Dictionary<Type, ObjectMetadata>();
			type_properties = new Dictionary<Type, IList<PropertyMetadata>>();
			static_writer = new JsonWriter();
			datetime_format = DateTimeFormatInfo.InvariantInfo;
			base_exporters_table = new Dictionary<Type, ExporterFunc>();
			custom_exporters_table = new Dictionary<Type, ExporterFunc>();
			base_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>();
			custom_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>();
			RegisterBaseExporters();
			RegisterBaseImporters();
		}

		private static void AddArrayMetadata(Type type)
		{
			if (array_metadata.ContainsKey(type))
			{
				return;
			}
			ArrayMetadata value = default(ArrayMetadata);
			value.IsArray = type.IsArray;
			if (type.GetInterface("System.Collections.IList") != null)
			{
				value.IsList = true;
			}
			PropertyInfo[] properties = type.GetProperties();
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (!(propertyInfo.Name != "Item"))
				{
					ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters();
					if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(int))
					{
						value.ElementType = propertyInfo.PropertyType;
					}
				}
			}
			lock (array_metadata_lock)
			{
				try
				{
					array_metadata.Add(type, value);
				}
				catch (ArgumentException)
				{
				}
			}
		}

		private static void AddObjectMetadata(Type type)
		{
			if (object_metadata.ContainsKey(type))
			{
				return;
			}
			ObjectMetadata value = default(ObjectMetadata);
			if (type.GetInterface("System.Collections.IDictionary") != null)
			{
				value.IsDictionary = true;
			}
			value.Properties = new Dictionary<string, PropertyMetadata>();
			PropertyInfo[] properties = type.GetProperties();
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.Name == "Item")
				{
					ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters();
					if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(string))
					{
						value.ElementType = propertyInfo.PropertyType;
					}
				}
				else
				{
					PropertyMetadata value2 = default(PropertyMetadata);
					value2.Info = propertyInfo;
					value2.Type = propertyInfo.PropertyType;
					value.Properties.Add(propertyInfo.Name, value2);
				}
			}
			FieldInfo[] fields = type.GetFields();
			foreach (FieldInfo fieldInfo in fields)
			{
				PropertyMetadata value3 = default(PropertyMetadata);
				value3.Info = fieldInfo;
				value3.IsField = true;
				value3.Type = fieldInfo.FieldType;
				value.Properties.Add(fieldInfo.Name, value3);
			}
			lock (object_metadata_lock)
			{
				try
				{
					object_metadata.Add(type, value);
				}
				catch (ArgumentException)
				{
				}
			}
		}

		private static void AddTypeProperties(Type type)
		{
			if (type_properties.ContainsKey(type))
			{
				return;
			}
			IList<PropertyMetadata> list = new List<PropertyMetadata>();
			PropertyInfo[] properties = type.GetProperties();
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (!(propertyInfo.Name == "Item"))
				{
					PropertyMetadata item = default(PropertyMetadata);
					item.Info = propertyInfo;
					item.IsField = false;
					list.Add(item);
				}
			}
			FieldInfo[] fields = type.GetFields();
			foreach (FieldInfo info in fields)
			{
				PropertyMetadata item2 = default(PropertyMetadata);
				item2.Info = info;
				item2.IsField = true;
				list.Add(item2);
			}
			lock (type_properties_lock)
			{
				try
				{
					type_properties.Add(type, list);
				}
				catch (ArgumentException)
				{
				}
			}
		}

		private static MethodInfo GetConvOp(Type t1, Type t2)
		{
			lock (conv_ops_lock)
			{
				if (!conv_ops.ContainsKey(t1))
				{
					conv_ops.Add(t1, new Dictionary<Type, MethodInfo>());
				}
			}
			if (conv_ops[t1].ContainsKey(t2))
			{
				return conv_ops[t1][t2];
			}
			MethodInfo method = t1.GetMethod("op_Implicit", new Type[1] { t2 });
			lock (conv_ops_lock)
			{
				try
				{
					conv_ops[t1].Add(t2, method);
					return method;
				}
				catch (ArgumentException)
				{
					return conv_ops[t1][t2];
				}
			}
		}

		private static object ReadValue(Type inst_type, JsonReader reader)
		{
			reader.Read();
			if (reader.Token == JsonToken.ArrayEnd)
			{
				return null;
			}
			Type underlyingType = Nullable.GetUnderlyingType(inst_type);
			Type type = underlyingType ?? inst_type;
			if (reader.Token == JsonToken.Null)
			{
				if (inst_type.IsClass || underlyingType != null)
				{
					return null;
				}
				throw new JsonException($"Can't assign null to an instance of type {inst_type}");
			}
			if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean)
			{
				Type type2 = reader.Value.GetType();
				if (type.IsAssignableFrom(type2))
				{
					return reader.Value;
				}
				if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type))
				{
					ImporterFunc importerFunc = custom_importers_table[type