Decompiled source of ItemDrawers v0.5.7

itemdrawers.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using AuthoritativeConfig;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SimpleJSON;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Serialization;
using UnityEngine.UI;
using itemdrawers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
public class AssetManager
{
	public static AssetBundle AssetBundle;

	public static Object[] AssetBundleObjects;

	public static UnityAction<ZNetScene> OnSceneAwake;

	public static UnityAction<ObjectDB> OnObjectDBAwake;

	public static void Create(Harmony harmony, string assetBundle)
	{
		harmony.PatchAll(typeof(AssetManager));
		LoadAssetsFromBundle(assetBundle);
	}

	public static void LoadAssetsFromBundle(string bundleName)
	{
		AssetBundle = GetAssetBundleFromResources(bundleName);
		AssetBundleObjects = AssetBundle.LoadAllAssets();
	}

	public static AssetBundle GetAssetBundleFromResources(string fileName)
	{
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName));
		using Stream stream = executingAssembly.GetManifestResourceStream(name);
		return AssetBundle.LoadFromStream(stream);
	}

	public static IEnumerable<T> GetGameObjects<T>() where T : Component
	{
		Object[] assetBundleObjects = AssetBundleObjects;
		foreach (Object obj in assetBundleObjects)
		{
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val != null)
			{
				T component = val.GetComponent<T>();
				if (component != null)
				{
					yield return component;
				}
			}
		}
	}

	public static T GetGameObject<T>(string id) where T : Component
	{
		Object[] assetBundleObjects = AssetBundleObjects;
		foreach (Object obj in assetBundleObjects)
		{
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val != null && ((Object)val).name == id)
			{
				T component = val.GetComponent<T>();
				if (component != null)
				{
					return component;
				}
			}
		}
		return default(T);
	}

	public static GameObject GetGameObject(string id)
	{
		Object[] assetBundleObjects = AssetBundleObjects;
		foreach (Object obj in assetBundleObjects)
		{
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val != null && ((Object)val).name == id)
			{
				return val;
			}
		}
		return null;
	}

	public static IEnumerable<T> GetAssets<T>()
	{
		Object[] assetBundleObjects = AssetBundleObjects;
		foreach (Object val in assetBundleObjects)
		{
			if (val is T)
			{
				yield return (T)(object)((val is T) ? val : null);
			}
		}
	}

	public static T GetAsset<T>(string name)
	{
		Object[] assetBundleObjects = AssetBundleObjects;
		foreach (Object val in assetBundleObjects)
		{
			if (val.name == name && val is T)
			{
				return (T)(object)((val is T) ? val : null);
			}
		}
		return default(T);
	}

	public static T LoadAsset<T>(string name) where T : Object
	{
		return AssetBundle.LoadAsset<T>(name);
	}

	public static void LoadItems(ObjectDB db)
	{
		IEnumerable<ItemDrop> gameObjects = AssetManager.GetGameObjects<ItemDrop>();
		db.m_items.AddRange(gameObjects.Select((ItemDrop x) => ((Component)x).gameObject));
		db.UpdateItemHashes();
	}

	public static void RegisterRecipes(ObjectDB db)
	{
		db.m_recipes.AddRange(from x in GetAssets<SkyheimRecipe>()
			select x.Convert());
		db.m_recipes.AddRange(GetAssets<Recipe>());
	}

	public static void RegisterStatusEffects(ObjectDB db)
	{
		db.m_StatusEffects.AddRange(GetAssets<StatusEffect>());
	}

	public static void RegisterPieces()
	{
		foreach (SkyheimPieceData gameObject in AssetManager.GetGameObjects<SkyheimPieceData>())
		{
			ItemDrop tool = gameObject.Tool;
			if (tool != null)
			{
				List<GameObject> pieces = tool.m_itemData.m_shared.m_buildPieces.m_pieces;
				if (!pieces.Contains(((Component)gameObject).gameObject))
				{
					gameObject.Convert();
					pieces.Add(((Component)gameObject).gameObject);
				}
			}
		}
	}

	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	[HarmonyPostfix]
	public static void ObjectDB_Awake_Postfix(ObjectDB __instance)
	{
		if ((Object)(object)ZNetScene.instance != (Object)null)
		{
			OnObjectDBAwake?.Invoke(__instance);
			LoadItems(__instance);
			RegisterRecipes(__instance);
			RegisterStatusEffects(__instance);
		}
	}

	[HarmonyPatch(typeof(FejdStartup), "SetupObjectDB")]
	[HarmonyPostfix]
	public static void FejdStartup_SetupObjectDB_Postfix(FejdStartup __instance)
	{
		LoadItems(((Component)__instance).GetComponent<ObjectDB>());
	}

	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	[HarmonyPostfix]
	public static void ZNetScene_Awake_Postfix(ZNetScene __instance)
	{
		foreach (ZNetView gameObject in AssetManager.GetGameObjects<ZNetView>())
		{
			__instance.m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name), ((Component)gameObject).gameObject);
		}
		RegisterPieces();
		OnSceneAwake?.Invoke(__instance);
	}
}
public class AssetType : PropertyAttribute
{
	public Type Type { get; protected set; }

	public AssetType(Type type)
	{
		Type = type;
	}
}
public static class CommonUtils
{
	[Serializable]
	public class SerializableWrapper<T>
	{
		public T Value;

		public SerializableWrapper(T v)
		{
			Value = v;
		}
	}

	public struct DistanceSort : IComparer<Collider>
	{
		private Vector3 _target;

		public DistanceSort(Vector3 target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_target = target;
		}

		public int Compare(Collider a, Collider b)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			Vector3 position = ((Component)a).transform.position;
			Vector3 position2 = ((Component)b).transform.position;
			return Vector3.Distance(position, _target).CompareTo(Vector3.Distance(position2, _target));
		}
	}

	public static long PlayerID => Game.instance.GetPlayerProfile().GetPlayerID();

	[Conditional("DEBUG")]
	public static void Log(string str)
	{
		Debug.Log((object)str);
	}

	[Conditional("DEBUG")]
	public static void LogFields(object obj)
	{
		FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
		foreach (FieldInfo obj2 in fields)
		{
			_ = obj2.Name;
			obj2.GetValue(obj);
		}
	}

	public static T ConvertPrefabReference<T>(string prefabReference) where T : Component
	{
		if (Object.op_Implicit((Object)(object)ZNetScene.instance) && !string.IsNullOrEmpty(prefabReference))
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabReference);
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab.GetComponent<T>();
			}
		}
		return default(T);
	}

	public static GameObject ConvertPrefabReference(string prefabReference)
	{
		if (Object.op_Implicit((Object)(object)ZNetScene.instance) && !string.IsNullOrEmpty(prefabReference))
		{
			return ZNetScene.instance.GetPrefab(prefabReference);
		}
		return null;
	}

	public static T GetItemComponent<T>(ItemData item) where T : Component
	{
		if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab))
		{
			return default(T);
		}
		return item.m_dropPrefab.GetComponent<T>();
	}

	public static T Clone<T>(T obj)
	{
		return (T)obj.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(obj, null);
	}

	public static T Get<T>(this IDictionary dict, string key, T defaultValue = default(T))
	{
		if (dict.Contains(key))
		{
			return (T)Convert.ChangeType(dict[key], typeof(T));
		}
		return defaultValue;
	}

	public static JSONNode ToJSON<T>(T obj)
	{
		Type type = obj.GetType();
		if (obj is IList)
		{
			JSONArray jSONArray = new JSONArray();
			{
				foreach (object item in obj as IList)
				{
					jSONArray.Add(ToJSON(item));
				}
				return jSONArray;
			}
		}
		if (type.IsClass && !(obj is string))
		{
			Type type2 = obj.GetType();
			JSONObject jSONObject = new JSONObject();
			FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				jSONObject.Add(fieldInfo.Name, ToJSON(fieldInfo.GetValue(obj)));
			}
			return jSONObject;
		}
		return (JSONNode)typeof(JSONNode).GetMethod("op_Implicit", new Type[1] { obj.GetType() }).Invoke(null, new object[1] { obj });
	}
}
public class NameAttribute : PropertyAttribute
{
	public string Name { get; private set; }

	public NameAttribute(string name)
	{
		Name = name;
	}
}
public class PrefabReferenceType : PropertyAttribute
{
	public Type ComponentType { get; protected set; }

	public PrefabReferenceType(Type componentType)
	{
		ComponentType = componentType;
	}
}
public class SkyheimPieceData : MonoBehaviour, ISerializationCallbackReceiver
{
	[Header("Requirements")]
	[SerializeField]
	[PrefabReferenceType(typeof(CraftingStation))]
	[FormerlySerializedAs("m_craftingStation")]
	private string _craftingStation;

	[SerializeField]
	[PrefabReferenceType(typeof(ItemDrop))]
	[FormerlySerializedAs("m_craftingTool")]
	private string _craftingTool;

	[SerializeField]
	[PrefabReferenceType(typeof(Piece))]
	[FormerlySerializedAs("m_template")]
	private string _template;

	[SerializeField]
	[FormerlySerializedAs("m_resources")]
	private List<SkyheimRecipe.SkyheimRequirement> _resources;

	[SerializeField]
	[HideInInspector]
	[FormerlySerializedAs("m_resources_internal")]
	private string _resourcesInternal;

	public ItemDrop Tool => CommonUtils.ConvertPrefabReference<ItemDrop>(_craftingTool);

	public void Convert()
	{
		RuntimeDeserialize();
		Piece component = ((Component)this).GetComponent<Piece>();
		component.m_craftingStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_craftingStation);
		component.m_resources = ((IEnumerable<SkyheimRecipe.SkyheimRequirement>)_resources).Select((Func<SkyheimRecipe.SkyheimRequirement, Requirement>)((SkyheimRecipe.SkyheimRequirement x) => x)).ToArray();
		Piece val = (string.IsNullOrEmpty(_template) ? null : CommonUtils.ConvertPrefabReference<Piece>(_template));
		if (!((Object)(object)val != (Object)null))
		{
			return;
		}
		component.m_placeEffect = val.m_placeEffect;
		WearNTear component2 = ((Component)component).GetComponent<WearNTear>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			WearNTear component3 = ((Component)val).GetComponent<WearNTear>();
			if (component3 != null)
			{
				component2.m_hitEffect = component3.m_hitEffect;
				component2.m_destroyedEffect = component3.m_destroyedEffect;
				component2.m_switchEffect = component3.m_switchEffect;
			}
		}
	}

	public void RuntimeDeserialize()
	{
		_resources = new List<SkyheimRecipe.SkyheimRequirement>();
		JSONNode.Enumerator enumerator = JSONNode.Parse(_resourcesInternal).AsArray.GetEnumerator();
		while (enumerator.MoveNext())
		{
			KeyValuePair<string, JSONNode> current = enumerator.Current;
			_resources.Add(new SkyheimRecipe.SkyheimRequirement(current.Value));
		}
	}

	public void OnBeforeSerialize()
	{
		JSONNode jSONNode = CommonUtils.ToJSON(_resources);
		_resourcesInternal = jSONNode.ToString();
	}

	public void OnAfterDeserialize()
	{
	}
}
[CreateAssetMenu(menuName = "Skyheim/Recipe")]
public class SkyheimRecipe : ScriptableObject, ISerializationCallbackReceiver
{
	[Serializable]
	public class SkyheimRequirement
	{
		[PrefabReferenceType(typeof(ItemDrop))]
		[FormerlySerializedAs("ResItem")]
		public string ResourceItem;

		[FormerlySerializedAs("m_amount")]
		public int Amount = 1;

		[FormerlySerializedAs("m_amountPerLevel")]
		public int AmountPerLevel = 1;

		[FormerlySerializedAs("m_recover")]
		public bool Recover = true;

		public SkyheimRequirement()
		{
		}

		public SkyheimRequirement(JSONNode j)
		{
			ResourceItem = j["ResourceItem"];
			Amount = j["Amount"];
			AmountPerLevel = j["AmountPerLevel"];
			Recover = j["Recover"];
		}

		public static implicit operator Requirement(SkyheimRequirement r)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = CommonUtils.ConvertPrefabReference<ItemDrop>(r.ResourceItem),
				m_amount = r.Amount,
				m_amountPerLevel = r.AmountPerLevel,
				m_recover = r.Recover
			};
		}
	}

	[SerializeField]
	[PrefabReferenceType(typeof(ItemDrop))]
	[FormerlySerializedAs("m_item")]
	private string _item;

	[SerializeField]
	[FormerlySerializedAs("m_amount")]
	private int _amount = 1;

	[SerializeField]
	[FormerlySerializedAs("m_enabled")]
	private bool _enabled = true;

	[Header("Requirements")]
	[SerializeField]
	[PrefabReferenceType(typeof(CraftingStation))]
	[FormerlySerializedAs("m_craftingStation")]
	private string _craftingStation;

	[SerializeField]
	[PrefabReferenceType(typeof(CraftingStation))]
	[FormerlySerializedAs("m_repairStation")]
	private string _repairStation;

	[SerializeField]
	[FormerlySerializedAs("m_minStationLevel")]
	private int _minStationLevel = 1;

	[SerializeField]
	[FormerlySerializedAs("m_resources")]
	private List<SkyheimRequirement> _resources;

	[SerializeField]
	[HideInInspector]
	[FormerlySerializedAs("m_resources_internal")]
	private string _resourcesInternal;

	public Recipe Convert()
	{
		RuntimeDeserialize();
		Recipe obj = ScriptableObject.CreateInstance<Recipe>();
		((Object)obj).name = ((Object)this).name;
		obj.m_item = CommonUtils.ConvertPrefabReference<ItemDrop>(_item);
		obj.m_craftingStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_craftingStation);
		obj.m_repairStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_repairStation);
		obj.m_resources = ((IEnumerable<SkyheimRequirement>)_resources).Select((Func<SkyheimRequirement, Requirement>)((SkyheimRequirement x) => x)).ToArray();
		obj.m_amount = _amount;
		obj.m_enabled = _enabled;
		obj.m_minStationLevel = _minStationLevel;
		return obj;
	}

	public void RuntimeDeserialize()
	{
		JSONNode jSONNode = JSONNode.Parse(_resourcesInternal);
		_resources = new List<SkyheimRequirement>();
		JSONNode.Enumerator enumerator = jSONNode.AsArray.GetEnumerator();
		while (enumerator.MoveNext())
		{
			KeyValuePair<string, JSONNode> current = enumerator.Current;
			_resources.Add(new SkyheimRequirement(current.Value));
		}
	}

	public void OnBeforeSerialize()
	{
		JSONNode jSONNode = CommonUtils.ToJSON(_resources);
		_resourcesInternal = jSONNode.ToString();
	}

	public void OnAfterDeserialize()
	{
	}
}
public class DrawerContainer : Container, Hoverable, Interactable
{
	public Image _image;

	public Text _text;

	private const int CurrentVersion = 0;

	private uint? _lastRevision;

	private ZNetView _nview;

	private Piece _piece;

	private ItemData _item;

	private int _quantity;

	private bool _loading;

	private int _pickupDelay = 10;

	private int _pickupMask;

	public void Awake_Drawer()
	{
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		_pickupMask = LayerMask.GetMask(new string[1] { "item" });
		_nview = ((Component)this).GetComponent<ZNetView>();
		_piece = ((Component)this).GetComponent<Piece>();
		((Component)_image).gameObject.SetActive(false);
		if ((Object)(object)_nview != (Object)null && _nview.GetZDO() != null)
		{
			((Object)this).name = $"Container_{_nview.GetZDO().m_uid}";
			base.m_name = "piece_chest_drawer";
			base.m_nview = _nview;
			base.m_inventory = new Inventory(((Object)this).name, (Sprite)null, 1, 1);
			base.m_inventory.m_onChanged = (Action)Delegate.Combine(base.m_inventory.m_onChanged, new Action(OnInventoryChanged));
			_nview.Register<int>("Drop", (Action<long, int>)RPC_Drop);
			_nview.Register<ZDOID>("DropResponse", (Action<long, ZDOID>)RPC_DropResponse);
			_nview.Register("Clear", (Action<long>)RPC_Clear);
			_nview.Register<string, int>("AddItem", (Action<long, string, int>)RPC_AddItem);
			_nview.Register<string, int>("AddItemResponse", (Action<long, string, int>)RPC_AddItemResponse);
			Load();
		}
		WearNTear component = ((Component)this).GetComponent<WearNTear>();
		if (component != null)
		{
			component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(base.OnDestroyed));
		}
		((MonoBehaviour)this).InvokeRepeating("CheckForChanges", 0f, 1f);
	}

	public void SetFontColor(Color fontColor, Color outlineColor, bool outlineEnabled)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		((Graphic)_text).color = fontColor;
		Outline component = ((Component)_text).GetComponent<Outline>();
		((Behaviour)component).enabled = outlineEnabled;
		if (((Behaviour)component).enabled)
		{
			((Shadow)component).effectColor = outlineColor;
		}
	}

	private void RetreiveItems()
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if (!ItemDrawerPlugin.RetreiveEnabled || _item == null || !Object.op_Implicit((Object)(object)_nview) || !_nview.IsOwner())
		{
			return;
		}
		if (_pickupDelay > 0)
		{
			_pickupDelay--;
			return;
		}
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position + Vector3.up, ItemDrawerPlugin.RetreiveRadius, _pickupMask);
		foreach (Collider val in array)
		{
			if (!Object.op_Implicit((Object)(object)val.attachedRigidbody))
			{
				continue;
			}
			ItemDrop component = ((Component)val.attachedRigidbody).GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_itemData.m_dropPrefab != (Object)(object)_item.m_dropPrefab)
			{
				continue;
			}
			ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component2) && component2.IsValid())
			{
				if (!component.CanPickup(true))
				{
					component.RequestOwn();
					continue;
				}
				AddItem(((Object)component.m_itemData.m_dropPrefab).name, component.m_itemData.m_stack);
				ZNetScene.instance.Destroy(((Component)component).gameObject);
			}
		}
	}

	private void CheckForChanges()
	{
		if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid())
		{
			Load();
			RetreiveItems();
			UpdateVisuals();
		}
	}

	public string GetHoverName()
	{
		if (!Object.op_Implicit((Object)(object)_piece))
		{
			return string.Empty;
		}
		return Localization.instance.Localize(_piece.m_name);
	}

	public string GetHoverText()
	{
		string text = ((_item != null) ? $"<color=#00FFFF>{_item.m_shared.m_name}</color> x {_quantity}" : "$piece_container_empty");
		if (!ZInput.IsGamepadActive())
		{
			string boundKeyString = ZInput.instance.GetBoundKeyString("drawer_mod_deposit_all", false);
			if (_quantity > 0)
			{
				text += "\n[<color=yellow><b>$KEY_Use</b></color>] Take Stack";
				string boundKeyString2 = ZInput.instance.GetBoundKeyString("drawer_mod_withdraw_one", false);
				text = text + "\n[<color=yellow><b>" + boundKeyString2 + "+$KEY_Use</b></color>] Take One";
			}
			else
			{
				string boundKeyString3 = ZInput.instance.GetBoundKeyString("drawer_mod_clear", false);
				text = text + "\n[<color=yellow><b>" + boundKeyString3 + "+$KEY_Use</b></color>] Clear Item";
			}
			text = text + "\n[<color=yellow><b>" + boundKeyString + "+$KEY_Use</b></color>] Deposit All";
		}
		return Localization.instance.Localize(text);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (_item == null || (Object)(object)user != (Object)(object)Player.m_localPlayer || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return false;
		}
		if (!ZInput.IsGamepadActive())
		{
			return OnKeyboardInteract(Player.m_localPlayer);
		}
		return OnGamepadInteract(Player.m_localPlayer);
	}

	private bool OnGamepadInteract(Player player)
	{
		bool blocking = ((Character)player).m_blocking;
		bool crouchToggled = player.m_crouchToggled;
		return ProcessInputInternal(player, blocking, crouchToggled);
	}

	private bool OnKeyboardInteract(Player player)
	{
		bool button = ZInput.GetButton("drawer_mod_deposit_all");
		bool button2 = ZInput.GetButton((_quantity > 0) ? "drawer_mod_withdraw_one" : "drawer_mod_clear");
		return ProcessInputInternal(player, button, button2);
	}

	private bool ProcessInputInternal(Player player, bool mod0, bool mod1)
	{
		if (mod0)
		{
			return UseItem((Humanoid)(object)player, _item);
		}
		if (mod1 && _quantity <= 0)
		{
			_nview.InvokeRPC("Clear", Array.Empty<object>());
		}
		else if (_quantity > 0)
		{
			_nview.InvokeRPC("Drop", new object[1] { mod1 ? 1 : _item.m_shared.m_maxStackSize });
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		if (item.m_shared.m_maxStackSize <= 1)
		{
			return false;
		}
		if (_item == null || (Object)(object)_item.m_dropPrefab == (Object)(object)item.m_dropPrefab)
		{
			int num = user.GetInventory().CountItems(item.m_shared.m_name, -1, true);
			if (num > 0)
			{
				_nview.InvokeRPC("AddItem", new object[2]
				{
					((Object)item.m_dropPrefab).name,
					num
				});
				return true;
			}
		}
		return false;
	}

	private void UpdateInventory()
	{
		if (base.m_inventory.m_inventory.Count > 0)
		{
			ItemData val = base.m_inventory.m_inventory[0];
			if (val.m_shared.m_name == _item.m_shared.m_name)
			{
				val.m_stack = _quantity;
				val.m_shared.m_maxStackSize = ItemDrawerPlugin.MaxItems;
			}
			else
			{
				_addItem();
			}
		}
		else
		{
			_addItem();
		}
		void _addItem()
		{
			base.m_inventory.m_inventory.Clear();
			ItemData val2 = _item.Clone();
			val2.m_stack = _quantity;
			val2.m_shared = CommonUtils.Clone<SharedData>(val2.m_shared);
			val2.m_shared.m_maxStackSize = ItemDrawerPlugin.MaxItems;
			base.m_inventory.m_inventory.Add(val2);
		}
	}

	private ItemDrop Drop(int quantity)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		if (_quantity > 0)
		{
			GameObject dropPrefab = _item.m_dropPrefab;
			int num = Mathf.Min(quantity, _quantity);
			_quantity -= num;
			_pickupDelay = 5;
			UpdateInventory();
			Vector3 val = ((Component)this).transform.position + ((Component)this).transform.forward * -0.5f;
			GameObject obj = Object.Instantiate<GameObject>(dropPrefab, val, Quaternion.identity);
			obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f + ((Component)this).transform.forward * 4f;
			ItemDrop component = obj.GetComponent<ItemDrop>();
			component.SetStack(num);
			return component;
		}
		return null;
	}

	public int AddItem(string name, int stack)
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
		if ((Object)(object)itemPrefab == (Object)null)
		{
			ZLog.Log((object)("Failed to find item prefab " + name));
			return 0;
		}
		ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null)
		{
			ZLog.Log((object)("Invalid item " + name));
			return 0;
		}
		if (_item != null && (Object)(object)_item.m_dropPrefab != (Object)(object)itemPrefab)
		{
			ZLog.Log((object)("Cannot add to container " + name));
			return 0;
		}
		stack = Math.Min(stack, ItemDrawerPlugin.MaxItems - _quantity);
		_item = component.m_itemData;
		_item.m_dropPrefab = itemPrefab;
		_item.m_gridPos = Vector2i.zero;
		_quantity += stack;
		UpdateInventory();
		OnContainerChanged();
		return stack;
	}

	private void OnContainerChanged()
	{
		if (!_loading && _nview.IsOwner())
		{
			Save();
		}
	}

	private void OnInventoryChanged()
	{
		if (base.m_inventory.m_inventory.Count > 0)
		{
			ItemData val = base.m_inventory.m_inventory[0];
			int num = _quantity - val.m_stack;
			_quantity = Math.Max(0, _quantity - num);
		}
		else
		{
			_quantity = 0;
		}
		OnContainerChanged();
		UpdateVisuals();
	}

	private void RPC_AddItem(long playerId, string prefabName, int quantity)
	{
		if (_nview.IsOwner())
		{
			int num = AddItem(prefabName, quantity);
			if (num > 0)
			{
				_nview.InvokeRPC(playerId, "AddItemResponse", new object[2] { prefabName, num });
			}
		}
	}

	private void RPC_AddItemResponse(long _, string prefabName, int quantity)
	{
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && quantity > 0)
		{
			ItemDrop component = ObjectDB.instance.GetItemPrefab(prefabName).GetComponent<ItemDrop>();
			if (component != null)
			{
				string name = component.m_itemData.m_shared.m_name;
				((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(name, quantity, -1, true);
			}
		}
	}

	private void RPC_Clear(long _)
	{
		if (_nview.IsOwner() && _item != null)
		{
			Clear();
			OnContainerChanged();
		}
	}

	private void RPC_Drop(long playerId, int quantity)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if (_nview.IsOwner() && _item != null)
		{
			ItemDrop val = Drop(quantity);
			if (val != null)
			{
				OnContainerChanged();
				ZDOID uid = val.m_nview.GetZDO().m_uid;
				_nview.InvokeRPC(playerId, "DropResponse", new object[1] { uid });
			}
		}
	}

	private void RPC_DropResponse(long _, ZDOID drop)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = ZNetScene.instance.FindInstance(drop);
		if ((Object)(object)val != (Object)null)
		{
			ItemDrop component = val.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null) && ((Humanoid)Player.m_localPlayer).GetInventory().AddItem(component.m_itemData))
			{
				((Character)Player.m_localPlayer).ShowPickupMessage(component.m_itemData, component.m_itemData.m_stack);
				ZNetScene.instance.Destroy(val);
			}
		}
	}

	private void UpdateVisuals()
	{
		if ((Object)(object)_image != (Object)null)
		{
			bool flag = _item != null && _item.m_shared.m_icons.Count() > 0;
			((Component)_image).gameObject.SetActive(flag);
			if (flag)
			{
				_image.sprite = _item.m_shared.m_icons[0];
			}
		}
		if ((Object)(object)_text != (Object)null)
		{
			_text.text = ((_quantity > 0) ? _quantity.ToString() : string.Empty);
		}
	}

	private void Clear()
	{
		_quantity = 0;
		_item = null;
		base.m_inventory.m_inventory.Clear();
		UpdateVisuals();
	}

	private void Save()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		ZPackage val = new ZPackage();
		val.Write(0);
		if (_item != null)
		{
			val.Write(((Object)(object)_item.m_dropPrefab == (Object)null) ? "" : ((Object)_item.m_dropPrefab).name);
			val.Write(_quantity);
		}
		else
		{
			val.Write("");
		}
		string @base = val.GetBase64();
		_nview.GetZDO().Set("items", @base);
		_lastRevision = _nview.GetZDO().DataRevision;
		ZDOMan.instance.ForceSendZDO(_nview.GetZDO().m_uid);
	}

	private void Load()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		if (_nview.GetZDO().DataRevision == _lastRevision && _lastRevision.HasValue)
		{
			return;
		}
		Clear();
		string @string = _nview.GetZDO().GetString("items", "");
		if (!string.IsNullOrEmpty(@string))
		{
			ZPackage val = new ZPackage(@string);
			val.ReadInt();
			string text = val.ReadString();
			if (!string.IsNullOrEmpty(text))
			{
				int stack = val.ReadInt();
				_loading = true;
				AddItem(text, stack);
				_loading = false;
				_lastRevision = _nview.GetZDO().DataRevision;
			}
		}
	}

	public void OnDestroyed_Drawer()
	{
		if (_nview.IsOwner() && _item != null)
		{
			while (_quantity > 0 && Object.op_Implicit((Object)(object)Drop(_item.m_shared.m_maxStackSize)))
			{
			}
		}
	}
}
namespace itemdrawers
{
	[BepInPlugin("mkz.itemdrawers", "Item Drawers", "0.5.7")]
	public class ItemDrawerPlugin : BaseUnityPlugin
	{
		public static ItemDrawerPlugin Instance;

		private Harmony _harmony;

		private static ConfigEntry<bool> _retreiveEnabled;

		private static ConfigEntry<float> _retreiveRadius;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<int> _maxItems;

		private static ConfigEntry<Color> _configFontColor;

		private static ConfigEntry<Color> _configOutlineColor;

		private static ConfigEntry<bool> _configOutlineEnabled;

		private static ConfigEntry<string> _configKeyDepositAll;

		private static ConfigEntry<string> _configKeyWithdrawOne;

		private static ConfigEntry<string> _configKeyClear;

		public const string KeyDepositAll = "drawer_mod_deposit_all";

		public const string KeyWithdrawOne = "drawer_mod_withdraw_one";

		public const string KeyClear = "drawer_mod_clear";

		public static float RetreiveRadius => _retreiveRadius.Value;

		public static bool RetreiveEnabled => _retreiveEnabled.Value;

		public static bool Enabled => _enabled.Value;

		public static int MaxItems => _maxItems.Value;

		public static bool OutlineEnabled => _configOutlineEnabled.Value;

		public static Color OutlineColor => _configOutlineColor.Value;

		public static Color FontColor => _configFontColor.Value;

		private Config AuthoritativeConfig => Config.Instance;

		public void Awake()
		{
			Instance = this;
			_harmony = Harmony.CreateAndPatchAll(typeof(ItemDrawerPlugin), (string)null);
			AssetManager.Create(_harmony, "itemdrawers");
			LoadConfig();
		}

		public void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchAll((string)null);
			}
		}

		[HarmonyPatch(typeof(Container), "Awake")]
		[HarmonyPrefix]
		private static bool Container_Awake_Prefix(Container __instance)
		{
			if (__instance is DrawerContainer drawerContainer)
			{
				drawerContainer.Awake_Drawer();
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Container), "OnDestroyed")]
		[HarmonyPrefix]
		private static bool Container_OnDestroyed_Prefix(Container __instance)
		{
			if (__instance is DrawerContainer drawerContainer)
			{
				drawerContainer.OnDestroyed_Drawer();
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Container), "Save")]
		[HarmonyPrefix]
		private static bool Container_Save_Prefix(Container __instance)
		{
			return !(__instance is DrawerContainer);
		}

		[HarmonyPatch(typeof(Container), "Load")]
		[HarmonyPrefix]
		private static bool Container_Load_Prefix(Container __instance)
		{
			return !(__instance is DrawerContainer);
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		private static void ZNetScene_Awake_Postfix()
		{
			Instance.ApplyConfig();
		}

		[HarmonyPatch(typeof(Player), "IsOverlappingOtherPiece")]
		[HarmonyPostfix]
		private static void Player_IsOverlappingOtherPiece_PostFix(string pieceName, ref bool __result)
		{
			if (pieceName == "piece_drawer")
			{
				__result = false;
			}
		}

		[HarmonyPatch(typeof(ZInput), "Load")]
		[HarmonyPostfix]
		private static void ZInput_Load_PostFix(ZInput __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			__instance.AddButton("drawer_mod_deposit_all", parseKeyConfig(_configKeyDepositAll, (Key)51), 0f, 0f, true, false);
			__instance.AddButton("drawer_mod_withdraw_one", parseKeyConfig(_configKeyWithdrawOne, (Key)53), 0f, 0f, true, false);
			__instance.AddButton("drawer_mod_clear", parseKeyConfig(_configKeyClear, (Key)53), 0f, 0f, true, false);
			static Key parseKeyConfig(ConfigEntry<string> configString, Key @default)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (Enum.TryParse<Key>(configString.Value, out Key result))
				{
					return result;
				}
				return @default;
			}
		}

		private void LoadConfig()
		{
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			AuthoritativeConfig.Init((BaseUnityPlugin)(object)this, defaultBindServerAuthority: true);
			_enabled = AuthoritativeConfig.Bind("General", "Enabled", defaultValue: true, "Enable creation of Item Drawers");
			_maxItems = AuthoritativeConfig.Bind("General", "MaxItems", 9999, "The maximum number of items that can be stored in a drawer");
			_retreiveEnabled = AuthoritativeConfig.Bind("Item Retreival", "Enabled", defaultValue: true, "Drawers will retreive dropped items matching their item");
			_retreiveRadius = AuthoritativeConfig.Bind("Item Retreival", "Radius", 5f, "The distance drawers will check for dropped items");
			_configKeyDepositAll = AuthoritativeConfig.Bind("Hotkeys", "Deposit All", "LeftShift", "Hold while interacting to deposit all", false);
			_configKeyWithdrawOne = AuthoritativeConfig.Bind("Hotkeys", "Withdraw One", "LeftAlt", "Hold while interacting to withdraw one", false);
			_configKeyClear = AuthoritativeConfig.Bind("Hotkeys", "Clear", "LeftAlt", "Hold while interacting to clear contents (only if 0 quantity)", false);
			_configFontColor = AuthoritativeConfig.Bind<Color>("Font", "Color", new Color(1f, 0.5f, 0f), "Drawer font color", false);
			_configOutlineColor = AuthoritativeConfig.Bind<Color>("Font", "Outline Color", new Color(0f, 0f, 0f), "Drawer outline color", false);
			_configOutlineEnabled = AuthoritativeConfig.Bind("Font", "Outline Enabled", defaultValue: true, "Enabled font outline on drawers", false);
			AuthoritativeConfig.OnConfigReceived.AddListener(new UnityAction(ApplyConfig));
		}

		private void ApplyConfig()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Piece gameObject = AssetManager.GetGameObject<Piece>("piece_drawer");
			if (gameObject != null)
			{
				gameObject.m_enabled = Enabled;
				DrawerContainer component = ((Component)gameObject).GetComponent<DrawerContainer>();
				component._text.text = MaxItems.ToString();
				component.SetFontColor(_configFontColor.Value, _configOutlineColor.Value, _configOutlineEnabled.Value);
			}
		}
	}
}
namespace SimpleJSON
{
	public enum JSONNodeType
	{
		Array = 1,
		Object = 2,
		String = 3,
		Number = 4,
		NullValue = 5,
		Boolean = 6,
		None = 7,
		Custom = 255
	}
	public enum JSONTextMode
	{
		Compact,
		Indent
	}
	public abstract class JSONNode
	{
		public struct Enumerator
		{
			private enum Type
			{
				None,
				Array,
				Object
			}

			private Type type;

			private Dictionary<string, JSONNode>.Enumerator m_Object;

			private List<JSONNode>.Enumerator m_Array;

			public bool IsValid => type != Type.None;

			public KeyValuePair<string, JSONNode> Current
			{
				get
				{
					if (type == Type.Array)
					{
						return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
					}
					if (type == Type.Object)
					{
						return m_Object.Current;
					}
					return new KeyValuePair<string, JSONNode>(string.Empty, null);
				}
			}

			public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
			{
				type = Type.Array;
				m_Object = default(Dictionary<string, JSONNode>.Enumerator);
				m_Array = aArrayEnum;
			}

			public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
			{
				type = Type.Object;
				m_Object = aDictEnum;
				m_Array = default(List<JSONNode>.Enumerator);
			}

			public bool MoveNext()
			{
				if (type == Type.Array)
				{
					return m_Array.MoveNext();
				}
				if (type == Type.Object)
				{
					return m_Object.MoveNext();
				}
				return false;
			}
		}

		public struct ValueEnumerator
		{
			private Enumerator m_Enumerator;

			public JSONNode Current => m_Enumerator.Current.Value;

			public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public ValueEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

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

			public ValueEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public struct KeyEnumerator
		{
			private Enumerator m_Enumerator;

			public string Current => m_Enumerator.Current.Key;

			public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public KeyEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

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

			public KeyEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable
		{
			private JSONNode m_Node;

			private Enumerator m_Enumerator;

			public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current;

			object IEnumerator.Current => m_Enumerator.Current;

			internal LinqEnumerator(JSONNode aNode)
			{
				m_Node = aNode;
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

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

			public void Dispose()
			{
				m_Node = null;
				m_Enumerator = default(Enumerator);
			}

			public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}

			public void Reset()
			{
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}
		}

		public static bool forceASCII = false;

		public static bool longAsString = false;

		public static bool allowLineComments = true;

		[ThreadStatic]
		private static StringBuilder m_EscapeBuilder;

		public abstract JSONNodeType Tag { get; }

		public virtual JSONNode this[int aIndex]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual JSONNode this[string aKey]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual string Value
		{
			get
			{
				return "";
			}
			set
			{
			}
		}

		public virtual int Count => 0;

		public virtual bool IsNumber => false;

		public virtual bool IsString => false;

		public virtual bool IsBoolean => false;

		public virtual bool IsNull => false;

		public virtual bool IsArray => false;

		public virtual bool IsObject => false;

		public virtual bool Inline
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public virtual IEnumerable<JSONNode> Children
		{
			get
			{
				yield break;
			}
		}

		public IEnumerable<JSONNode> DeepChildren
		{
			get
			{
				foreach (JSONNode child in Children)
				{
					foreach (JSONNode deepChild in child.DeepChildren)
					{
						yield return deepChild;
					}
				}
			}
		}

		public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this);

		public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator());

		public ValueEnumerator Values => new ValueEnumerator(GetEnumerator());

		public virtual double AsDouble
		{
			get
			{
				double result = 0.0;
				if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out result))
				{
					return result;
				}
				return 0.0;
			}
			set
			{
				Value = value.ToString(CultureInfo.InvariantCulture);
			}
		}

		public virtual int AsInt
		{
			get
			{
				return (int)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual float AsFloat
		{
			get
			{
				return (float)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual bool AsBool
		{
			get
			{
				bool result = false;
				if (bool.TryParse(Value, out result))
				{
					return result;
				}
				return !string.IsNullOrEmpty(Value);
			}
			set
			{
				Value = (value ? "true" : "false");
			}
		}

		public virtual long AsLong
		{
			get
			{
				long result = 0L;
				if (long.TryParse(Value, out result))
				{
					return result;
				}
				return 0L;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual ulong AsULong
		{
			get
			{
				ulong result = 0uL;
				if (ulong.TryParse(Value, out result))
				{
					return result;
				}
				return 0uL;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual JSONArray AsArray => this as JSONArray;

		public virtual JSONObject AsObject => this as JSONObject;

		internal static StringBuilder EscapeBuilder
		{
			get
			{
				if (m_EscapeBuilder == null)
				{
					m_EscapeBuilder = new StringBuilder();
				}
				return m_EscapeBuilder;
			}
		}

		public virtual decimal AsDecimal
		{
			get
			{
				if (!decimal.TryParse(Value, out var result))
				{
					result = default(decimal);
				}
				return result;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual char AsChar
		{
			get
			{
				if (IsString && Value.Length > 0)
				{
					return Value[0];
				}
				if (IsNumber)
				{
					return (char)AsInt;
				}
				return '\0';
			}
			set
			{
				if (IsString)
				{
					Value = value.ToString();
				}
				else if (IsNumber)
				{
					AsInt = value;
				}
			}
		}

		public virtual uint AsUInt
		{
			get
			{
				return (uint)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual byte AsByte
		{
			get
			{
				return (byte)AsInt;
			}
			set
			{
				AsInt = value;
			}
		}

		public virtual sbyte AsSByte
		{
			get
			{
				return (sbyte)AsInt;
			}
			set
			{
				AsInt = value;
			}
		}

		public virtual short AsShort
		{
			get
			{
				return (short)AsInt;
			}
			set
			{
				AsInt = value;
			}
		}

		public virtual ushort AsUShort
		{
			get
			{
				return (ushort)AsInt;
			}
			set
			{
				AsInt = value;
			}
		}

		public virtual DateTime AsDateTime
		{
			get
			{
				if (!DateTime.TryParse(Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
				{
					result = new DateTime(0L);
				}
				return result;
			}
			set
			{
				Value = value.ToString(CultureInfo.InvariantCulture);
			}
		}

		public virtual TimeSpan AsTimeSpan
		{
			get
			{
				if (!TimeSpan.TryParse(Value, CultureInfo.InvariantCulture, out var result))
				{
					result = new TimeSpan(0L);
				}
				return result;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual Guid AsGuid
		{
			get
			{
				Guid.TryParse(Value, out var result);
				return result;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual byte[] AsByteArray
		{
			get
			{
				if (IsNull || !IsArray)
				{
					return null;
				}
				int count = Count;
				byte[] array = new byte[count];
				for (int i = 0; i < count; i++)
				{
					array[i] = this[i].AsByte;
				}
				return array;
			}
			set
			{
				if (IsArray && value != null)
				{
					Clear();
					for (int i = 0; i < value.Length; i++)
					{
						Add(value[i]);
					}
				}
			}
		}

		public virtual List<byte> AsByteList
		{
			get
			{
				if (IsNull || !IsArray)
				{
					return null;
				}
				int count = Count;
				List<byte> list = new List<byte>(count);
				for (int i = 0; i < count; i++)
				{
					list.Add(this[i].AsByte);
				}
				return list;
			}
			set
			{
				if (IsArray && value != null)
				{
					Clear();
					for (int i = 0; i < value.Count; i++)
					{
						Add(value[i]);
					}
				}
			}
		}

		public virtual string[] AsStringArray
		{
			get
			{
				if (IsNull || !IsArray)
				{
					return null;
				}
				int count = Count;
				string[] array = new string[count];
				for (int i = 0; i < count; i++)
				{
					array[i] = this[i].Value;
				}
				return array;
			}
			set
			{
				if (IsArray && value != null)
				{
					Clear();
					for (int i = 0; i < value.Length; i++)
					{
						Add(value[i]);
					}
				}
			}
		}

		public virtual List<string> AsStringList
		{
			get
			{
				if (IsNull || !IsArray)
				{
					return null;
				}
				int count = Count;
				List<string> list = new List<string>(count);
				for (int i = 0; i < count; i++)
				{
					list.Add(this[i].Value);
				}
				return list;
			}
			set
			{
				if (IsArray && value != null)
				{
					Clear();
					for (int i = 0; i < value.Count; i++)
					{
						Add(value[i]);
					}
				}
			}
		}

		public virtual void Add(string aKey, JSONNode aItem)
		{
		}

		public virtual void Add(JSONNode aItem)
		{
			Add("", aItem);
		}

		public virtual JSONNode Remove(string aKey)
		{
			return null;
		}

		public virtual JSONNode Remove(int aIndex)
		{
			return null;
		}

		public virtual JSONNode Remove(JSONNode aNode)
		{
			return aNode;
		}

		public virtual void Clear()
		{
		}

		public virtual JSONNode Clone()
		{
			return null;
		}

		public virtual bool HasKey(string aKey)
		{
			return false;
		}

		public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault)
		{
			return aDefault;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact);
			return stringBuilder.ToString();
		}

		public virtual string ToString(int aIndent)
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent);
			return stringBuilder.ToString();
		}

		internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);

		public abstract Enumerator GetEnumerator();

		public static implicit operator JSONNode(string s)
		{
			if (s != null)
			{
				return new JSONString(s);
			}
			return JSONNull.CreateOrGet();
		}

		public static implicit operator string(JSONNode d)
		{
			if (!(d == null))
			{
				return d.Value;
			}
			return null;
		}

		public static implicit operator JSONNode(double n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator double(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsDouble;
			}
			return 0.0;
		}

		public static implicit operator JSONNode(float n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator float(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsFloat;
			}
			return 0f;
		}

		public static implicit operator JSONNode(int n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator int(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsInt;
			}
			return 0;
		}

		public static implicit operator JSONNode(long n)
		{
			if (longAsString)
			{
				return new JSONString(n.ToString());
			}
			return new JSONNumber(n);
		}

		public static implicit operator long(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsLong;
			}
			return 0L;
		}

		public static implicit operator JSONNode(ulong n)
		{
			if (longAsString)
			{
				return new JSONString(n.ToString());
			}
			return new JSONNumber(n);
		}

		public static implicit operator ulong(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsULong;
			}
			return 0uL;
		}

		public static implicit operator JSONNode(bool b)
		{
			return new JSONBool(b);
		}

		public static implicit operator bool(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsBool;
			}
			return false;
		}

		public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
		{
			return aKeyValue.Value;
		}

		public static bool operator ==(JSONNode a, object b)
		{
			if ((object)a == b)
			{
				return true;
			}
			bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator;
			bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator;
			if (flag && flag2)
			{
				return true;
			}
			if (!flag)
			{
				return a.Equals(b);
			}
			return false;
		}

		public static bool operator !=(JSONNode a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		internal static string Escape(string aText)
		{
			StringBuilder escapeBuilder = EscapeBuilder;
			escapeBuilder.Length = 0;
			if (escapeBuilder.Capacity < aText.Length + aText.Length / 10)
			{
				escapeBuilder.Capacity = aText.Length + aText.Length / 10;
			}
			foreach (char c in aText)
			{
				switch (c)
				{
				case '\\':
					escapeBuilder.Append("\\\\");
					continue;
				case '"':
					escapeBuilder.Append("\\\"");
					continue;
				case '\n':
					escapeBuilder.Append("\\n");
					continue;
				case '\r':
					escapeBuilder.Append("\\r");
					continue;
				case '\t':
					escapeBuilder.Append("\\t");
					continue;
				case '\b':
					escapeBuilder.Append("\\b");
					continue;
				case '\f':
					escapeBuilder.Append("\\f");
					continue;
				}
				if (c < ' ' || (forceASCII && c > '\u007f'))
				{
					ushort num = c;
					escapeBuilder.Append("\\u").Append(num.ToString("X4"));
				}
				else
				{
					escapeBuilder.Append(c);
				}
			}
			string result = escapeBuilder.ToString();
			escapeBuilder.Length = 0;
			return result;
		}

		private static JSONNode ParseElement(string token, bool quoted)
		{
			if (quoted)
			{
				return token;
			}
			if (token.Length <= 5)
			{
				string text = token.ToLower();
				switch (text)
				{
				case "false":
				case "true":
					return text == "true";
				case "null":
					return JSONNull.CreateOrGet();
				}
			}
			if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return result;
			}
			return token;
		}

		public static JSONNode Parse(string aJSON)
		{
			Stack<JSONNode> stack = new Stack<JSONNode>();
			JSONNode jSONNode = null;
			int i = 0;
			StringBuilder stringBuilder = new StringBuilder();
			string aKey = "";
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			for (; i < aJSON.Length; i++)
			{
				switch (aJSON[i])
				{
				case '{':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONObject());
					if (jSONNode != null)
					{
						jSONNode.Add(aKey, stack.Peek());
					}
					aKey = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					flag3 = false;
					break;
				case '[':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONArray());
					if (jSONNode != null)
					{
						jSONNode.Add(aKey, stack.Peek());
					}
					aKey = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					flag3 = false;
					break;
				case ']':
				case '}':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stack.Count == 0)
					{
						throw new Exception("JSON Parse: Too many closing brackets");
					}
					stack.Pop();
					if (stringBuilder.Length > 0 || flag2)
					{
						jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2));
					}
					if (jSONNode != null)
					{
						jSONNode.Inline = !flag3;
					}
					flag2 = false;
					aKey = "";
					stringBuilder.Length = 0;
					if (stack.Count > 0)
					{
						jSONNode = stack.Peek();
					}
					break;
				case ':':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					aKey = stringBuilder.ToString();
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '"':
					flag = !flag;
					flag2 = flag2 || flag;
					break;
				case ',':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stringBuilder.Length > 0 || flag2)
					{
						jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2));
					}
					flag2 = false;
					aKey = "";
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '\n':
				case '\r':
					flag3 = true;
					break;
				case '\t':
				case ' ':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
					}
					break;
				case '\\':
					i++;
					if (flag)
					{
						char c = aJSON[i];
						switch (c)
						{
						case 't':
							stringBuilder.Append('\t');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'b':
							stringBuilder.Append('\b');
							break;
						case 'f':
							stringBuilder.Append('\f');
							break;
						case 'u':
						{
							string s = aJSON.Substring(i + 1, 4);
							stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier));
							i += 4;
							break;
						}
						default:
							stringBuilder.Append(c);
							break;
						}
					}
					break;
				case '/':
					if (allowLineComments && !flag && i + 1 < aJSON.Length && aJSON[i + 1] == '/')
					{
						while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r')
						{
						}
					}
					else
					{
						stringBuilder.Append(aJSON[i]);
					}
					break;
				default:
					stringBuilder.Append(aJSON[i]);
					break;
				case '\ufeff':
					break;
				}
			}
			if (flag)
			{
				throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
			}
			if (jSONNode == null)
			{
				return ParseElement(stringBuilder.ToString(), flag2);
			}
			return jSONNode;
		}

		public abstract void SerializeBinary(BinaryWriter aWriter);

		public void SaveToBinaryStream(Stream aData)
		{
			BinaryWriter aWriter = new BinaryWriter(aData);
			SerializeBinary(aWriter);
		}

		public void SaveToCompressedStream(Stream aData)
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public void SaveToCompressedFile(string aFileName)
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public string SaveToCompressedBase64()
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public void SaveToBinaryFile(string aFileName)
		{
			Directory.CreateDirectory(new FileInfo(aFileName).Directory.FullName);
			using FileStream aData = File.OpenWrite(aFileName);
			SaveToBinaryStream(aData);
		}

		public string SaveToBinaryBase64()
		{
			using MemoryStream memoryStream = new MemoryStream();
			SaveToBinaryStream(memoryStream);
			memoryStream.Position = 0L;
			return Convert.ToBase64String(memoryStream.ToArray());
		}

		public static JSONNode DeserializeBinary(BinaryReader aReader)
		{
			JSONNodeType jSONNodeType = (JSONNodeType)aReader.ReadByte();
			switch (jSONNodeType)
			{
			case JSONNodeType.Array:
			{
				int num2 = aReader.ReadInt32();
				JSONArray jSONArray = new JSONArray();
				for (int j = 0; j < num2; j++)
				{
					jSONArray.Add(DeserializeBinary(aReader));
				}
				return jSONArray;
			}
			case JSONNodeType.Object:
			{
				int num = aReader.ReadInt32();
				JSONObject jSONObject = new JSONObject();
				for (int i = 0; i < num; i++)
				{
					string aKey = aReader.ReadString();
					JSONNode aItem = DeserializeBinary(aReader);
					jSONObject.Add(aKey, aItem);
				}
				return jSONObject;
			}
			case JSONNodeType.String:
				return new JSONString(aReader.ReadString());
			case JSONNodeType.Number:
				return new JSONNumber(aReader.ReadDouble());
			case JSONNodeType.Boolean:
				return new JSONBool(aReader.ReadBoolean());
			case JSONNodeType.NullValue:
				return JSONNull.CreateOrGet();
			default:
				throw new Exception("Error deserializing JSON. Unknown tag: " + jSONNodeType);
			}
		}

		public static JSONNode LoadFromCompressedFile(string aFileName)
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public static JSONNode LoadFromCompressedStream(Stream aData)
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public static JSONNode LoadFromCompressedBase64(string aBase64)
		{
			throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}

		public static JSONNode LoadFromBinaryStream(Stream aData)
		{
			using BinaryReader aReader = new BinaryReader(aData);
			return DeserializeBinary(aReader);
		}

		public static JSONNode LoadFromBinaryFile(string aFileName)
		{
			using FileStream aData = File.OpenRead(aFileName);
			return LoadFromBinaryStream(aData);
		}

		public static JSONNode LoadFromBinaryBase64(string aBase64)
		{
			return LoadFromBinaryStream(new MemoryStream(Convert.FromBase64String(aBase64))
			{
				Position = 0L
			});
		}

		public static implicit operator JSONNode(decimal aDecimal)
		{
			return new JSONString(aDecimal.ToString());
		}

		public static implicit operator decimal(JSONNode aNode)
		{
			return aNode.AsDecimal;
		}

		public static implicit operator JSONNode(char aChar)
		{
			return new JSONString(aChar.ToString());
		}

		public static implicit operator char(JSONNode aNode)
		{
			return aNode.AsChar;
		}

		public static implicit operator JSONNode(uint aUInt)
		{
			return new JSONNumber(aUInt);
		}

		public static implicit operator uint(JSONNode aNode)
		{
			return aNode.AsUInt;
		}

		public static implicit operator JSONNode(byte aByte)
		{
			return new JSONNumber((int)aByte);
		}

		public static implicit operator byte(JSONNode aNode)
		{
			return aNode.AsByte;
		}

		public static implicit operator JSONNode(sbyte aSByte)
		{
			return new JSONNumber(aSByte);
		}

		public static implicit operator sbyte(JSONNode aNode)
		{
			return aNode.AsSByte;
		}

		public static implicit operator JSONNode(short aShort)
		{
			return new JSONNumber(aShort);
		}

		public static implicit operator short(JSONNode aNode)
		{
			return aNode.AsShort;
		}

		public static implicit operator JSONNode(ushort aUShort)
		{
			return new JSONNumber((int)aUShort);
		}

		public static implicit operator ushort(JSONNode aNode)
		{
			return aNode.AsUShort;
		}

		public static implicit operator JSONNode(DateTime aDateTime)
		{
			return new JSONString(aDateTime.ToString(CultureInfo.InvariantCulture));
		}

		public static implicit operator DateTime(JSONNode aNode)
		{
			return aNode.AsDateTime;
		}

		public static implicit operator JSONNode(TimeSpan aTimeSpan)
		{
			return new JSONString(aTimeSpan.ToString());
		}

		public static implicit operator TimeSpan(JSONNode aNode)
		{
			return aNode.AsTimeSpan;
		}

		public static implicit operator JSONNode(Guid aGuid)
		{
			return new JSONString(aGuid.ToString());
		}

		public static implicit operator Guid(JSONNode aNode)
		{
			return aNode.AsGuid;
		}

		public static implicit operator JSONNode(byte[] aByteArray)
		{
			return new JSONArray
			{
				AsByteArray = aByteArray
			};
		}

		public static implicit operator byte[](JSONNode aNode)
		{
			return aNode.AsByteArray;
		}

		public static implicit operator JSONNode(List<byte> aByteList)
		{
			return new JSONArray
			{
				AsByteList = aByteList
			};
		}

		public static implicit operator List<byte>(JSONNode aNode)
		{
			return aNode.AsByteList;
		}

		public static implicit operator JSONNode(string[] aStringArray)
		{
			return new JSONArray
			{
				AsStringArray = aStringArray
			};
		}

		public static implicit operator string[](JSONNode aNode)
		{
			return aNode.AsStringArray;
		}

		public static implicit operator JSONNode(List<string> aStringList)
		{
			return new JSONArray
			{
				AsStringList = aStringList
			};
		}

		public static implicit operator List<string>(JSONNode aNode)
		{
			return aNode.AsStringList;
		}

		public static implicit operator JSONNode(int? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONNumber(aValue.Value);
		}

		public static implicit operator int?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsInt;
		}

		public static implicit operator JSONNode(float? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONNumber(aValue.Value);
		}

		public static implicit operator float?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsFloat;
		}

		public static implicit operator JSONNode(double? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONNumber(aValue.Value);
		}

		public static implicit operator double?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsDouble;
		}

		public static implicit operator JSONNode(bool? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONBool(aValue.Value);
		}

		public static implicit operator bool?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsBool;
		}

		public static implicit operator JSONNode(long? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONNumber(aValue.Value);
		}

		public static implicit operator long?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsLong;
		}

		public static implicit operator JSONNode(short? aValue)
		{
			if (!aValue.HasValue)
			{
				return JSONNull.CreateOrGet();
			}
			return new JSONNumber(aValue.Value);
		}

		public static implicit operator short?(JSONNode aNode)
		{
			if (aNode == null || aNode.IsNull)
			{
				return null;
			}
			return aNode.AsShort;
		}
	}
	public class JSONArray : JSONNode
	{
		private List<JSONNode> m_List = new List<JSONNode>();

		private bool inline;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Array;

		public override bool IsArray => true;

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					return new JSONLazyCreator(this);
				}
				return m_List[aIndex];
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					m_List.Add(value);
				}
				else
				{
					m_List[aIndex] = value;
				}
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				m_List.Add(value);
			}
		}

		public override int Count => m_List.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (JSONNode item in m_List)
				{
					yield return item;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_List.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			m_List.Add(aItem);
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_List.Count)
			{
				return null;
			}
			JSONNode result = m_List[aIndex];
			m_List.RemoveAt(aIndex);
			return result;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			m_List.Remove(aNode);
			return aNode;
		}

		public override void Clear()
		{
			m_List.Clear();
		}

		public override JSONNode Clone()
		{
			JSONArray jSONArray = new JSONArray();
			jSONArray.m_List.Capacity = m_List.Capacity;
			foreach (JSONNode item in m_List)
			{
				if (item != null)
				{
					jSONArray.Add(item.Clone());
				}
				else
				{
					jSONArray.Add(null);
				}
			}
			return jSONArray;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('[');
			int count = m_List.Count;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			for (int i = 0; i < count; i++)
			{
				if (i > 0)
				{
					aSB.Append(',');
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append(']');
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)1);
			aWriter.Write(m_List.Count);
			for (int i = 0; i < m_List.Count; i++)
			{
				m_List[i].SerializeBinary(aWriter);
			}
		}
	}
	public class JSONObject : JSONNode
	{
		private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();

		private bool inline;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Object;

		public override bool IsObject => true;

		public override JSONNode this[string aKey]
		{
			get
			{
				if (m_Dict.ContainsKey(aKey))
				{
					return m_Dict[aKey];
				}
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = value;
				}
				else
				{
					m_Dict.Add(aKey, value);
				}
			}
		}

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_Dict.Count)
				{
					return null;
				}
				return m_Dict.ElementAt(aIndex).Value;
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex >= 0 && aIndex < m_Dict.Count)
				{
					string key = m_Dict.ElementAt(aIndex).Key;
					m_Dict[key] = value;
				}
			}
		}

		public override int Count => m_Dict.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (KeyValuePair<string, JSONNode> item in m_Dict)
				{
					yield return item.Value;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_Dict.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			if (aKey != null)
			{
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = aItem;
				}
				else
				{
					m_Dict.Add(aKey, aItem);
				}
			}
			else
			{
				m_Dict.Add(Guid.NewGuid().ToString(), aItem);
			}
		}

		public override JSONNode Remove(string aKey)
		{
			if (!m_Dict.ContainsKey(aKey))
			{
				return null;
			}
			JSONNode result = m_Dict[aKey];
			m_Dict.Remove(aKey);
			return result;
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_Dict.Count)
			{
				return null;
			}
			KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex);
			m_Dict.Remove(keyValuePair.Key);
			return keyValuePair.Value;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			try
			{
				KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First();
				m_Dict.Remove(keyValuePair.Key);
				return aNode;
			}
			catch
			{
				return null;
			}
		}

		public override void Clear()
		{
			m_Dict.Clear();
		}

		public override JSONNode Clone()
		{
			JSONObject jSONObject = new JSONObject();
			foreach (KeyValuePair<string, JSONNode> item in m_Dict)
			{
				jSONObject.Add(item.Key, item.Value.Clone());
			}
			return jSONObject;
		}

		public override bool HasKey(string aKey)
		{
			return m_Dict.ContainsKey(aKey);
		}

		public override JSONNode GetValueOrDefault(string aKey, JSONNode aDefault)
		{
			if (m_Dict.TryGetValue(aKey, out var value))
			{
				return value;
			}
			return aDefault;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('{');
			bool flag = true;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			foreach (KeyValuePair<string, JSONNode> item in m_Dict)
			{
				if (!flag)
				{
					aSB.Append(',');
				}
				flag = false;
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"');
				if (aMode == JSONTextMode.Compact)
				{
					aSB.Append(':');
				}
				else
				{
					aSB.Append(" : ");
				}
				item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append('}');
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)2);
			aWriter.Write(m_Dict.Count);
			foreach (string key in m_Dict.Keys)
			{
				aWriter.Write(key);
				m_Dict[key].SerializeBinary(aWriter);
			}
		}
	}
	public class JSONString : JSONNode
	{
		private string m_Data;

		public override JSONNodeType Tag => JSONNodeType.String;

		public override bool IsString => true;

		public override string Value
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONString(string aData)
		{
			m_Data = aData;
		}

		public override JSONNode Clone()
		{
			return new JSONString(m_Data);
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"');
		}

		public override bool Equals(object obj)
		{
			if (base.Equals(obj))
			{
				return true;
			}
			if (obj is string text)
			{
				return m_Data == text;
			}
			JSONString jSONString = obj as JSONString;
			if (jSONString != null)
			{
				return m_Data == jSONString.m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}

		public override void Clear()
		{
			m_Data = "";
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)3);
			aWriter.Write(m_Data);
		}
	}
	public class JSONNumber : JSONNode
	{
		private double m_Data;

		public override JSONNodeType Tag => JSONNodeType.Number;

		public override bool IsNumber => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString(CultureInfo.InvariantCulture);
			}
			set
			{
				if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override double AsDouble
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override long AsLong
		{
			get
			{
				return (long)m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override ulong AsULong
		{
			get
			{
				return (ulong)m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONNumber(double aData)
		{
			m_Data = aData;
		}

		public JSONNumber(string aData)
		{
			Value = aData;
		}

		public override JSONNode Clone()
		{
			return new JSONNumber(m_Data);
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(Value);
		}

		private static bool IsNumeric(object value)
		{
			if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte))
			{
				return value is byte;
			}
			return true;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (base.Equals(obj))
			{
				return true;
			}
			JSONNumber jSONNumber = obj as JSONNumber;
			if (jSONNumber != null)
			{
				return m_Data == jSONNumber.m_Data;
			}
			if (IsNumeric(obj))
			{
				return Convert.ToDouble(obj) == m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}

		public override void Clear()
		{
			m_Data = 0.0;
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)4);
			aWriter.Write(m_Data);
		}
	}
	public class JSONBool : JSONNode
	{
		private bool m_Data;

		public override JSONNodeType Tag => JSONNodeType.Boolean;

		public override bool IsBoolean => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString();
			}
			set
			{
				if (bool.TryParse(value, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override bool AsBool
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONBool(bool aData)
		{
			m_Data = aData;
		}

		public JSONBool(string aData)
		{
			Value = aData;
		}

		public override JSONNode Clone()
		{
			return new JSONBool(m_Data);
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(m_Data ? "true" : "false");
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is bool)
			{
				return m_Data == (bool)obj;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}

		public override void Clear()
		{
			m_Data = false;
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)6);
			aWriter.Write(m_Data);
		}
	}
	public class JSONNull : JSONNode
	{
		private static JSONNull m_StaticInstance = new JSONNull();

		public static bool reuseSameInstance = true;

		public override JSONNodeType Tag => JSONNodeType.NullValue;

		public override bool IsNull => true;

		public override string Value
		{
			get
			{
				return "null";
			}
			set
			{
			}
		}

		public override bool AsBool
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public static JSONNull CreateOrGet()
		{
			if (reuseSameInstance)
			{
				return m_StaticInstance;
			}
			return new JSONNull();
		}

		private JSONNull()
		{
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public override JSONNode Clone()
		{
			return CreateOrGet();
		}

		public override bool Equals(object obj)
		{
			if ((object)this == obj)
			{
				return true;
			}
			return obj is JSONNull;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
			aWriter.Write((byte)5);
		}
	}
	internal class JSONLazyCreator : JSONNode
	{
		private JSONNode m_Node;

		private string m_Key;

		public override JSONNodeType Tag => JSONNodeType.None;

		public override JSONNode this[int aIndex]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				Set(new JSONArray()).Add(value);
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				Set(new JSONObject()).Add(aKey, value);
			}
		}

		public override int AsInt
		{
			get
			{
				Set(new JSONNumber(0.0));
				return 0;
			}
			set
			{
				Set(new JSONNumber(value));
			}
		}

		public override float AsFloat
		{
			get
			{
				Set(new JSONNumber(0.0));
				return 0f;
			}
			set
			{
				Set(new JSONNumber(value));
			}
		}

		public override double AsDouble
		{
			get
			{
				Set(new JSONNumber(0.0));
				return 0.0;
			}
			set
			{
				Set(new JSONNumber(value));
			}
		}

		public override long AsLong
		{
			get
			{
				if (JSONNode.longAsString)
				{
					Set(new JSONString("0"));
				}
				else
				{
					Set(new JSONNumber(0.0));
				}
				return 0L;
			}
			set
			{
				if (JSONNode.longAsString)
				{
					Set(new JSONString(value.ToString()));
				}
				else
				{
					Set(new JSONNumber(value));
				}
			}
		}

		public override ulong AsULong
		{
			get
			{
				if (JSONNode.longAsString)
				{
					Set(new JSONString("0"));
				}
				else
				{
					Set(new JSONNumber(0.0));
				}
				return 0uL;
			}
			set
			{
				if (JSONNode.longAsString)
				{
					Set(new JSONString(value.ToString()));
				}
				else
				{
					Set(new JSONNumber(value));
				}
			}
		}

		public override bool AsBool
		{
			get
			{
				Set(new JSONBool(aData: false));
				return false;
			}
			set
			{
				Set(new JSONBool(value));
			}
		}

		public override JSONArray AsArray => Set(new JSONArray());

		public override JSONObject AsObject => Set(new JSONObject());

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONLazyCreator(JSONNode aNode)
		{
			m_Node = aNode;
			m_Key = null;
		}

		public JSONLazyCreator(JSONNode aNode, string aKey)
		{
			m_Node = aNode;
			m_Key = aKey;
		}

		private T Set<T>(T aVal) where T : JSONNode
		{
			if (m_Key == null)
			{
				m_Node.Add(aVal);
			}
			else
			{
				m_Node.Add(m_Key, aVal);
			}
			m_Node = null;
			return aVal;
		}

		public override void Add(JSONNode aItem)
		{
			Set(new JSONArray()).Add(aItem);
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			Set(new JSONObject()).Add(aKey, aItem);
		}

		public static bool operator ==(JSONLazyCreator a, object b)
		{
			if (b == null)
			{
				return true;
			}
			return (object)a == b;
		}

		public static bool operator !=(JSONLazyCreator a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return true;
			}
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}

		public override void SerializeBinary(BinaryWriter aWriter)
		{
		}
	}
	public static class JSON
	{
		public static JSONNode Parse(string aJSON)
		{
			return JSONNode.Parse(aJSON);
		}
	}
}
namespace AuthoritativeConfig
{
	public class Config
	{
		private static Config _instance;

		public Dictionary<string, ConfigBaseEntry> _configEntries;

		public BaseUnityPlugin _mod;

		private static ConfigEntry<bool> _serverIsAuthoritative;

		private static bool _defaultBindAuthority;

		public static ManualLogSource Logger;

		public UnityEvent OnConfigReceived = new UnityEvent();

		public static Config Instance => _instance ?? (_instance = new Config());

		public static ZNet ZNet => ZNet.instance;

		public static string GUID => Instance._mod.Info.Metadata.GUID;

		public static string RPC_SYNC_GUID => "AuthoritativeConfig_" + GUID;

		public static int RPC_SYNC_HASH => StringExtensionMethods.GetStableHashCode(RPC_SYNC_GUID);

		public void Init(BaseUnityPlugin mod, bool defaultBindServerAuthority = false)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			_mod = mod;
			Logger = new ManualLogSource(RPC_SYNC_GUID);
			Logger.Sources.Add((ILogSource)(object)Logger);
			_configEntries = new Dictionary<string, ConfigBaseEntry>();
			_defaultBindAuthority = defaultBindServerAuthority;
			_serverIsAuthoritative = _mod.Config.Bind<bool>("ServerAuthoritativeConfig", "ServerIsAuthoritative", true, "<Server Only> Forces Clients to use Server defined configs.");
			Harmony.CreateAndPatchAll(typeof(Config), (string)null);
			Logger.LogInfo((object)"Initialized Server Authoritative Config Manager.");
		}

		[HarmonyPatch(typeof(Game), "Start")]
		[HarmonyPostfix]
		protected static void RegisterSyncConfigRPC()
		{
			if (!ZRoutedRpc.instance.m_functions.ContainsKey(RPC_SYNC_HASH))
			{
				Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID));
				ZRoutedRpc.instance.Register<ZPackage>(RPC_SYNC_GUID, (Action<long, ZPackage>)RPC_SyncServerConfig);
			}
			foreach (ConfigBaseEntry value in Instance._configEntries.Values)
			{
				value.ClearServerValue();
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		[HarmonyPostfix]
		protected static void RequestConfigFromServer()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			if (!ZNet.IsServer() && (int)ZNet.GetConnectionStatus() == 2)
			{
				long? num = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long?;
				ZRoutedRpc.instance.InvokeRoutedRPC(num.Value, RPC_SYNC_GUID, new object[1] { (object)new ZPackage() });
				Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID));
				Debug.Log((object)(Instance._mod.Info.Metadata.Name + ": Authoritative Config Requested -> " + RPC_SYNC_GUID));
			}
			else if (!ZNet.IsServer())
			{
				Logger.LogWarning((object)"Failed to Request Configs. Bad Peer? Too Early?");
			}
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null)
		{
			ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority);
			_configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry;
			return configEntry;
		}

		public ConfigEntry<T> Bind<T>(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null)
		{
			ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(configDefinition, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority);
			_configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry;
			return configEntry;
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, bool? serverAuthoritative = null)
		{
			ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, description), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority);
			_configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry;
			return configEntry;
		}

		public static void SendConfigToClient(long sender)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			if (!ZNet.IsServer())
			{
				return;
			}
			ZPackage val = new ZPackage();
			int num = 0;
			foreach (KeyValuePair<string, ConfigBaseEntry> configEntry in Instance._configEntries)
			{
				if (configEntry.Value.ServerAuthoritative)
				{
					val.Write(configEntry.Key);
					val.Write(configEntry.Value.BaseEntry.GetSerializedValue());
					num++;
					Logger.LogInfo((object)("Sending Config " + configEntry.Key + ": " + configEntry.Value.BaseEntry.GetSerializedValue()));
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, RPC_SYNC_GUID, new object[1] { val });
			Logger.LogInfo((object)$"Sent {num} config pairs to client {sender}");
		}

		public static void ReadConfigPkg(ZPackage pkg)
		{
			if (ZNet.IsServer())
			{
				return;
			}
			int num = 0;
			while (pkg.GetPos() != pkg.Size())
			{
				string text = pkg.ReadString();
				string text2 = pkg.ReadString();
				num++;
				if (Instance._configEntries.ContainsKey(text))
				{
					Instance._configEntries[text].SetSerializedValue(text2);
					Logger.LogInfo((object)("Applied Server Authoritative config pair => " + text + ": " + text2));
				}
				else
				{
					Logger.LogError((object)("Recieved config key we dont have locally. Possible Version Mismatch. " + text + ": " + text2));
				}
			}
			Logger.LogInfo((object)$"Applied {num} config pairs");
			UnityEvent onConfigReceived = Instance.OnConfigReceived;
			if (onConfigReceived != null)
			{
				onConfigReceived.Invoke();
			}
		}

		public static void RPC_SyncServerConfig(long sender, ZPackage pkg)
		{
			if (ZNet.IsServer() && _serverIsAuthoritative.Value)
			{
				SendConfigToClient(sender);
			}
			else if (!ZNet.IsServer() && pkg != null && pkg.Size() > 0 && AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long? == sender)
			{
				ReadConfigPkg(pkg);
			}
		}
	}
	public class ConfigBaseEntry
	{
		protected object _serverValue;

		public ConfigEntryBase BaseEntry;

		public bool ServerAuthoritative;

		protected bool _didError;

		internal ConfigBaseEntry(ConfigEntryBase configEntry, bool serverAuthoritative)
		{
			BaseEntry = configEntry;
			ServerAuthoritative = serverAuthoritative;
		}

		public void SetSerializedValue(string value)
		{
			try
			{
				_serverValue = TomlTypeConverter.ConvertToValue(value, BaseEntry.SettingType);
				_didError = false;
			}
			catch (Exception ex)
			{
				Config.Logger.LogWarning((object)$"Config value of setting \"{BaseEntry.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}");
			}
		}

		public void ClearServerValue()
		{
			_serverValue = null;
			_didError = false;
		}
	}
	public class ConfigEntry<T> : ConfigBaseEntry
	{
		private readonly ConfigEntry<T> _configEntry;

		public T ServerValue => (T)_serverValue;

		public T Value
		{
			get
			{
				if (ServerAuthoritative && (Object)(object)Config.ZNet != (Object)null && !Config.ZNet.IsServer())
				{
					if (_serverValue != null)
					{
						return ServerValue;
					}
					if (!_didError)
					{
						Config.Logger.LogWarning((object)$"No Recieved value for Server Authoritative Config. {BaseEntry.Definition}. Falling Back to Client Config.");
						_didError = true;
					}
					return _configEntry.Value;
				}
				return _configEntry.Value;
			}
			set
			{
				_configEntry.Value = value;
			}
		}

		internal ConfigEntry(ConfigEntry<T> configEntry, bool serverAuthoritative)
			: base((ConfigEntryBase)(object)configEntry, serverAuthoritative)
		{
			_configEntry = configEntry;
		}
	}
}