Decompiled source of balrond bundling machine v1.1.2

plugins/BalrondPackager.dll

Decompiled 2 weeks 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.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("BalrondPackager")]
[assembly: AssemblyDescription("Balrond Packager for Valheim")]
[assembly: AssemblyCompany("Balrond")]
[assembly: AssemblyProduct("BalrondPackager")]
[assembly: ComVisible(false)]
[assembly: Guid("cde312a0-cf19-4264-8616-e1c74774beed")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[module: UnverifiableCode]
namespace BalrondPackager
{
	public static class BalrondTranslator
	{
		public static readonly Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

		public static Dictionary<string, string> getLanguage(string language)
		{
			if (string.IsNullOrEmpty(language))
			{
				return null;
			}
			Dictionary<string, string> value;
			return translations.TryGetValue(language, out value) ? value : null;
		}
	}
	public sealed class BuildPieceBuilder
	{
		private static readonly string[] PieceNames = new string[2] { "packager_bal", "unpackager_bal" };

		private Dictionary<string, GameObject> m_prefabByName;

		public void SetupBuildPieces(List<GameObject> prefabs)
		{
			if (prefabs == null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": SetupBuildPieces received null prefab list."));
				return;
			}
			TableMapper.setupTables(prefabs);
			m_prefabByName = BuildPrefabLookup(prefabs);
			for (int i = 0; i < PieceNames.Length; i++)
			{
				if (!m_prefabByName.TryGetValue(PieceNames[i], out var value) || (Object)(object)value == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": build piece not found: " + PieceNames[i]));
				}
				else
				{
					ConfigureBuildPiece(value);
				}
			}
		}

		private static Dictionary<string, GameObject> BuildPrefabLookup(List<GameObject> prefabs)
		{
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.Ordinal);
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name) && !dictionary.ContainsKey(((Object)val).name))
				{
					dictionary.Add(((Object)val).name, val);
				}
			}
			return dictionary;
		}

		private void ConfigureBuildPiece(GameObject gameObject)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Piece val = (((Object)(object)gameObject != (Object)null) ? gameObject.GetComponent<Piece>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Piece component missing on " + (((Object)(object)gameObject != (Object)null) ? ((Object)gameObject).name : "null")));
				return;
			}
			val.m_category = (PieceCategory)1;
			val.m_usage = (UsageTagFlags)2;
			val.m_enabled = false;
			List<Requirement> list = new List<Requirement>();
			bool flag = true;
			string name = ((Object)gameObject).name;
			string text = name;
			CraftingStation val2;
			if (!(text == "packager_bal"))
			{
				if (!(text == "unpackager_bal"))
				{
					return;
				}
				val2 = TableMapper.workbench;
				flag &= AddResource(list, "Stone", 10);
				flag &= AddResource(list, "Wood", 10);
			}
			else
			{
				val2 = TableMapper.forge;
				flag &= AddResource(list, "ElderBark", 20);
				flag &= AddResource(list, "SurtlingCore", 5);
				flag &= AddResource(list, "Stone", 10);
				flag &= AddResource(list, "Iron", 10);
				flag &= AddResource(list, "RoundLog", 10);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": required crafting station missing for " + ((Object)gameObject).name + ". Piece disabled."));
				flag = false;
			}
			if (!flag)
			{
				val.m_resources = list.ToArray();
				return;
			}
			val.m_craftingStation = val2;
			val.m_resources = list.ToArray();
			val.m_enabled = true;
		}

		private bool AddResource(List<Requirement> requirements, string itemName, int amount, int amountPerLevel = 0, bool recover = true)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			if (m_prefabByName == null || !m_prefabByName.TryGetValue(itemName, out var value) || (Object)(object)value == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": required resource prefab not found: " + itemName));
				return false;
			}
			ItemDrop component = value.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": resource prefab has no ItemDrop: " + itemName));
				return false;
			}
			requirements.Add(new Requirement
			{
				m_resItem = component,
				m_amount = amount,
				m_amountPerLevel = amountPerLevel,
				m_recover = recover
			});
			return true;
		}
	}
	internal class BuildPieceList
	{
		public static string[] buildPieces = new string[2] { "packager_bal", "unpackager_bal" };
	}
	public class BalrondPackager : MonoBehaviour
	{
		private struct PackedEntry
		{
			internal readonly string PrefabName;

			internal readonly int Stack;

			internal readonly string SerializedData;

			internal PackedEntry(string prefabName, int stack, string serializedData)
			{
				PrefabName = prefabName;
				Stack = stack;
				SerializedData = serializedData;
			}
		}

		public enum Response
		{
			Fail,
			Success,
			Conversion,
			Empty
		}

		public Switch m_incinerateSwitch;

		public Container m_container;

		public Animator m_leverAnim;

		public EffectList m_leverEffects = new EffectList();

		public float m_effectDelayMin = 10f;

		public float m_effectDelayMax = 15f;

		[Header("Conversion")]
		public ItemDrop m_defaultResult;

		public int m_defaultCost = 1;

		public Transform output;

		public GameObject m_enabled;

		public EffectList m_produceEffects = new EffectList();

		private ZNetView m_nview;

		private bool m_isInUse;

		private void Awake()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if ((Object)(object)m_incinerateSwitch != (Object)null)
			{
				Switch incinerateSwitch = m_incinerateSwitch;
				incinerateSwitch.m_onUse = (Callback)Delegate.Combine((Delegate?)(object)incinerateSwitch.m_onUse, (Delegate?)new Callback(OnIncinerate));
				Switch incinerateSwitch2 = m_incinerateSwitch;
				incinerateSwitch2.m_onHover = (TooltipCallback)Delegate.Combine((Delegate?)(object)incinerateSwitch2.m_onHover, (Delegate?)new TooltipCallback(GetLeverHoverText));
			}
			else
			{
				Debug.LogWarning((object)(Launch.projectName + ": Missing Switch on packager: " + ((Object)((Component)this).gameObject).name));
			}
			m_nview = ((Component)this).GetComponent<ZNetView>();
			if (!((Object)(object)m_nview == (Object)null) && m_nview.GetZDO() != null)
			{
				m_nview.Register<long>("RPC_RequestPackage", (Action<long, long>)RPC_RequestPackage);
				m_nview.Register<int>("RPC_PackageRespons", (Action<long, int>)RPC_PackageRespons);
				m_nview.Register("RPC_AnimateLever", (Action<long>)RPC_AnimateLever);
				m_nview.Register("RPC_AnimateLeverReturn", (Action<long>)RPC_AnimateLeverReturn);
				if ((Object)(object)m_enabled != (Object)null)
				{
					m_enabled.SetActive(false);
				}
			}
		}

		private void OnDestroy()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if ((Object)(object)m_incinerateSwitch != (Object)null)
			{
				Switch incinerateSwitch = m_incinerateSwitch;
				incinerateSwitch.m_onUse = (Callback)Delegate.Remove((Delegate?)(object)incinerateSwitch.m_onUse, (Delegate?)new Callback(OnIncinerate));
				Switch incinerateSwitch2 = m_incinerateSwitch;
				incinerateSwitch2.m_onHover = (TooltipCallback)Delegate.Remove((Delegate?)(object)incinerateSwitch2.m_onHover, (Delegate?)new TooltipCallback(GetLeverHoverText));
			}
		}

		private void ReleaseUseLock()
		{
			m_isInUse = false;
		}

		public string GetLeverHoverText()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return (Localization.instance != null) ? Localization.instance.Localize("$piece_packager\n$piece_noaccess") : "$piece_packager\n$piece_noaccess";
			}
			return (Localization.instance != null) ? Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] $piece_pulllever") : "[Use] $piece_pulllever";
		}

		private bool OnIncinerate(Switch sw, Humanoid user, ItemData item)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.HasOwner())
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			if ((Object)(object)Game.instance == (Object)null || Game.instance.GetPlayerProfile() == null)
			{
				return false;
			}
			m_nview.InvokeRPC("RPC_RequestPackage", new object[1] { Game.instance.GetPlayerProfile().GetPlayerID() });
			return true;
		}

		private void RPC_RequestPackage(long uid, long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner())
			{
				if ((Object)(object)m_container == (Object)null || m_container.GetInventory() == null)
				{
					m_nview.InvokeRPC(uid, "RPC_PackageRespons", new object[1] { 0 });
				}
				else if (m_container.IsInUse() || m_isInUse)
				{
					m_nview.InvokeRPC(uid, "RPC_PackageRespons", new object[1] { 0 });
				}
				else if (m_container.GetInventory().NrOfItems() == 0)
				{
					m_nview.InvokeRPC(uid, "RPC_PackageRespons", new object[1] { 3 });
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(Package(uid));
				}
			}
		}

		private IEnumerator Package(long uid)
		{
			m_isInUse = true;
			m_nview.InvokeRPC(ZNetView.Everybody, "RPC_AnimateLever", Array.Empty<object>());
			if (m_leverEffects != null)
			{
				m_leverEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			if ((Object)(object)m_enabled != (Object)null)
			{
				m_enabled.SetActive(true);
			}
			float delayMin = Mathf.Max(0f, m_effectDelayMin);
			float delayMax = Mathf.Max(delayMin, m_effectDelayMax);
			yield return (object)new WaitForSeconds(Random.Range(delayMin, delayMax));
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				m_isInUse = false;
				yield break;
			}
			m_nview.InvokeRPC(ZNetView.Everybody, "RPC_AnimateLeverReturn", Array.Empty<object>());
			if ((Object)(object)m_enabled != (Object)null)
			{
				m_enabled.SetActive(false);
			}
			if (!m_nview.IsOwner() || (Object)(object)m_container == (Object)null || m_container.GetInventory() == null || m_container.IsInUse())
			{
				m_isInUse = false;
				yield break;
			}
			((MonoBehaviour)this).Invoke("ReleaseUseLock", 4f);
			int response = TryCreatePackage();
			m_nview.InvokeRPC(uid, "RPC_PackageRespons", new object[1] { response });
		}

		private int TryCreatePackage()
		{
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = (((Object)(object)m_container != (Object)null) ? m_container.GetInventory() : null);
			if (val == null)
			{
				return 0;
			}
			List<ItemData> allItems = val.GetAllItems();
			if (allItems == null || allItems.Count == 0)
			{
				return 3;
			}
			if (allItems.Count > 256)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Refusing to create package with " + allItems.Count + " entries."));
				return 0;
			}
			if ((Object)(object)m_defaultResult == (Object)null || (Object)(object)output == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Packager missing result item or output transform."));
				return 0;
			}
			List<PackedEntry> list = new List<PackedEntry>(allItems.Count);
			StringBuilder stringBuilder = new StringBuilder("Contains:\n", 64 + allItems.Count * 24);
			bool flag = true;
			bool flag2 = false;
			float num = 0f;
			int num2 = 0;
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val2 = allItems[i];
				if (!IsValidPackageItem(val2))
				{
					string text = ((val2 != null && (Object)(object)val2.m_dropPrefab != (Object)null) ? ((Object)val2.m_dropPrefab).name : "null");
					Debug.LogWarning((object)(Launch.projectName + ": Can't create package; unsupported item: " + text));
					return 0;
				}
				if (!PackageItemSerializer.TrySerialize(val2, out var encoded))
				{
					Debug.LogWarning((object)(Launch.projectName + ": Failed to serialize " + ((Object)val2.m_dropPrefab).name + "."));
					return 0;
				}
				num2 += encoded.Length;
				if (num2 > 1048576)
				{
					Debug.LogWarning((object)(Launch.projectName + ": Package payload exceeds the safety limit of " + 1048576 + " encoded characters."));
					return 0;
				}
				list.Add(new PackedEntry(((Object)val2.m_dropPrefab).name, val2.m_stack, encoded));
				stringBuilder.Append(val2.m_shared.m_name).Append(" x").Append(val2.m_stack)
					.Append('\n');
				num += val2.GetWeight(-1);
				if (!PackageMetadata.IsItemTeleportable(val2))
				{
					flag = false;
				}
				if (val2.m_shared.m_toolTier >= 1000)
				{
					flag2 = true;
				}
			}
			ItemDrop val3 = Object.Instantiate<ItemDrop>(m_defaultResult, output.position, output.rotation);
			if ((Object)(object)val3 == (Object)null || val3.m_itemData == null)
			{
				return 0;
			}
			try
			{
				val3.m_itemData.m_stack = 1;
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageFormatVersion", 3.ToString(CultureInfo.InvariantCulture));
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageAmount", list.Count.ToString(CultureInfo.InvariantCulture));
				for (int j = 0; j < list.Count; j++)
				{
					PackedEntry packedEntry = list[j];
					PackageMetadata.Set(val3.m_itemData, "BalrondPackagePrefab-" + j, packedEntry.PrefabName);
					PackageMetadata.Set(val3.m_itemData, "BalrondPackageData-" + j, packedEntry.SerializedData);
					ItemData itemData = val3.m_itemData;
					string key = "BalrondPackageIndex-" + j;
					string prefabName = packedEntry.PrefabName;
					int stack = packedEntry.Stack;
					PackageMetadata.Set(itemData, key, prefabName + "." + stack.ToString(CultureInfo.InvariantCulture));
				}
				string value = stringBuilder.ToString();
				float num3 = num * 0.5f;
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageDescription", value);
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageWeight", num3.ToString("R", CultureInfo.InvariantCulture));
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageTeleportable", flag ? "1" : "0");
				PackageMetadata.Set(val3.m_itemData, "BalrondPackageHardNoTeleport", flag2 ? "1" : "0");
				val3.Save();
				if (m_produceEffects != null)
				{
					m_produceEffects.Create(output.position, output.rotation, (Transform)null, 1f, -1, default(ZDOID));
				}
				val.RemoveAll();
				return 1;
			}
			catch (Exception ex)
			{
				if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val3).gameObject);
				}
				Debug.LogWarning((object)(Launch.projectName + ": Package creation failed: " + ex));
				return 0;
			}
		}

		private static bool IsValidPackageItem(ItemData item)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || item.m_shared == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return false;
			}
			if (string.Equals(((Object)item.m_dropPrefab).name, "CustomPackageItem_bal", StringComparison.Ordinal))
			{
				return false;
			}
			return ValidateItemType(item.m_shared.m_itemType);
		}

		private static bool ValidateItemType(ItemType itemType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			return (int)itemType == 1 || (int)itemType == 2 || (int)itemType == 9 || (int)itemType == 23 || (int)itemType == 16 || (int)itemType == 13 || (int)itemType == 21 || (int)itemType == 24;
		}

		private void RPC_PackageRespons(long uid, int response)
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, (Response)response switch
				{
					Response.Success => "$piece_packager_success", 
					Response.Conversion => "$piece_packager_conversion", 
					Response.Empty => "$piece_packager_empty", 
					_ => "$piece_packager_fail", 
				}, 0, (Sprite)null, false);
			}
		}

		private void RPC_AnimateLever(long uid)
		{
			if ((Object)(object)m_leverAnim != (Object)null)
			{
				m_leverAnim.SetBool("Pulled", true);
			}
		}

		private void RPC_AnimateLeverReturn(long uid)
		{
			if ((Object)(object)m_leverAnim != (Object)null)
			{
				m_leverAnim.SetBool("Pulled", false);
			}
		}
	}
	public class BalrondUnpackager : MonoBehaviour, Hoverable, Interactable
	{
		public string m_name = "$tag_unpackager_bal";

		public string m_useItemText = "$tag_use_me";

		public ItemDrop m_requiredItem;

		public Transform m_itemSpawnPoint;

		public float m_SpawnDelay = 2f;

		[Header("Effects")]
		public EffectList m_spawnStartEffects = new EffectList();

		public EffectList m_spawnFinishEffects = new EffectList();

		public Transform m_roofCheckPoint;

		public bool m_requiresRoof;

		private ZNetView m_nview;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null)
			{
				ZLog.Log((object)(Launch.projectName + ": Missing ZNetView on unpackager " + ((Object)((Component)this).gameObject).name));
			}
			else if ((Object)(object)m_requiredItem == (Object)null)
			{
				m_requiredItem = FindRequiredItem();
			}
		}

		private static ItemDrop FindRequiredItem()
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("CustomPackageItem_bal") : null);
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null)
			{
				val = ZNetScene.instance.m_prefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == "CustomPackageItem_bal");
			}
			return ((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null;
		}

		public string GetHoverText()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			string text;
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				text = m_name + "\n$piece_noaccess";
			}
			else
			{
				string text2 = string.Empty;
				if ((Object)(object)m_requiredItem != (Object)null && m_requiredItem.m_itemData != null && m_requiredItem.m_itemData.m_shared != null)
				{
					text2 = m_requiredItem.m_itemData.m_shared.m_name;
				}
				text = m_name + "\n[<color=yellow><b>1-8</b></color>] \n" + m_useItemText + " " + text2;
			}
			return (Localization.instance != null) ? Localization.instance.Localize(text) : text;
		}

		public string GetHoverName()
		{
			return m_name;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			return !hold;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer || item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return true;
			}
			if (!CheckUsable((Player)(object)((user is Player) ? user : null), showMessage: true))
			{
				return true;
			}
			if (!string.Equals(((Object)item.m_dropPrefab).name, "CustomPackageItem_bal", StringComparison.Ordinal))
			{
				((Character)user).Message((MessageType)2, "$tag_cant_unpack", 0, (Sprite)null, false);
				return true;
			}
			if (!TryDeserializePackage(item, out var unpackedItems))
			{
				((Character)user).Message((MessageType)2, "$piece_packager_fail", 0, (Sprite)null, false);
				return true;
			}
			Vector3 spawnPosition = GetSpawnPosition();
			if (m_spawnStartEffects != null)
			{
				m_spawnStartEffects.Create(spawnPosition, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			if (!SpawnItems(unpackedItems, spawnPosition))
			{
				((Character)user).Message((MessageType)2, "$piece_packager_fail", 0, (Sprite)null, false);
				return true;
			}
			if (m_spawnFinishEffects != null)
			{
				m_spawnFinishEffects.Create(spawnPosition, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			((Character)user).ShowRemovedMessage(item, 1);
			user.GetInventory().RemoveItem(item, 1);
			((Character)user).Message((MessageType)2, "$tag_unpacked_it", 0, (Sprite)null, false);
			return true;
		}

		public bool CheckUsable(Player player, bool showMessage)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (m_requiresRoof && !player.NoCostCheat())
			{
				if ((Object)(object)m_roofCheckPoint == (Object)null)
				{
					return false;
				}
				float num = default(float);
				bool flag = default(bool);
				Cover.GetCoverForPoint(m_roofCheckPoint.position, ref num, ref flag, 0.5f);
				if (!flag)
				{
					if (showMessage)
					{
						((Character)player).Message((MessageType)2, "$msg_stationneedroof", 0, (Sprite)null, false);
					}
					return false;
				}
				if (num < 0.7f)
				{
					if (showMessage)
					{
						((Character)player).Message((MessageType)2, "$msg_stationtooexposed", 0, (Sprite)null, false);
					}
					return false;
				}
			}
			return true;
		}

		private Vector3 GetSpawnPosition()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return ((Object)(object)m_itemSpawnPoint != (Object)null) ? m_itemSpawnPoint.position : ((Component)this).transform.position;
		}

		private static bool TryDeserializePackage(ItemData packageItem, out List<ItemData> unpackedItems)
		{
			unpackedItems = null;
			if (packageItem == null || packageItem.m_customData == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			if (!PackageMetadata.TryGetInt(packageItem, "BalrondPackageAmount", out var value) || value <= 0 || value > 256)
			{
				return false;
			}
			int formatVersion = PackageMetadata.GetFormatVersion(packageItem);
			if (formatVersion > 3)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Unsupported package format version " + formatVersion + "."));
				return false;
			}
			List<ItemData> list = new List<ItemData>(value);
			for (int i = 0; i < value; i++)
			{
				if (!TryDeserializeEntry(packageItem, i, formatVersion, out var restored))
				{
					return false;
				}
				list.Add(restored);
			}
			unpackedItems = list;
			return true;
		}

		private static bool TryDeserializeEntry(ItemData packageItem, int index, int formatVersion, out ItemData restored)
		{
			restored = null;
			if (formatVersion >= 3)
			{
				if (!packageItem.m_customData.TryGetValue("BalrondPackagePrefab-" + index, out var value) || !packageItem.m_customData.TryGetValue("BalrondPackageData-" + index, out var value2) || string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value2))
				{
					return false;
				}
				return PackageItemSerializer.TryDeserialize(value, value2, out restored);
			}
			if (!packageItem.m_customData.TryGetValue("BalrondPackageIndex-" + index, out var value3) || string.IsNullOrEmpty(value3))
			{
				return false;
			}
			int num = value3.LastIndexOf('.');
			if (num <= 0 || num >= value3.Length - 1)
			{
				return false;
			}
			string text = value3.Substring(0, num);
			if (!int.TryParse(value3.Substring(num + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result <= 0)
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null || val.m_itemData == null || val.m_itemData.m_shared == null)
			{
				return false;
			}
			restored = val.m_itemData.Clone();
			restored.m_shared = val.m_itemData.m_shared;
			restored.m_dropPrefab = itemPrefab;
			restored.m_stack = result;
			restored.m_equipped = false;
			return true;
		}

		private static bool SpawnItems(List<ItemData> items, Vector3 spawnPosition)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (items == null || items.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < items.Count; i++)
			{
				ItemData val = items[i];
				if (val == null || (Object)(object)val.m_dropPrefab == (Object)null || val.m_stack <= 0)
				{
					return false;
				}
				ItemDrop val2 = ItemDrop.DropItem(val, val.m_stack, spawnPosition, Quaternion.identity);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
			}
			return true;
		}
	}
	public sealed class DatabaseAddMethods
	{
		public bool AddItems(ObjectDB db, List<GameObject> items)
		{
			if ((Object)(object)db == (Object)null || db.m_items == null || items == null || items.Count == 0)
			{
				return false;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			for (int i = 0; i < db.m_items.Count; i++)
			{
				GameObject val = db.m_items[i];
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
				{
					hashSet.Add(((Object)val).name);
				}
			}
			bool result = false;
			for (int j = 0; j < items.Count; j++)
			{
				GameObject val2 = items[j];
				if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name) && !hashSet.Contains(((Object)val2).name))
				{
					ItemDrop component = val2.GetComponent<ItemDrop>();
					if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
					{
						Debug.LogWarning((object)(Launch.projectName + ": Invalid item prefab skipped from ObjectDB: " + ((Object)val2).name));
						continue;
					}
					db.m_items.Add(val2);
					hashSet.Add(((Object)val2).name);
					result = true;
				}
			}
			return result;
		}

		public bool AddRecipes(ObjectDB db, List<Recipe> recipes)
		{
			if ((Object)(object)db == (Object)null || db.m_recipes == null || recipes == null || recipes.Count == 0)
			{
				return false;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			for (int i = 0; i < db.m_recipes.Count; i++)
			{
				Recipe val = db.m_recipes[i];
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
				{
					hashSet.Add(((Object)val).name);
				}
			}
			bool result = false;
			for (int j = 0; j < recipes.Count; j++)
			{
				Recipe val2 = recipes[j];
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.m_item == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name) && !hashSet.Contains(((Object)val2).name))
				{
					db.m_recipes.Add(val2);
					hashSet.Add(((Object)val2).name);
					result = true;
				}
			}
			return result;
		}

		public bool AddStatusEffects(ObjectDB db, List<StatusEffect> statusEffects)
		{
			if ((Object)(object)db == (Object)null || db.m_StatusEffects == null || statusEffects == null || statusEffects.Count == 0)
			{
				return false;
			}
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 0; i < db.m_StatusEffects.Count; i++)
			{
				StatusEffect val = db.m_StatusEffects[i];
				if ((Object)(object)val != (Object)null)
				{
					hashSet.Add(val.NameHash());
				}
			}
			bool result = false;
			for (int j = 0; j < statusEffects.Count; j++)
			{
				StatusEffect val2 = statusEffects[j];
				if (!((Object)(object)val2 == (Object)null) && !hashSet.Contains(val2.NameHash()))
				{
					db.m_StatusEffects.Add(val2);
					hashSet.Add(val2.NameHash());
					result = true;
				}
			}
			return result;
		}
	}
	public sealed class ModResourceLoader
	{
		public AssetBundle assetBundle;

		public readonly List<GameObject> buildPrefabs = new List<GameObject>();

		public readonly List<GameObject> plantPrefabs = new List<GameObject>();

		public readonly List<GameObject> itemPrefabs = new List<GameObject>();

		public readonly List<GameObject> monsterPrefabs = new List<GameObject>();

		public readonly List<GameObject> vegetationPrefabs = new List<GameObject>();

		public readonly List<GameObject> clutterPrefabs = new List<GameObject>();

		public readonly List<GameObject> locationPrefabs = new List<GameObject>();

		public readonly List<GameObject> roomPrefabs = new List<GameObject>();

		public readonly List<GameObject> vfxPrefabs = new List<GameObject>();

		public readonly List<Sprite> backgrounds = new List<Sprite>();

		public readonly List<Recipe> recipes = new List<Recipe>();

		public readonly List<StatusEffect> statusEffects = new List<StatusEffect>();

		public void LoadAssets()
		{
			ClearLoadedCollections();
			assetBundle = GetAssetBundleFromResources("balrondpackager");
			if ((Object)(object)assetBundle == (Object)null)
			{
				Debug.LogError((object)(Launch.projectName + ": embedded AssetBundle 'balrondpackager' was not found or could not be loaded."));
				return;
			}
			LoadPieces("Assets/Custom/Comission/BalrondPackager/");
			LoadItems("Assets/Custom/Comission/BalrondPackager/");
			LoadOther("Assets/Custom/Comission/BalrondPackager/");
		}

		private void ClearLoadedCollections()
		{
			buildPrefabs.Clear();
			plantPrefabs.Clear();
			itemPrefabs.Clear();
			monsterPrefabs.Clear();
			vegetationPrefabs.Clear();
			clutterPrefabs.Clear();
			locationPrefabs.Clear();
			roomPrefabs.Clear();
			vfxPrefabs.Clear();
			backgrounds.Clear();
			recipes.Clear();
			statusEffects.Clear();
		}

		public void AddPrefabsToZnetScene(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			HashSet<int> hashSet2 = new HashSet<int>();
			for (int i = 0; i < zNetScene.m_prefabs.Count; i++)
			{
				GameObject val = zNetScene.m_prefabs[i];
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name))
				{
					hashSet.Add(((Object)val).name);
					hashSet2.Add(StringExtensionMethods.GetStableHashCode(((Object)val).name));
				}
			}
			AddUniquePrefabs(itemPrefabs, zNetScene, hashSet, hashSet2, requireZNetView: true);
			AddUniquePrefabs(plantPrefabs, zNetScene, hashSet, hashSet2, requireZNetView: true);
			AddUniquePrefabs(vfxPrefabs, zNetScene, hashSet, hashSet2, requireZNetView: false);
			AddUniquePrefabs(buildPrefabs, zNetScene, hashSet, hashSet2, requireZNetView: true);
			Launch.buildPieceBuilder.SetupBuildPieces(zNetScene.m_prefabs);
			SetupBuildPiecesList(zNetScene);
			SetupPackager(zNetScene);
			SetupUnpackager(zNetScene);
		}

		private static void AddUniquePrefabs(List<GameObject> prefabs, ZNetScene zNetScene, HashSet<string> names, HashSet<int> hashes, bool requireZNetView)
		{
			if (prefabs == null)
			{
				return;
			}
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(((Object)val).name))
				{
					continue;
				}
				if (requireZNetView && (Object)(object)val.GetComponent<ZNetView>() == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": network prefab skipped because it has no ZNetView: " + ((Object)val).name));
					continue;
				}
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name);
				if (names.Contains(((Object)val).name))
				{
					Debug.LogWarning((object)(Launch.projectName + ": duplicate ZNetScene prefab name skipped: " + ((Object)val).name));
				}
				else if (hashes.Contains(stableHashCode))
				{
					Debug.LogWarning((object)(Launch.projectName + ": ZNetScene stable-hash collision skipped: " + ((Object)val).name + " (" + stableHashCode + ")"));
				}
				else
				{
					zNetScene.m_prefabs.Add(val);
					names.Add(((Object)val).name);
					hashes.Add(stableHashCode);
				}
			}
		}

		private void SetupBuildPiecesList(ZNetScene zNetScene)
		{
			GameObject val = FindPrefab(zNetScene.m_prefabs, "Hammer");
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			PieceTable val3 = (((Object)(object)val2 != (Object)null && val2.m_itemData != null && val2.m_itemData.m_shared != null) ? val2.m_itemData.m_shared.m_buildPieces : null);
			if ((Object)(object)val3 == (Object)null || val3.m_pieces == null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Hammer PieceTable not available during ZNetScene setup."));
				return;
			}
			string[] array = new string[4] { "Hammer", "HammerIron_bal", "HammerDverger_bal", "HammerBlackmetal_bal" };
			for (int i = 0; i < array.Length; i++)
			{
				AddTableToTool(array[i], val3, zNetScene.m_prefabs);
			}
			for (int j = 0; j < buildPrefabs.Count; j++)
			{
				GameObject val4 = buildPrefabs[j];
				if (!((Object)(object)val4 == (Object)null) && !string.IsNullOrEmpty(((Object)val4).name))
				{
					GameObject val5 = FindPrefab(zNetScene.m_prefabs, ((Object)val4).name);
					if ((Object)(object)val5 == (Object)null)
					{
						Debug.LogWarning((object)(Launch.projectName + ": build prefab is not registered in ZNetScene and will not be added to Hammer: " + ((Object)val4).name));
						continue;
					}
					SetupRavenGuide(val5, zNetScene.m_prefabs);
					AddToBuildList(val5, val3.m_pieces);
				}
			}
		}

		private static void AddTableToTool(string name, PieceTable pieceTable, List<GameObject> prefabs)
		{
			GameObject val = FindPrefab(prefabs, name);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val2 == (Object)null) && val2.m_itemData != null && val2.m_itemData.m_shared != null)
			{
				val2.m_itemData.m_shared.m_buildPieces = pieceTable;
			}
		}

		public static void SetupRavenGuide(GameObject gameObject, List<GameObject> prefabs)
		{
			if ((Object)(object)gameObject == (Object)null || prefabs == null)
			{
				return;
			}
			Transform val = gameObject.transform.Find("GuidePoint");
			GuidePoint val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<GuidePoint>() : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				GameObject val3 = FindPrefab(prefabs, "piece_workbench");
				Transform val4 = (((Object)(object)val3 != (Object)null) ? val3.transform.Find("GuidePoint") : null);
				GuidePoint val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<GuidePoint>() : null);
				if ((Object)(object)val5 != (Object)null)
				{
					val2.m_ravenPrefab = val5.m_ravenPrefab;
				}
			}
		}

		private static bool AddToBuildList(GameObject prefab, List<GameObject> buildPieces)
		{
			if ((Object)(object)prefab == (Object)null || buildPieces == null)
			{
				return false;
			}
			for (int i = 0; i < buildPieces.Count; i++)
			{
				GameObject val = buildPieces[i];
				if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, ((Object)prefab).name, StringComparison.Ordinal))
				{
					return false;
				}
			}
			buildPieces.Add(prefab);
			return true;
		}

		private static GameObject FindPrefab(List<GameObject> prefabs, string name)
		{
			if (prefabs == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.Ordinal))
				{
					return val;
				}
			}
			return null;
		}

		private static AssetBundle GetAssetBundleFromResources(string filenameSuffix)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
			string text = null;
			for (int i = 0; i < manifestResourceNames.Length; i++)
			{
				if (manifestResourceNames[i].EndsWith(filenameSuffix, StringComparison.OrdinalIgnoreCase))
				{
					text = manifestResourceNames[i];
					break;
				}
			}
			if (text == null)
			{
				return null;
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			return (stream != null) ? AssetBundle.LoadFromStream(stream) : null;
		}

		private void LoadPieces(string basePath)
		{
			string mainPath = basePath + "Pieces/";
			for (int i = 0; i < BuildPieceList.buildPieces.Length; i++)
			{
				LoadPrefab(mainPath, BuildPieceList.buildPieces[i], buildPrefabs, "piece");
			}
		}

		private void LoadItems(string basePath)
		{
			string mainPath = basePath + "Items/";
			for (int i = 0; i < ItemList.items.Length; i++)
			{
				LoadPrefab(mainPath, ItemList.items[i], itemPrefabs, "item");
			}
		}

		private void LoadOther(string basePath)
		{
		}

		private void LoadPrefab(string mainPath, string name, List<GameObject> target, string kind)
		{
			if (!((Object)(object)assetBundle == (Object)null) && !string.IsNullOrEmpty(name))
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(mainPath + name + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": could not find " + kind + " prefab: " + name + " at " + mainPath));
				}
				else
				{
					ShaderReplacment.Replace(val);
					target.Add(val);
				}
			}
		}

		private void SetupPackager(ZNetScene zNetScene)
		{
			GameObject val = FindPrefab(zNetScene.m_prefabs, "packager_bal");
			if (!((Object)(object)val == (Object)null))
			{
				BalrondPackager balrondPackager = val.GetComponent<BalrondPackager>();
				if ((Object)(object)balrondPackager == (Object)null)
				{
					balrondPackager = val.AddComponent<BalrondPackager>();
				}
				Incinerator component = val.GetComponent<Incinerator>();
				if ((Object)(object)component != (Object)null)
				{
					balrondPackager.m_container = component.m_container;
					balrondPackager.m_leverAnim = component.m_leverAnim;
					balrondPackager.m_leverEffects = component.m_leverEffects;
					balrondPackager.m_incinerateSwitch = component.m_incinerateSwitch;
					Transform val2 = val.transform.Find("_enabled");
					balrondPackager.m_enabled = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null);
					balrondPackager.output = val.transform.Find("output");
					Object.Destroy((Object)(object)component);
				}
				GameObject val3 = FindPrefab(zNetScene.m_prefabs, "CustomPackageItem_bal");
				balrondPackager.m_defaultResult = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<ItemDrop>() : null);
				balrondPackager.m_defaultCost = 1;
				if ((Object)(object)balrondPackager.m_defaultResult != (Object)null && balrondPackager.m_defaultResult.m_itemData != null && balrondPackager.m_defaultResult.m_itemData.m_shared != null)
				{
					balrondPackager.m_defaultResult.m_itemData.m_shared.m_maxStackSize = 1;
					balrondPackager.m_defaultResult.m_itemData.m_shared.m_autoStack = false;
					balrondPackager.m_defaultResult.m_itemData.m_shared.m_description = "$tag_packagebundle_description";
				}
				if ((Object)(object)balrondPackager.m_container == (Object)null || (Object)(object)balrondPackager.m_incinerateSwitch == (Object)null || (Object)(object)balrondPackager.output == (Object)null || (Object)(object)balrondPackager.m_defaultResult == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": packager prefab is missing one or more required references."));
				}
			}
		}

		private void SetupUnpackager(ZNetScene zNetScene)
		{
			GameObject val = FindPrefab(zNetScene.m_prefabs, "unpackager_bal");
			if (!((Object)(object)val == (Object)null))
			{
				BalrondUnpackager balrondUnpackager = val.GetComponent<BalrondUnpackager>();
				if ((Object)(object)balrondUnpackager == (Object)null)
				{
					balrondUnpackager = val.AddComponent<BalrondUnpackager>();
				}
				balrondUnpackager.m_requiresRoof = false;
				GameObject val2 = FindPrefab(zNetScene.m_prefabs, "CustomPackageItem_bal");
				balrondUnpackager.m_requiredItem = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<ItemDrop>() : null);
				balrondUnpackager.m_itemSpawnPoint = val.transform.Find("spawnpoint");
				balrondUnpackager.m_roofCheckPoint = val.transform.Find("roof_check_pint");
				if ((Object)(object)balrondUnpackager.m_itemSpawnPoint == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": unpackager spawnpoint not found; transform position will be used."));
				}
			}
		}
	}
	public class ShaderReplacment
	{
		public static readonly List<GameObject> prefabsToReplaceShader = new List<GameObject>();

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

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

		public static bool debug = true;

		private static readonly HashSet<GameObject> PrefabSet = new HashSet<GameObject>();

		private static readonly HashSet<Material> MaterialSet = new HashSet<Material>();

		private static readonly Dictionary<string, Shader> ShaderByName = new Dictionary<string, Shader>(StringComparer.Ordinal);

		private static bool shadersIndexed;

		private static bool materialFixApplied;

		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 void Replace(GameObject gameObject)
		{
			if (!((Object)(object)gameObject == (Object)null))
			{
				if (PrefabSet.Add(gameObject))
				{
					prefabsToReplaceShader.Add(gameObject);
				}
				GetMaterialsInPrefab(gameObject);
			}
		}

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

		private static void IndexLoadedShaders()
		{
			if (shadersIndexed)
			{
				return;
			}
			shadersIndexed = true;
			ShaderByName.Clear();
			shaders.Clear();
			Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
			Shader[] array2 = array;
			foreach (Shader val in array2)
			{
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && !ShaderByName.ContainsKey(((Object)val).name))
				{
					ShaderByName.Add(((Object)val).name, val);
					shaders.Add(val);
				}
			}
		}

		public static Shader findShader(string name)
		{
			return GetShaderByName(name);
		}

		public static Shader GetShaderByName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return null;
			}
			IndexLoadedShaders();
			name = name.Trim();
			if (ShaderByName.TryGetValue(name, out var value))
			{
				return value;
			}
			value = Shader.Find(name);
			if ((Object)(object)value != (Object)null)
			{
				ShaderByName[name] = value;
				if (!shaders.Contains(value))
				{
					shaders.Add(value);
				}
			}
			return value;
		}

		public static void getMeShaders()
		{
			IndexLoadedShaders();
		}

		public static void debugShaderList(List<Shader> shaderList)
		{
			if (shaderList == null)
			{
				return;
			}
			foreach (Shader shader in shaderList)
			{
				if ((Object)(object)shader != (Object)null)
				{
					Debug.LogWarning((object)("SHADER NAME IS: " + ((Object)shader).name));
				}
			}
			debug = false;
		}

		public static void runMaterialFix()
		{
			if (materialFixApplied)
			{
				return;
			}
			materialFixApplied = true;
			IndexLoadedShaders();
			int num = 0;
			int num2 = 0;
			foreach (Material materialsInPrefab in materialsInPrefabs)
			{
				if ((Object)(object)materialsInPrefab == (Object)null || (Object)(object)materialsInPrefab.shader == (Object)null)
				{
					continue;
				}
				string name = ((Object)materialsInPrefab.shader).name;
				if (!string.IsNullOrEmpty(name) && !(name == "Standard") && name.IndexOf("ScrollingTex", StringComparison.Ordinal) < 0 && name.IndexOf("Balrond", StringComparison.Ordinal) >= 0)
				{
					string text = checkNaming(name.Replace("Balrond", "Custom"));
					Shader shaderByName = GetShaderByName(text);
					if ((Object)(object)shaderByName == (Object)null)
					{
						num2++;
						Debug.LogWarning((object)(Launch.projectName + ": shader replacement not found: " + name + " -> " + text));
					}
					else
					{
						materialsInPrefab.shader = shaderByName;
						num++;
					}
				}
			}
			Debug.Log((object)$"{Launch.projectName}: shader material pass complete: replaced={num}, unresolved={num2}, uniqueMaterials={materialsInPrefabs.Count}.");
		}

		private static string checkNaming(string name)
		{
			if (name.IndexOf("Tess Bumped", StringComparison.Ordinal) >= 0 || name.IndexOf("Bumped", StringComparison.Ordinal) >= 0)
			{
				return name.Replace("Custom", "Lux Lit Particles");
			}
			if (name.IndexOf("Standard Surface", StringComparison.Ordinal) >= 0)
			{
				return name.Replace("Custom", "Particles").Replace("Standard Surface2", "Standard Surface");
			}
			if (name.IndexOf("Standard Unlit", StringComparison.Ordinal) >= 0)
			{
				return name.Replace("Custom", "Particles").Replace("Standard Unlit", "Standard Unlit2").Replace("Standard Unlit22", "Standard Unlit2");
			}
			return name;
		}
	}
	public static class TableMapper
	{
		public static CraftingStation cauldron;

		public static CraftingStation workbench;

		public static CraftingStation heavyWorkbench;

		public static CraftingStation forge;

		public static CraftingStation ironworks;

		public static CraftingStation blackforge;

		public static CraftingStation stoneCutter;

		public static CraftingStation artisian;

		public static CraftingStation magetable;

		public static CraftingStation runeforge;

		public static CraftingStation tannery;

		public static CraftingStation fletcher;

		public static CraftingStation grill;

		public static CraftingStation alchemylab;

		public static void setupTables(List<GameObject> prefabs)
		{
			if (prefabs == null)
			{
				return;
			}
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.Ordinal);
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name) && !dictionary.ContainsKey(((Object)val).name))
				{
					dictionary.Add(((Object)val).name, val);
				}
			}
			cauldron = FindStation(dictionary, "piece_cauldron");
			workbench = FindStation(dictionary, "piece_workbench");
			heavyWorkbench = FindStation(dictionary, "piece_heavy_workbench_bal", warn: false);
			forge = FindStation(dictionary, "forge");
			ironworks = FindStation(dictionary, "piece_metalworks_bal", warn: false);
			blackforge = FindStation(dictionary, "blackforge", warn: false);
			stoneCutter = FindStation(dictionary, "piece_stonecutter", warn: false);
			artisian = FindStation(dictionary, "piece_artisanstation", warn: false);
			runeforge = FindStation(dictionary, "piece_runeforge_bal", warn: false);
			magetable = FindStation(dictionary, "piece_magetable", warn: false);
			fletcher = FindStation(dictionary, "piece_fletcher_bal", warn: false);
		}

		private static CraftingStation FindStation(Dictionary<string, GameObject> byName, string name, bool warn = true)
		{
			if (byName.TryGetValue(name, out var value) && (Object)(object)value != (Object)null)
			{
				return value.GetComponent<CraftingStation>();
			}
			if (warn)
			{
				Debug.LogWarning((object)(Launch.projectName + ": crafting station not found: " + name));
			}
			return null;
		}
	}
	internal class ItemList
	{
		public static string[] items = new string[1] { "CustomPackageItem_bal" };
	}
	public sealed class JsonLoader
	{
		public string defaultPath = string.Empty;

		public void loadJson()
		{
			defaultPath = GetTranslationPath();
			LoadTranslations(defaultPath);
		}

		public void justDefaultPath()
		{
			defaultPath = GetTranslationPath();
		}

		public void createDefaultPath()
		{
			defaultPath = GetTranslationPath();
			EnsureDirectory(defaultPath);
		}

		private static string GetTranslationPath()
		{
			return Path.Combine(Paths.ConfigPath, "BalrondPackager-translation");
		}

		private static void EnsureDirectory(string path)
		{
			try
			{
				Directory.CreateDirectory(path);
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("BalrondPackager: failed to create translation directory: " + ex.Message));
			}
		}

		private static void LoadTranslations(string path)
		{
			EnsureDirectory(path);
			BalrondTranslator.translations.Clear();
			string[] files;
			try
			{
				files = Directory.GetFiles(path, "*.json");
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("BalrondPackager: failed to enumerate translation files: " + ex.Message));
				return;
			}
			int num = 0;
			foreach (string text in files)
			{
				try
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
					JsonData jsonData = JsonMapper.ToObject(File.ReadAllText(text));
					Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
					foreach (string key in jsonData.Keys)
					{
						dictionary[key] = ((jsonData[key] != null) ? jsonData[key].ToString() : string.Empty);
					}
					BalrondTranslator.translations[fileNameWithoutExtension] = dictionary;
					num++;
				}
				catch (Exception ex2)
				{
					Debug.LogWarning((object)("BalrondPackager: failed to load translation '" + text + "': " + ex2.Message));
				}
			}
			Debug.Log((object)("BalrondPackager: translation files loaded: " + num));
		}
	}
	[BepInPlugin("balrond.astafaraios.BalrondPackager", "BalrondPackager", "1.1.2")]
	public sealed class Launch : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(FejdStartup), "SetupGui")]
		private static class FejdStartup_SetupGUI
		{
			private static void Postfix()
			{
				if (Localization.instance != null)
				{
					AddTranslations(Localization.instance, Localization.instance.GetSelectedLanguage());
				}
			}
		}

		[HarmonyPatch(typeof(AudioMan), "Awake")]
		private static class AudioMan_Awake_Patch
		{
			private static void Postfix(AudioMan __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_masterMixer == (Object)null))
				{
					ApplyMixer(modResourceLoader.itemPrefabs, __instance);
					ApplyMixer(modResourceLoader.buildPrefabs, __instance);
					ApplyMixer(modResourceLoader.monsterPrefabs, __instance);
					ApplyMixer(modResourceLoader.vfxPrefabs, __instance);
					ApplyMixer(modResourceLoader.vegetationPrefabs, __instance);
				}
			}

			private static void ApplyMixer(List<GameObject> prefabs, AudioMan audioMan)
			{
				if (prefabs == null)
				{
					return;
				}
				for (int i = 0; i < prefabs.Count; i++)
				{
					GameObject val = prefabs[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>(true);
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						if ((Object)(object)componentsInChildren[j] != (Object)null)
						{
							componentsInChildren[j].outputAudioMixerGroup = audioMan.m_masterMixer.outputAudioMixerGroup;
						}
					}
				}
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Prefix(ObjectDB __instance)
			{
				PrepareObjectDB(__instance);
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB", new Type[] { typeof(ObjectDB) })]
		private static class ObjectDB_CopyOtherDB_Patch
		{
			private static void Prefix(ObjectDB __0)
			{
				PrepareObjectDB(__0);
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake_Patch
		{
			private static void Prefix(ZNetScene __instance)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					modResourceLoader.AddPrefabsToZnetScene(__instance);
					if ((Object)(object)ObjectDB.instance != (Object)null)
					{
						ObjectDB.instance.m_buildPieces = null;
					}
				}
			}

			private static void Postfix()
			{
				if (!s_materialFixApplied && ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()))
				{
					ShaderReplacment.runMaterialFix();
					s_materialFixApplied = true;
				}
			}
		}

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private static class Translation_SetupLanguage
		{
			private static void Postfix(Localization __instance, string __0)
			{
				AddTranslations(__instance, __0);
			}
		}

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

		public const string PluginName = "BalrondPackager";

		public const string PluginVersion = "1.1.2";

		public static readonly ModResourceLoader modResourceLoader = new ModResourceLoader();

		public static readonly DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods();

		public static readonly BuildPieceBuilder buildPieceBuilder = new BuildPieceBuilder();

		public static readonly JsonLoader jsonLoader = new JsonLoader();

		public static GameObject RootObject;

		public static GameObject PrefabContainer;

		public static string projectName = "BalrondPackager";

		private readonly Harmony m_harmony = new Harmony("balrond.astafaraios.BalrondPackager");

		private static bool s_materialFixApplied;

		private void Awake()
		{
			jsonLoader.loadJson();
			CreatePrefabContainer();
			modResourceLoader.LoadAssets();
			RegisterCompatibilityPatches();
		}

		private void RegisterCompatibilityPatches()
		{
			int num = 0;
			num += PatchClass(typeof(FejdStartup_SetupGUI));
			num += PatchClass(typeof(AudioMan_Awake_Patch));
			num += PatchClass(typeof(ObjectDB_Awake_Patch));
			num += PatchClass(typeof(ObjectDB_CopyOtherDB_Patch));
			num += PatchClass(typeof(ZNetScene_Awake_Patch));
			num += PatchClass(typeof(Translation_SetupLanguage));
			num += PatchClass(typeof(PackageItemWeightPatch));
			num += PatchClass(typeof(PackageItemTooltipPatch));
			num += PatchClass(typeof(PackageInventoryTeleportPatch));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Valheim Deep North publicized compatibility patches registered: " + num + "."));
		}

		private int PatchClass(Type patchType)
		{
			try
			{
				m_harmony.CreateClassProcessor(patchType).Patch();
				return 1;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch " + patchType.FullName + ": " + ex));
				return 0;
			}
		}

		private static void CreatePrefabContainer()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (!((Object)(object)RootObject != (Object)null))
			{
				RootObject = new GameObject("_BalrondPackagerRoot");
				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)("BalrondPackager: CloneMe source is null for " + name));
				return null;
			}
			if ((Object)(object)PrefabContainer == (Object)null)
			{
				CreatePrefabContainer();
			}
			GameObject val = Object.Instantiate<GameObject>(source, PrefabContainer.transform);
			((Object)val).name = name;
			FixMaterials(val, source);
			val.SetActive(true);
			return val;
		}

		public static GameObject FixMaterials(GameObject clone, GameObject source)
		{
			if ((Object)(object)clone == (Object)null || (Object)(object)source == (Object)null)
			{
				return clone;
			}
			MeshRenderer[] componentsInChildren = source.GetComponentsInChildren<MeshRenderer>(true);
			MeshRenderer[] componentsInChildren2 = clone.GetComponentsInChildren<MeshRenderer>(true);
			int num = Mathf.Min(componentsInChildren.Length, componentsInChildren2.Length);
			for (int i = 0; i < num; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren2[i] != (Object)null)
				{
					((Renderer)componentsInChildren2[i]).sharedMaterials = ((Renderer)componentsInChildren[i]).sharedMaterials;
				}
			}
			return clone;
		}

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

		private static void AddTranslations(Localization localization, string language)
		{
			if (localization == null)
			{
				return;
			}
			string text = (string.IsNullOrEmpty(language) ? "English" : language);
			Dictionary<string, string> language2 = BalrondTranslator.getLanguage(text);
			if (language2 == null)
			{
				language2 = BalrondTranslator.getLanguage("English");
				if (language2 == null)
				{
					Debug.LogWarning((object)("BalrondPackager: No translation data found for '" + text + "' or English."));
					return;
				}
			}
			foreach (KeyValuePair<string, string> item in language2)
			{
				if (!string.IsNullOrEmpty(item.Key))
				{
					localization.AddWord(item.Key, item.Value ?? string.Empty);
				}
			}
		}

		private static void PrepareObjectDB(ObjectDB db)
		{
			if (!((Object)(object)db == (Object)null))
			{
				databaseAddMethods.AddItems(db, modResourceLoader.itemPrefabs);
				databaseAddMethods.AddStatusEffects(db, modResourceLoader.statusEffects);
				databaseAddMethods.AddRecipes(db, modResourceLoader.recipes);
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetWeight", new Type[] { typeof(int) })]
	internal static class PackageItemWeightPatch
	{
		private static void Postfix(ItemData __instance, int __0, ref float __result)
		{
			if (PackageMetadata.TryGetWeight(__instance, out var weight))
			{
				int num = ((__0 < 0) ? __instance.m_stack : __0);
				if (num < 0)
				{
					num = 0;
				}
				__result = weight * (float)num;
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(int) })]
	internal static class PackageItemTooltipPatch
	{
		private static void Postfix(ItemData __instance, ref string __result)
		{
			if (PackageMetadata.TryGetDescription(__instance, out var description))
			{
				if (Localization.instance != null)
				{
					description = Localization.instance.Localize(description);
				}
				if (string.IsNullOrEmpty(__result))
				{
					__result = description;
				}
				else
				{
					__result = __result + "\n" + description;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "IsTeleportable", new Type[] { typeof(bool) })]
	internal static class PackageInventoryTeleportPatch
	{
		private static bool Prefix(Inventory __instance, bool __0, ref bool __result)
		{
			if (__instance == null)
			{
				return true;
			}
			List<ItemData> allItems = __instance.GetAllItems();
			if (allItems == null || allItems.Count == 0)
			{
				return true;
			}
			bool flag = false;
			for (int i = 0; i < allItems.Count; i++)
			{
				if (PackageMetadata.HasPackagePayload(allItems[i]))
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return true;
			}
			for (int j = 0; j < allItems.Count; j++)
			{
				ItemData val = allItems[j];
				if (val != null && ((val.m_shared != null && val.m_shared.m_toolTier >= 1000) || PackageMetadata.IsHardNoTeleport(val)))
				{
					__result = false;
					return false;
				}
			}
			if (__0 || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)35)))
			{
				__result = true;
				return false;
			}
			for (int k = 0; k < allItems.Count; k++)
			{
				if (!PackageMetadata.IsItemTeleportable(allItems[k]))
				{
					__result = false;
					return false;
				}
			}
			__result = true;
			return false;
		}
	}
	internal static class PackageItemSerializer
	{
		private const int SerializerVersion = 1;

		internal static bool TrySerialize(ItemData item, out string encoded)
		{
			encoded = null;
			if (item == null || item.m_shared == null || (Object)(object)item.m_dropPrefab == (Object)null || item.m_stack <= 0)
			{
				return false;
			}
			try
			{
				using (MemoryStream memoryStream = new MemoryStream(256))
				{
					using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
					binaryWriter.Write(1);
					binaryWriter.Write(item.m_stack);
					binaryWriter.Write(item.m_durability);
					binaryWriter.Write(item.m_quality);
					binaryWriter.Write(item.m_variant);
					binaryWriter.Write(item.m_crafterID);
					binaryWriter.Write(item.m_crafterName ?? string.Empty);
					binaryWriter.Write(item.m_worldLevel);
					Dictionary<string, string> customData = item.m_customData;
					int num = customData?.Count ?? 0;
					if (num < 0 || num > 1024)
					{
						return false;
					}
					binaryWriter.Write(num);
					if (customData != null)
					{
						foreach (KeyValuePair<string, string> item2 in customData)
						{
							string text = item2.Key ?? string.Empty;
							string text2 = item2.Value ?? string.Empty;
							if (text.Length > 131072 || text2.Length > 131072)
							{
								return false;
							}
							binaryWriter.Write(text);
							binaryWriter.Write(text2);
						}
					}
					binaryWriter.Flush();
					encoded = Convert.ToBase64String(memoryStream.ToArray());
				}
				return !string.IsNullOrEmpty(encoded) && encoded.Length <= 262144;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Failed to serialize packed item: " + ex.Message));
				encoded = null;
				return false;
			}
		}

		internal static bool TryDeserialize(string prefabName, string encoded, out ItemData restored)
		{
			restored = null;
			if (string.IsNullOrEmpty(prefabName) || string.IsNullOrEmpty(encoded) || encoded.Length > 262144 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null || val.m_itemData == null || val.m_itemData.m_shared == null)
			{
				return false;
			}
			try
			{
				byte[] buffer = Convert.FromBase64String(encoded);
				using MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				int num = binaryReader.ReadInt32();
				if (num != 1)
				{
					return false;
				}
				int num2 = binaryReader.ReadInt32();
				float num3 = binaryReader.ReadSingle();
				int num4 = binaryReader.ReadInt32();
				int num5 = binaryReader.ReadInt32();
				long crafterID = binaryReader.ReadInt64();
				string text = binaryReader.ReadString();
				int num6 = binaryReader.ReadInt32();
				int num7 = binaryReader.ReadInt32();
				if (num2 <= 0 || num4 <= 0 || num5 < 0 || num6 < 0 || float.IsNaN(num3) || float.IsInfinity(num3) || num3 < 0f || num7 < 0 || num7 > 1024 || text.Length > 131072)
				{
					return false;
				}
				Dictionary<string, string> dictionary = new Dictionary<string, string>(num7, StringComparer.Ordinal);
				for (int i = 0; i < num7; i++)
				{
					string text2 = binaryReader.ReadString();
					string text3 = binaryReader.ReadString();
					if (text2.Length > 131072 || text3.Length > 131072)
					{
						return false;
					}
					dictionary[text2] = text3;
				}
				if (memoryStream.Position != memoryStream.Length)
				{
					return false;
				}
				ItemData val2 = val.m_itemData.Clone();
				val2.m_shared = val.m_itemData.m_shared;
				val2.m_dropPrefab = itemPrefab;
				val2.m_stack = num2;
				val2.m_durability = num3;
				val2.m_quality = num4;
				val2.m_variant = num5;
				val2.m_crafterID = crafterID;
				val2.m_crafterName = text;
				val2.m_worldLevel = num6;
				val2.m_customData = dictionary;
				val2.m_equipped = false;
				restored = val2;
				return true;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)(Launch.projectName + ": Failed to deserialize packed item '" + prefabName + "': " + ex.Message));
				restored = null;
				return false;
			}
		}
	}
	internal static class PackageMetadata
	{
		internal const string PackageAmountKey = "BalrondPackageAmount";

		internal const string PackageDescriptionKey = "BalrondPackageDescription";

		internal const string PackageWeightKey = "BalrondPackageWeight";

		internal const string PackageTeleportableKey = "BalrondPackageTeleportable";

		internal const string PackageHardNoTeleportKey = "BalrondPackageHardNoTeleport";

		internal const string PackageFormatVersionKey = "BalrondPackageFormatVersion";

		internal const string PackageItemDataVersionKey = "BalrondPackageItemDataVersion";

		internal const string PackageIndexPrefix = "BalrondPackageIndex-";

		internal const string PackagePrefabPrefix = "BalrondPackagePrefab-";

		internal const string PackageDataPrefix = "BalrondPackageData-";

		internal const string PackagePrefabName = "CustomPackageItem_bal";

		internal const int CurrentFormatVersion = 3;

		internal const int MaxPackedEntries = 256;

		internal const int MaxSerializedEntryLength = 262144;

		internal const int MaxSerializedPackageLength = 1048576;

		internal const int MaxCustomDataEntries = 1024;

		internal const int MaxCustomDataStringLength = 131072;

		internal static bool IsPackage(ItemData item)
		{
			return item != null && (Object)(object)item.m_dropPrefab != (Object)null && string.Equals(((Object)item.m_dropPrefab).name, "CustomPackageItem_bal", StringComparison.Ordinal);
		}

		internal static bool HasPackagePayload(ItemData item)
		{
			if (!IsPackage(item) || item.m_customData == null)
			{
				return false;
			}
			string value;
			return item.m_customData.TryGetValue("BalrondPackageAmount", out value) && !string.IsNullOrEmpty(value);
		}

		internal static void Set(ItemData item, string key, string value)
		{
			if (item != null && !string.IsNullOrEmpty(key))
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				item.m_customData[key] = value ?? string.Empty;
			}
		}

		internal static bool TryGetInt(ItemData item, string key, out int value)
		{
			value = 0;
			if (item == null || item.m_customData == null || string.IsNullOrEmpty(key))
			{
				return false;
			}
			string value2;
			return item.m_customData.TryGetValue(key, out value2) && int.TryParse(value2, NumberStyles.Integer, CultureInfo.InvariantCulture, out value);
		}

		internal static int GetFormatVersion(ItemData item)
		{
			int value;
			return (!TryGetInt(item, "BalrondPackageFormatVersion", out value) || value <= 0) ? 1 : value;
		}

		internal static bool TryGetWeight(ItemData item, out float weight)
		{
			weight = 0f;
			if (!HasPackagePayload(item))
			{
				return false;
			}
			if (!item.m_customData.TryGetValue("BalrondPackageWeight", out var value))
			{
				return false;
			}
			if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out weight) && !float.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out weight))
			{
				return false;
			}
			return !float.IsNaN(weight) && !float.IsInfinity(weight) && weight >= 0f;
		}

		internal static bool TryGetTeleportable(ItemData item, out bool teleportable)
		{
			teleportable = true;
			if (!HasPackagePayload(item))
			{
				return false;
			}
			if (!item.m_customData.TryGetValue("BalrondPackageTeleportable", out var value))
			{
				return false;
			}
			teleportable = value == "1" || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase);
			return true;
		}

		internal static bool IsHardNoTeleport(ItemData item)
		{
			if (!HasPackagePayload(item))
			{
				return false;
			}
			if (item.m_customData.TryGetValue("BalrondPackageHardNoTeleport", out var value))
			{
				return value == "1" || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase);
			}
			if (GetFormatVersion(item) >= 3 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			if (!TryGetInt(item, "BalrondPackageAmount", out var value2) || value2 <= 0 || value2 > 256)
			{
				return false;
			}
			for (int i = 0; i < value2; i++)
			{
				if (!item.m_customData.TryGetValue("BalrondPackageIndex-" + i, out var value3) || string.IsNullOrEmpty(value3))
				{
					continue;
				}
				int num = value3.LastIndexOf('.');
				if (num > 0)
				{
					string text = value3.Substring(0, num);
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
					ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					if ((Object)(object)val != (Object)null && val.m_itemData != null && val.m_itemData.m_shared != null && val.m_itemData.m_shared.m_toolTier >= 1000)
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static bool TryGetDescription(ItemData item, out string description)
		{
			description = null;
			if (!HasPackagePayload(item))
			{
				return false;
			}
			return item.m_customData.TryGetValue("BalrondPackageDescription", out description) && !string.IsNullOrEmpty(description);
		}

		internal static bool IsItemTeleportable(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return true;
			}
			if (TryGetTeleportable(item, out var teleportable))
			{
				return teleportable;
			}
			return item.m_shared.m_teleportable;
		}
	}
}
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 != JsonType.None)
			{
				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 != JsonType.None)
			{
				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 = new ArrayMetadata
			{
				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 = new PropertyMetadata
					{
						Info = propertyInfo,
						Type = propertyInfo.PropertyType
					};
					value.Properties.Add(propertyInfo.Name, value2);
				}
			}
			FieldInfo[] fields = type.GetFields();
			foreach (FieldInfo fieldInfo in fields)
			{
				PropertyMetadata value3 = new PropertyMetadata
				{
					Info = fieldInfo,
					IsField = true,
					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"))
				{
					list.Add(new PropertyMetadata
					{
						Info = propertyInfo,
						IsField = false
					});
				}
			}
			FieldInfo[] fields = type.GetFields();
			foreach (FieldInfo info in fields)
			{
				list.Add(new PropertyMetadata
				{
					Info = info,
					IsField = true
				});
			}
			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.Contain