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