Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of balrond lightkeeper v1.0.0
plugins/BalrondLightkeeper.dll
Decompiled 3 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using HarmonyLib; using LitJson2; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("LightController")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LightController")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d2273ae8-aeed-4e80-94d5-3d5f9d843737")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace LightController { public class BalrondTranslator { public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>(); public static Dictionary<string, string> getLanguage(string language) { if (string.IsNullOrEmpty(language)) { return null; } if (translations.TryGetValue(language, out var value)) { return value; } return null; } } [HarmonyPatch(typeof(Container), "Interact")] public static class Container_Interact_Patch { private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result) { if (hold) { return true; } FireController component = ((Component)__instance).GetComponent<FireController>(); if ((Object)(object)component == (Object)null) { return true; } if (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)) { component.ToggleNetworkFromUser(character); __result = true; return false; } if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) { component.ToggleNetworkAutoFuelFromUser(character); __result = true; return false; } return true; } } [HarmonyPatch(typeof(Container), "GetHoverText")] public static class Container_GetHoverText_Patch { private static bool Prefix(Container __instance, ref string __result) { FireController component = ((Component)__instance).GetComponent<FireController>(); if ((Object)(object)component == (Object)null) { return true; } __result = component.GetHoverText(); return false; } } [HarmonyPatch(typeof(Container), "GetHoverName")] public static class Container_GetHoverName_Patch { private static bool Prefix(Container __instance, ref string __result) { FireController component = ((Component)__instance).GetComponent<FireController>(); if ((Object)(object)component == (Object)null) { return true; } __result = component.GetHoverName(); return false; } } [HarmonyPatch(typeof(Fireplace), "IsBurning")] public static class Fireplace_IsBurning_Patch { private static bool Prefix(Fireplace __instance, ref bool __result) { LightEnabler component = ((Component)__instance).GetComponent<LightEnabler>(); if ((Object)(object)component != (Object)null && !component.AllowBurning()) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Fireplace), "GetHoverText")] public static class Fireplace_GetHoverText_Patch { private static void Postfix(Fireplace __instance, ref string __result) { LightEnabler component = ((Component)__instance).GetComponent<LightEnabler>(); if (!((Object)(object)component == (Object)null)) { __result += Localization.instance.Localize(component.IsIgnored() ? "\n[<color=yellow><b>Ctrl + $KEY_Use</b></color>] $tag_lightkeeper_fire_obey_bal" : "\n[<color=yellow><b>Ctrl + $KEY_Use</b></color>] $tag_lightkeeper_fire_ignore_bal"); } } } [HarmonyPatch(typeof(Fireplace), "Interact")] public static class Fireplace_Interact_Patch { private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt, ref bool __result) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (hold) { return true; } if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)) { return true; } LightEnabler component = ((Component)__instance).GetComponent<LightEnabler>(); if ((Object)(object)component == (Object)null) { return true; } if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false)) { __result = true; return false; } bool flag = !component.IsIgnored(); component.SetIgnored(flag); Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val != (Object)null) { ((Character)val).Message((MessageType)2, flag ? "$tag_lightkeeper_fire_msg_ignored_bal" : "$tag_lightkeeper_fire_msg_obey_bal", 0, (Sprite)null); } __result = true; return false; } } public class JsonLoader { public string defaultPath = string.Empty; public void loadJson() { LoadTranslations(); justDefaultPath(); } public void justDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZZZBalrondLightkeeper-translation/"); defaultPath = text; } public void createDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZZZBalrondLightkeeper-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("ZZZBalrondLightkeeper: Folder already exists: " + text)); } defaultPath = text; } private string[] jsonFilePath(string folderName, string extension) { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZZZBalrondLightkeeper-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("ZZZBalrondLightkeeper: Folder already exists: " + text)); } string[] files = Directory.GetFiles(text, extension); Debug.Log((object)("ZZZBalrondLightkeeper:" + folderName + " Json Files Found: " + files.Length)); return files; } private static void CreateFolder(string path) { try { Directory.CreateDirectory(path); Debug.Log((object)"ZZZBalrondLightkeeper: Folder created successfully."); } catch (Exception ex) { Debug.Log((object)("ZZZBalrondLightkeeper: Error creating folder: " + ex.Message)); } } private void LoadTranslations() { int num = 0; string[] array = jsonFilePath("Translation", "*.json"); foreach (string text in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string json = File.ReadAllText(text); JsonData jsonData = JsonMapper.ToObject(json); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string key in jsonData.Keys) { dictionary[key] = jsonData[key].ToString(); } if (dictionary != null) { BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary); Debug.Log((object)("ZZZBalrondLightkeeper: Json Files Language: " + fileNameWithoutExtension)); num++; } else { Debug.LogError((object)("ZZZBalrondLightkeeper: Loading FAILED file: " + text)); } } Debug.Log((object)("ZZZBalrondLightkeeper: Translation JsonFiles Loaded: " + num)); } } [BepInPlugin("balrond.astafaraios.BalrondLightkeeper", "ZZZBalrondLightkeeper", "1.3.0")] public class Launch : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class ZNetScene_Awake_Patch { private static void Prefix(ZNetScene __instance) { if ((Object)(object)__instance == (Object)null) { return; } GameObject val = __instance.m_prefabs.Find((GameObject x) => ((Object)x).name == "Hammer"); if ((Object)(object)val == (Object)null) { return; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { return; } PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces; if ((Object)(object)buildPieces == (Object)null) { return; } List<GameObject> list = __instance.m_prefabs.FindAll((GameObject x) => (Object)(object)x.GetComponent<Fireplace>() != (Object)null); foreach (GameObject item in list) { AddLightEnabler(item); } foreach (GameObject prefab in prefabs) { if (!((Object)(object)prefab == (Object)null)) { if (((Object)prefab).name == "FireController") { SetupLightController(prefab, __instance); CreateLightControllerRecipe(prefab, __instance); } if (!buildPieces.m_pieces.Any((GameObject x) => ((Object)x).name == ((Object)prefab).name)) { buildPieces.m_pieces.Add(prefab); } if (!__instance.m_prefabs.Any((GameObject x) => ((Object)x).name == ((Object)prefab).name)) { __instance.m_prefabs.Add(prefab); } } } } } public const string PluginGUID = "balrond.astafaraios.BalrondLightkeeper"; public const string PluginName = "ZZZBalrondLightkeeper"; public const string PluginVersion = "1.3.0"; public static JsonLoader jsonLoader = new JsonLoader(); private readonly Harmony harmony = new Harmony("balrond.astafaraios.BalrondLightkeeper"); private static AssetBundle assetBundle; private static readonly List<GameObject> prefabs = new List<GameObject>(); private static readonly string[] bundleNames = new string[1] { "lightcontroller" }; private static readonly string[] prefabNames = new string[1] { "FireController" }; private void Awake() { jsonLoader.loadJson(); LoadAllAssetBundles(); harmony.PatchAll(); } private void OnDestroy() { harmony.UnpatchSelf(); } private static void LoadAllAssetBundles() { string[] array = bundleNames; foreach (string filename in array) { assetBundle = GetAssetBundleFromResources(filename); LoadPrefabs(assetBundle); } } private 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); } private static void LoadPrefabs(AssetBundle bundle) { string[] array = prefabNames; foreach (string text in array) { GameObject prefab = bundle.LoadAsset<GameObject>("Assets/CustomItems/LightController/" + text + ".prefab"); prefab.SetActive(true); if (!prefabs.Any((GameObject x) => ((Object)x).name == ((Object)prefab).name)) { prefabs.Add(prefab); } } } private static void AddLightEnabler(GameObject prefab) { if (!((Object)(object)prefab == (Object)null) && (Object)(object)prefab.GetComponent<LightEnabler>() == (Object)null) { prefab.AddComponent<LightEnabler>(); } } private static void SetupLightController(GameObject prefab, ZNetScene scene) { FireController fireController = prefab.GetComponent<FireController>(); if ((Object)(object)fireController == (Object)null) { fireController = prefab.AddComponent<FireController>(); } SetupLightControllerContainer(prefab, scene); GameObject val = scene.m_prefabs.Find((GameObject x) => ((Object)x).name == "guard_stone"); PrivateArea val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<PrivateArea>() : null); Transform val3 = prefab.transform.Find("_enabled"); Transform val4 = prefab.transform.Find("_disabled"); Transform val5 = prefab.transform.Find("AreaMarker"); fireController.m_name = "$tag_lightkeeper_name_bal"; fireController.m_radius = 20f; fireController.m_updateConnectionsInterval = 5f; fireController.m_switchOn = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : null); fireController.m_switchOff = (((Object)(object)val4 != (Object)null) ? ((Component)val4).gameObject : null); fireController.m_areaMarker = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<CircleProjector>() : null); if ((Object)(object)val2 != (Object)null) { fireController.m_connectEffect = val2.m_connectEffect; fireController.m_inRangeEffect = val2.m_inRangeEffect; fireController.m_activateEffect = val2.m_activateEffect; fireController.m_deactivateEffect = val2.m_deactivateEffect; } } private static void SetupLightControllerContainer(GameObject prefab, ZNetScene scene) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) Container val = prefab.GetComponent<Container>(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent<Container>(); } GameObject val2 = scene.m_prefabs.Find((GameObject x) => ((Object)x).name == "piece_chest"); Container val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Container>() : null); val.m_name = "$tag_lightkeeper_name_bal"; val.m_width = 3; val.m_height = 4; val.m_privacy = (PrivacySetting)2; val.m_checkGuardStone = true; val.m_autoDestroyEmpty = false; if ((Object)(object)val3 != (Object)null) { val.m_bkg = val3.m_bkg; val.m_openEffects = val3.m_openEffects; val.m_closeEffects = val3.m_closeEffects; val.m_destroyedLootPrefab = val3.m_destroyedLootPrefab; } val.m_open = null; val.m_closed = null; val.m_rootObjectOverride = null; val.m_wagon = null; } private static void CreateLightControllerRecipe(GameObject prefab, ZNetScene scene) { Piece component = prefab.GetComponent<Piece>(); component.m_name = "$tag_lightkeeper_name_bal"; component.m_description = "$tag_lightkeeper_description_bal"; if (!((Object)(object)component == (Object)null)) { GameObject val = scene.m_prefabs.Find((GameObject x) => ((Object)x).name == "piece_stonecutter"); if ((Object)(object)val != (Object)null) { component.m_craftingStation = val.GetComponent<CraftingStation>(); } component.m_resources = ((IEnumerable<Requirement>)(object)new Requirement[4] { Requirement(scene, "Stone", 20), Requirement(scene, "Ruby", 4), Requirement(scene, "Tin", 5), Requirement(scene, "Resin", 15) }).Where((Requirement x) => (Object)(object)x.m_resItem != (Object)null).ToArray(); } } private static Requirement Requirement(ZNetScene scene, string prefabName, int amount) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown GameObject val = scene.m_prefabs.Find((GameObject x) => ((Object)x).name == prefabName); return new Requirement { m_amount = amount, m_recover = true, m_resItem = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null) }; } } public class FireController : MonoBehaviour, Hoverable, Interactable { private const string ZdoEnabled = "LC_enabled"; private const string ZdoAutoFuel = "LC_autofuel"; private const string ZdoInitialized = "LC_initialized"; private const string ZdoRadius = "LC_radius"; private const string RpcSetNetworkState = "LC_SetNetworkState"; private const string RpcSetNetworkAutoFuel = "LC_SetNetworkAutoFuel"; private const float MinRadius = 5f; private const float MaxRadius = 50f; private const float RadiusStep = 1f; private const float ConnectionBeamHeight = 0.85f; public string m_name = "$tag_lightkeeper_name_bal"; public float m_radius = 20f; public float m_updateConnectionsInterval = 5f; public CircleProjector m_areaMarker; public EffectList m_activateEffect = new EffectList(); public EffectList m_deactivateEffect = new EffectList(); public GameObject m_connectEffect; public GameObject m_inRangeEffect; public GameObject m_switchOn; public GameObject m_switchOff; public ZNetView m_nview; public Piece m_piece; public Container m_container; private readonly List<GameObject> m_connectionInstances = new List<GameObject>(); private readonly List<FireController> m_connectedAreas = new List<FireController>(); private LightControllerFuelService m_fuelService; private float m_connectionUpdateTime = -1000f; private float m_lastHoverTime = -1000f; private bool m_tempChecked; private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { m_piece = ((Component)this).GetComponent<Piece>(); m_container = ((Component)this).GetComponent<Container>(); WearNTear component = ((Component)this).GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { component.m_onDamaged = (Action)Delegate.Combine(component.m_onDamaged, new Action(OnDamaged)); } if ((Object)(object)m_areaMarker != (Object)null) { m_areaMarker.m_radius = GetRadius(); ((Component)m_areaMarker).gameObject.SetActive(false); } if ((Object)(object)m_inRangeEffect != (Object)null) { m_inRangeEffect.SetActive(false); } LightControllerRegistry.RegisterController(this); if (m_nview.IsOwner() && m_nview.GetZDO().GetInt("LC_initialized", 0) == 0) { m_nview.GetZDO().Set("LC_initialized", 1); m_nview.GetZDO().Set("LC_enabled", true); m_nview.GetZDO().Set("LC_autofuel", true); m_nview.GetZDO().Set("LC_radius", m_radius); } m_nview.Register<bool>("LC_SetNetworkState", (Action<long, bool>)RPC_SetNetworkState); m_nview.Register<bool>("LC_SetNetworkAutoFuel", (Action<long, bool>)RPC_SetNetworkAutoFuel); m_fuelService = new LightControllerFuelService(this); ((MonoBehaviour)this).InvokeRepeating("UpdateStatus", 0f, 1f); } } private void OnDestroy() { StopConnectionEffects(); LightControllerRegistry.UnregisterController(this); } private void Update() { HandleRangeInput(); if (m_fuelService != null) { m_fuelService.Update(); } } private void HandleRangeInput() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!(Time.time - m_lastHoverTime > 0.25f) && PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false)) { if (Input.GetKeyDown((KeyCode)61) || Input.GetKeyDown((KeyCode)270)) { ChangeRadius(1f); } if (Input.GetKeyDown((KeyCode)45) || Input.GetKeyDown((KeyCode)269)) { ChangeRadius(-1f); } } } public string GetHoverName() { return Localization.instance.Localize(m_name); } public string GetHoverText() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return string.Empty; } m_lastHoverTime = Time.time; ShowAreaMarker(); PokeConnectionEffects(); if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false)) { return Localization.instance.Localize("$tag_lightkeeper_name_bal\n$tag_lightkeeper_noaccess_bal"); } string value = (IsEnabled() ? "$tag_lightkeeper_on_bal" : "$tag_lightkeeper_off_bal"); string value2 = (IsAutoFuelEnabled() ? "$tag_lightkeeper_on_bal" : "$tag_lightkeeper_off_bal"); StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append("$tag_lightkeeper_name_bal"); stringBuilder.Append(" <color=orange><b>(").Append(value).Append(")</b></color>"); AppendAction(stringBuilder, "$KEY_Use", "$tag_lightkeeper_open_storage_bal", null); AppendAction(stringBuilder, "Alt + $KEY_Use", "$tag_lightkeeper_turn_lights_bal", value); AppendAction(stringBuilder, "Ctrl + $KEY_Use", "$tag_lightkeeper_turn_autofuel_bal", value2); AppendAction(stringBuilder, "+ / -", "$tag_lightkeeper_adjust_range_bal", "<b>" + Mathf.RoundToInt(GetRadius()) + "/" + 50f + "m</b>"); stringBuilder.Append("\n<color=grey>$tag_lightkeeper_storage_skipped_bal</color>"); return Localization.instance.Localize(stringBuilder.ToString()); } private static void AppendAction(StringBuilder text, string key, string label, string value) { text.Append("\n[<color=yellow><b>").Append(key).Append("</b></color>] ") .Append(label); if (!string.IsNullOrEmpty(value)) { text.Append(" : ").Append(value); } } private static string L(string key) { return (Localization.instance != null) ? Localization.instance.Localize(key) : key; } public bool Interact(Humanoid human, bool hold, bool alt) { if (hold) { return false; } if (IsAltHeld()) { ToggleNetworkFromUser(human); return true; } if (IsCtrlHeld()) { ToggleNetworkAutoFuelFromUser(human); return true; } if ((Object)(object)m_container != (Object)null) { return m_container.Interact(human, hold, alt); } ToggleNetworkFromUser(human); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } public void ToggleNetworkFromUser(Humanoid human) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { bool flag = !IsEnabled(); SetNetworkState(flag); Player val = (Player)(object)((human is Player) ? human : null); if ((Object)(object)val != (Object)null) { ((Character)val).Message((MessageType)2, flag ? "$tag_lightkeeper_msg_turned_on_bal" : "$tag_lightkeeper_msg_turned_off_bal", 0, (Sprite)null); } } } public void ToggleNetworkAutoFuelFromUser(Humanoid human) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { bool flag = !IsAutoFuelEnabled(); SetNetworkAutoFuel(flag); Player val = (Player)(object)((human is Player) ? human : null); if ((Object)(object)val != (Object)null) { ((Character)val).Message((MessageType)2, flag ? "$tag_lightkeeper_msg_autofuel_enabled_bal" : "$tag_lightkeeper_msg_autofuel_disabled_bal", 0, (Sprite)null); } } } public bool IsEnabled() { return (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO().GetBool("LC_enabled", true); } public bool IsAutoFuelEnabled() { return (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO().GetBool("LC_autofuel", true); } public float GetRadius() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return m_radius; } return m_nview.GetZDO().GetFloat("LC_radius", m_radius); } private void ChangeRadius(float delta) { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return; } if (!m_nview.HasOwner()) { m_nview.ClaimOwnership(); } if (!m_nview.IsOwner()) { return; } float radius = GetRadius(); float num = Mathf.Clamp(radius + delta, 5f, 50f); if (!Mathf.Approximately(radius, num)) { m_nview.GetZDO().Set("LC_radius", num); m_radius = num; if ((Object)(object)m_areaMarker != (Object)null) { m_areaMarker.m_radius = num; } LightControllerNetwork.InvalidateAllConnectionCaches(); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$tag_lightkeeper_msg_range_bal " + Mathf.RoundToInt(num) + "m", 0, (Sprite)null); } } } private void SetNetworkState(bool enabled) { List<FireController> connectedAreas = GetConnectedAreas(forceUpdate: true); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if (LightControllerRegistry.IsValidController(fireController)) { if (!fireController.m_nview.HasOwner()) { fireController.m_nview.ClaimOwnership(); } fireController.m_nview.InvokeRPC("LC_SetNetworkState", new object[1] { enabled }); } } } private void SetNetworkAutoFuel(bool enabled) { List<FireController> connectedAreas = GetConnectedAreas(forceUpdate: true); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if (LightControllerRegistry.IsValidController(fireController)) { if (!fireController.m_nview.HasOwner()) { fireController.m_nview.ClaimOwnership(); } fireController.m_nview.InvokeRPC("LC_SetNetworkAutoFuel", new object[1] { enabled }); } } } private void RPC_SetNetworkState(long sender, bool enabled) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner()) { return; } bool flag = IsEnabled(); m_nview.GetZDO().Set("LC_enabled", enabled); UpdateStatus(); if (flag != enabled) { if (enabled) { m_activateEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1); } else { m_deactivateEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1); } } } private void RPC_SetNetworkAutoFuel(long sender, bool enabled) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("LC_autofuel", enabled); UpdateStatus(); } } private void UpdateStatus() { bool flag = IsEnabled(); if ((Object)(object)m_switchOn != (Object)null) { m_switchOn.SetActive(flag); } if ((Object)(object)m_switchOff != (Object)null) { m_switchOff.SetActive(!flag); } if ((Object)(object)m_areaMarker != (Object)null) { m_areaMarker.m_radius = GetRadius(); } } private void OnDamaged() { } public bool GetNetworkEnabled() { List<FireController> connectedAreas = GetConnectedAreas(); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if ((Object)(object)fireController != (Object)null && !fireController.IsEnabled()) { return false; } } return true; } public bool GetNetworkAutoFuelEnabled() { List<FireController> connectedAreas = GetConnectedAreas(); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if ((Object)(object)fireController != (Object)null && !fireController.IsAutoFuelEnabled()) { return false; } } return true; } public bool IsInside(Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Utils.DistanceXZ(((Component)this).transform.position, point) < GetRadius() + radius; } public List<FireController> GetConnectedAreas(bool forceUpdate = false) { if (forceUpdate || Time.time - m_connectionUpdateTime > m_updateConnectionsInterval) { GetAllConnectedAreas(m_connectedAreas); m_connectionUpdateTime = Time.time; } return m_connectedAreas; } private void GetAllConnectedAreas(List<FireController> areas) { areas.Clear(); Queue<FireController> queue = new Queue<FireController>(); List<FireController> controllers = LightControllerRegistry.Controllers; for (int i = 0; i < controllers.Count; i++) { if ((Object)(object)controllers[i] != (Object)null) { controllers[i].m_tempChecked = false; } } m_tempChecked = true; queue.Enqueue(this); areas.Add(this); while (queue.Count > 0) { FireController a = queue.Dequeue(); for (int j = 0; j < controllers.Count; j++) { FireController fireController = controllers[j]; if (LightControllerRegistry.IsValidController(fireController) && !fireController.m_tempChecked && AreControllersConnected(a, fireController)) { fireController.m_tempChecked = true; areas.Add(fireController); queue.Enqueue(fireController); } } } } private static bool AreControllersConnected(FireController a, FireController b) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null) { return false; } float num = Utils.DistanceXZ(((Component)a).transform.position, ((Component)b).transform.position); return num <= a.GetRadius() || num <= b.GetRadius(); } public void InvalidateConnectionCache() { m_connectedAreas.Clear(); m_connectionUpdateTime = -1000f; } public void ShowAreaMarker() { if (!((Object)(object)m_areaMarker == (Object)null)) { m_areaMarker.m_radius = GetRadius(); ((Component)m_areaMarker).gameObject.SetActive(true); ((MonoBehaviour)this).CancelInvoke("HideMarker"); ((MonoBehaviour)this).Invoke("HideMarker", 0.5f); } } private void HideMarker() { if ((Object)(object)m_areaMarker != (Object)null) { ((Component)m_areaMarker).gameObject.SetActive(false); } } public void PokeConnectionEffects() { List<FireController> connectedAreas = GetConnectedAreas(); StartConnectionEffects(); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if ((Object)(object)fireController != (Object)null && (Object)(object)fireController != (Object)(object)this) { fireController.StartConnectionEffects(); } } } private void StartConnectionEffects() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_connectEffect == (Object)null) { return; } List<FireController> controllers = LightControllerRegistry.Controllers; List<FireController> list = new List<FireController>(); for (int i = 0; i < controllers.Count; i++) { FireController fireController = controllers[i]; if (LightControllerRegistry.IsValidController(fireController) && !((Object)(object)fireController == (Object)(object)this) && AreControllersConnected(this, fireController)) { list.Add(fireController); } } Vector3 val = ((Component)this).transform.position + Vector3.up * 0.85f; if (m_connectionInstances.Count != list.Count) { StopConnectionEffects(); for (int j = 0; j < list.Count; j++) { GameObject item = Object.Instantiate<GameObject>(m_connectEffect, val, Quaternion.identity, ((Component)this).transform); m_connectionInstances.Add(item); } } for (int k = 0; k < list.Count; k++) { Vector3 val2 = ((Component)list[k]).transform.position + Vector3.up * 0.85f; Vector3 val3 = val2 - val; if (!(((Vector3)(ref val3)).sqrMagnitude <= 0.001f)) { GameObject val4 = m_connectionInstances[k]; if (!((Object)(object)val4 == (Object)null)) { val4.transform.position = val; val4.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val3)).normalized); val4.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val3)).magnitude); } } } ((MonoBehaviour)this).CancelInvoke("StopConnectionEffects"); ((MonoBehaviour)this).Invoke("StopConnectionEffects", 0.3f); } private void StopConnectionEffects() { for (int i = 0; i < m_connectionInstances.Count; i++) { if ((Object)(object)m_connectionInstances[i] != (Object)null) { Object.Destroy((Object)(object)m_connectionInstances[i]); } } m_connectionInstances.Clear(); } private static bool IsCtrlHeld() { return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); } private static bool IsAltHeld() { return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } } public class LightControllerFuelService { private const float AutoFuelInterval = 2f; private const float CleanupInterval = 10f; private const int MaxFireChecksPerTick = 40; private const int MaxFireplacesFueledPerTick = 10; private const int MaxFuelItemsUsedPerFireplace = 20; private readonly FireController m_owner; private readonly List<FireController> m_networkBuffer = new List<FireController>(); private float m_nextFuelTime; private float m_nextCleanupTime; private int m_nextFireIndex; public LightControllerFuelService(FireController owner) { m_owner = owner; } public void Update() { if ((Object)(object)m_owner == (Object)null || !LightControllerRegistry.IsValidController(m_owner) || Time.time < m_nextFuelTime) { return; } m_nextFuelTime = Time.time + 2f; if (Time.time >= m_nextCleanupTime) { m_nextCleanupTime = Time.time + 10f; LightControllerRegistry.CleanupInvalidReferences(); } if (!m_owner.IsEnabled() || !m_owner.GetNetworkAutoFuelEnabled()) { return; } List<FireController> connectedAreas = m_owner.GetConnectedAreas(); FireController networkLeader = LightControllerNetwork.GetNetworkLeader(connectedAreas); if ((Object)(object)networkLeader != (Object)(object)m_owner || !m_owner.GetNetworkEnabled()) { return; } m_networkBuffer.Clear(); for (int i = 0; i < connectedAreas.Count; i++) { FireController fireController = connectedAreas[i]; if (LightControllerRegistry.IsValidController(fireController)) { m_networkBuffer.Add(fireController); } } if (m_networkBuffer.Count != 0) { AutoFuelNetwork(m_networkBuffer); } } private void AutoFuelNetwork(List<FireController> network) { List<LightEnabler> fires = LightControllerRegistry.Fires; if (fires.Count == 0) { return; } if (m_nextFireIndex < 0 || m_nextFireIndex >= fires.Count) { m_nextFireIndex = 0; } int num = 0; int num2 = 0; int count = fires.Count; while (num < 40 && num2 < 10 && num < count && fires.Count > 0) { if (m_nextFireIndex >= fires.Count) { m_nextFireIndex = 0; } LightEnabler lightEnabler = fires[m_nextFireIndex]; m_nextFireIndex++; num++; if (LightControllerRegistry.IsValidFire(lightEnabler) && !lightEnabler.IsIgnored() && LightControllerNetwork.IsFireInsideControllerNetwork(lightEnabler, network) && TryFuelFireFromNetwork(lightEnabler, network)) { num2++; } } } private bool TryFuelFireFromNetwork(LightEnabler fire, List<FireController> network) { Fireplace fireplace = fire.m_fireplace; if ((Object)(object)fireplace == (Object)null) { return false; } if (fireplace.m_infiniteFuel) { return false; } if ((Object)(object)fireplace.m_fuelItem == (Object)null || fireplace.m_fuelItem.m_itemData == null) { return false; } if ((Object)(object)fire.m_nview == (Object)null || !fire.m_nview.IsValid() || fire.m_nview.GetZDO() == null) { return false; } string name = fireplace.m_fuelItem.m_itemData.m_shared.m_name; if (string.IsNullOrEmpty(name)) { return false; } float @float = fire.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); float maxFuel = fireplace.m_maxFuel; int num = Mathf.CeilToInt(maxFuel - @float); if (num <= 0) { return false; } int num2 = Mathf.Min(num, 20); int num3 = CountAvailableFuel(network, name); if (num3 <= 0) { return false; } int num4 = Mathf.Min(num2, num3); if (num4 <= 0) { return false; } int num5 = RemoveFuelFromNetwork(network, name, num4); if (num5 <= 0) { return false; } float fuel = Mathf.Clamp(@float + (float)num5, 0f, maxFuel); fireplace.SetFuel(fuel); return true; } private int CountAvailableFuel(List<FireController> network, string fuelName) { int num = 0; for (int i = 0; i < network.Count; i++) { FireController fireController = network[i]; if (!CanUseControllerContainer(fireController)) { continue; } Inventory inventory = fireController.m_container.GetInventory(); if (inventory != null) { num += inventory.CountItems(fuelName, -1, true); if (num >= 20) { return num; } } } return num; } private int RemoveFuelFromNetwork(List<FireController> network, string fuelName, int amount) { int num = amount; int num2 = 0; for (int i = 0; i < network.Count; i++) { if (num <= 0) { break; } FireController fireController = network[i]; if (!CanUseControllerContainer(fireController)) { continue; } Inventory inventory = fireController.m_container.GetInventory(); if (inventory != null) { int num3 = inventory.CountItems(fuelName, -1, true); if (num3 > 0) { int num4 = Mathf.Min(num3, num); inventory.RemoveItem(fuelName, num4, -1, true); num -= num4; num2 += num4; } } } return num2; } private bool CanUseControllerContainer(FireController controller) { if (!LightControllerRegistry.IsValidController(controller)) { return false; } if ((Object)(object)controller.m_container == (Object)null) { return false; } if (controller.m_container.IsInUse()) { return false; } if ((Object)(object)controller.m_nview == (Object)null || !controller.m_nview.IsValid()) { return false; } if (!controller.m_nview.IsOwner()) { return false; } return true; } } public static class LightControllerNetwork { public static bool GetFireState(Vector3 firePosition) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) List<FireController> controllers = LightControllerRegistry.Controllers; for (int i = 0; i < controllers.Count; i++) { FireController fireController = controllers[i]; if (LightControllerRegistry.IsValidController(fireController) && fireController.IsInside(firePosition, 0f) && !fireController.GetNetworkEnabled()) { return false; } } return true; } public static bool IsFireInsideControllerNetwork(LightEnabler fire, List<FireController> network) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) if (!LightControllerRegistry.IsValidFire(fire)) { return false; } if (fire.IsIgnored()) { return false; } Vector3 position = ((Component)fire).transform.position; for (int i = 0; i < network.Count; i++) { FireController fireController = network[i]; if (LightControllerRegistry.IsValidController(fireController) && fireController.IsInside(position, 0f)) { return true; } } return false; } public static FireController GetNetworkLeader(List<FireController> network) { FireController fireController = null; int num = int.MaxValue; for (int i = 0; i < network.Count; i++) { FireController fireController2 = network[i]; if (LightControllerRegistry.IsValidController(fireController2)) { int stableControllerKey = GetStableControllerKey(fireController2); if ((Object)(object)fireController == (Object)null || stableControllerKey < num) { fireController = fireController2; num = stableControllerKey; } } } return fireController; } private static int GetStableControllerKey(FireController controller) { if ((Object)(object)controller == (Object)null || (Object)(object)controller.m_nview == (Object)null || !controller.m_nview.IsValid()) { return int.MaxValue; } ZDO zDO = controller.m_nview.GetZDO(); if (zDO == null) { return int.MaxValue; } return ((object)(ZDOID)(ref zDO.m_uid)).GetHashCode(); } public static void InvalidateAllConnectionCaches() { List<FireController> controllers = LightControllerRegistry.Controllers; for (int i = 0; i < controllers.Count; i++) { FireController fireController = controllers[i]; if ((Object)(object)fireController != (Object)null) { fireController.InvalidateConnectionCache(); } } } } public static class LightControllerRegistry { private static readonly List<FireController> m_controllers = new List<FireController>(); private static readonly List<LightEnabler> m_fires = new List<LightEnabler>(); public static List<FireController> Controllers => m_controllers; public static List<LightEnabler> Fires => m_fires; public static void RegisterController(FireController controller) { if ((Object)(object)controller != (Object)null && !m_controllers.Contains(controller)) { m_controllers.Add(controller); } } public static void UnregisterController(FireController controller) { m_controllers.Remove(controller); LightControllerNetwork.InvalidateAllConnectionCaches(); } public static void RegisterFire(LightEnabler fire) { if ((Object)(object)fire != (Object)null && !m_fires.Contains(fire)) { m_fires.Add(fire); } } public static void UnregisterFire(LightEnabler fire) { m_fires.Remove(fire); } public static void CleanupInvalidReferences() { int count = m_controllers.Count; m_controllers.RemoveAll(IsInvalidController); m_fires.RemoveAll(IsInvalidFire); if (m_controllers.Count != count) { LightControllerNetwork.InvalidateAllConnectionCaches(); } } public static bool IsValidController(FireController controller) { return !IsInvalidController(controller); } public static bool IsValidFire(LightEnabler fire) { return !IsInvalidFire(fire); } private static bool IsInvalidController(FireController controller) { return (Object)(object)controller == (Object)null || (Object)(object)((Component)controller).gameObject == (Object)null || (Object)(object)controller.m_nview == (Object)null || !controller.m_nview.IsValid(); } private static bool IsInvalidFire(LightEnabler fire) { return (Object)(object)fire == (Object)null || (Object)(object)((Component)fire).gameObject == (Object)null || (Object)(object)fire.m_fireplace == (Object)null || (Object)(object)fire.m_nview == (Object)null || !fire.m_nview.IsValid(); } } public class LightEnabler : MonoBehaviour { private const string ZdoIgnoreController = "LC_ignore_controller"; private const string RpcSetIgnoreController = "LC_SetIgnoreController"; public ZNetView m_nview; public Piece m_piece; public Fireplace m_fireplace; private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); m_piece = ((Component)this).GetComponent<Piece>(); m_fireplace = ((Component)this).GetComponent<Fireplace>(); if ((Object)(object)m_fireplace == (Object)null) { ((Behaviour)this).enabled = false; return; } if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.Register<bool>("LC_SetIgnoreController", (Action<long, bool>)RPC_SetIgnoreController); } LightControllerRegistry.RegisterFire(this); } private void OnDestroy() { LightControllerRegistry.UnregisterFire(this); } public bool IsIgnored() { return (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO().GetBool("LC_ignore_controller", false); } public void SetIgnored(bool ignored) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { if (!m_nview.HasOwner()) { m_nview.ClaimOwnership(); } m_nview.InvokeRPC("LC_SetIgnoreController", new object[1] { ignored }); } } public bool ToggleIgnored() { bool flag = !IsIgnored(); SetIgnored(flag); return flag; } private void RPC_SetIgnoreController(long sender, bool ignored) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("LC_ignore_controller", ignored); } } public bool AllowBurning() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (IsIgnored()) { return true; } return LightControllerNetwork.GetFireState(((Component)this).transform.position); } } [HarmonyPatch] internal static class TranslationPatches { [HarmonyPatch(typeof(FejdStartup), "SetupGui")] private class FejdStartup_SetupGUI { private static void Postfix() { string selectedLanguage = Localization.instance.GetSelectedLanguage(); Dictionary<string, string> translations = GetTranslations(selectedLanguage); AddTranslations(translations); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "SetupLanguage")] private class Translation_SetupLanguage { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "LoadCSV")] private class Translation_LoadCSV { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } private static Dictionary<string, string> GetTranslations(string language) { Dictionary<string, string> result = BalrondTranslator.getLanguage("English"); if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language); if (language2 != null) { result = language2; } else { Debug.Log((object)("ZZZBalrondLightkeeper: Did not find translation file for '" + language + "', loading English")); } } return result; } private static void AddTranslations(Dictionary<string, string> translations, Localization localizationInstance = null) { if (translations == null) { Debug.LogWarning((object)"ZZZBalrondLightkeeper: No translation file found!"); return; } if (localizationInstance != null) { foreach (KeyValuePair<string, string> translation in translations) { localizationInstance.AddWord(translation.Key, translation.Value); } return; } foreach (KeyValuePair<string, string> translation2 in translations) { Localization.instance.AddWord(translation2.Key, translation2.Value); } } } } namespace LitJson2 { internal enum JsonType { None, Object, Array, String, Int, Long, Double, Boolean } internal interface IJsonWrapper : IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable { bool IsArray { get; } bool IsBoolean { get; } bool IsDouble { get; } bool IsInt { get; } bool IsLong { get; } bool IsObject { get; } bool IsString { get; } bool GetBoolean(); double GetDouble(); int GetInt(); JsonType GetJsonType(); long GetLong(); string GetString(); void SetBoolean(bool val); void SetDouble(double val); void SetInt(int val); void SetJsonType(JsonType type); void SetLong(long val); void SetString(string val); string ToJson(); void ToJson(JsonWriter writer); } internal class JsonData : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable, IEquatable<JsonData> { private IList<JsonData> inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary<string, JsonData> inst_object; private string inst_string; private string json; private JsonType type; private IList<KeyValuePair<string, JsonData>> object_list; public int Count => EnsureCollection().Count; public bool IsArray => type == JsonType.Array; public bool IsBoolean => type == JsonType.Boolean; public bool IsDouble => type == JsonType.Double; public bool IsInt => type == JsonType.Int; public bool IsLong => type == JsonType.Long; public bool IsObject => type == JsonType.Object; public bool IsString => type == JsonType.String; public ICollection<string> Keys { get { EnsureDictionary(); return inst_object.Keys; } } int ICollection.Count => Count; bool ICollection.IsSynchronized => EnsureCollection().IsSynchronized; object ICollection.SyncRoot => EnsureCollection().SyncRoot; bool IDictionary.IsFixedSize => EnsureDictionary().IsFixedSize; bool IDictionary.IsReadOnly => EnsureDictionary().IsReadOnly; ICollection IDictionary.Keys { get { EnsureDictionary(); IList<string> list = new List<string>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Key); } return (ICollection)list; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList<JsonData> list = new List<JsonData>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Value); } return (ICollection)list; } } bool IJsonWrapper.IsArray => IsArray; bool IJsonWrapper.IsBoolean => IsBoolean; bool IJsonWrapper.IsDouble => IsDouble; bool IJsonWrapper.IsInt => IsInt; bool IJsonWrapper.IsLong => IsLong; bool IJsonWrapper.IsObject => IsObject; bool IJsonWrapper.IsString => IsString; bool IList.IsFixedSize => EnsureList().IsFixedSize; bool IList.IsReadOnly => EnsureList().IsReadOnly; object IDictionary.this[object key] { get { return EnsureDictionary()[key]; } set { if (!(key is string)) { throw new ArgumentException("The key has to be a string"); } JsonData value2 = ToJsonData(value); this[(string)key] = value2; } } object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); JsonData value2 = ToJsonData(value); KeyValuePair<string, JsonData> keyValuePair = object_list[idx]; inst_object[keyValuePair.Key] = value2; KeyValuePair<string, JsonData> value3 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value2); object_list[idx] = value3; } } object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); JsonData value2 = ToJsonData(value); this[index] = value2; } } public JsonData this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair<string, JsonData> keyValuePair = new KeyValuePair<string, JsonData>(prop_name, value); if (inst_object.ContainsKey(prop_name)) { for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == prop_name) { object_list[i] = keyValuePair; break; } } } else { object_list.Add(keyValuePair); } inst_object[prop_name] = value; json = null; } } public JsonData this[int index] { get { EnsureCollection(); if (type == JsonType.Array) { return inst_array[index]; } return object_list[index].Value; } set { EnsureCollection(); if (type == JsonType.Array) { inst_array[index] = value; } else { KeyValuePair<string, JsonData> keyValuePair = object_list[index]; KeyValuePair<string, JsonData> value2 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value); object_list[index] = value2; inst_object[keyValuePair.Key] = value; } json = null; } } public JsonData() { } public JsonData(bool boolean) { type = JsonType.Boolean; inst_boolean = boolean; } public JsonData(double number) { type = JsonType.Double; inst_double = number; } public JsonData(int number) { type = JsonType.Int; inst_int = number; } public JsonData(long number) { type = JsonType.Long; inst_long = number; } public JsonData(object obj) { if (obj is bool) { type = JsonType.Boolean; inst_boolean = (bool)obj; return; } if (obj is double) { type = JsonType.Double; inst_double = (double)obj; return; } if (obj is int) { type = JsonType.Int; inst_int = (int)obj; return; } if (obj is long) { type = JsonType.Long; inst_long = (long)obj; return; } if (obj is string) { type = JsonType.String; inst_string = (string)obj; return; } throw new ArgumentException("Unable to wrap the given object with JsonData"); } public JsonData(string str) { type = JsonType.String; inst_string = str; } public static implicit operator JsonData(bool data) { return new JsonData(data); } public static implicit operator JsonData(double data) { return new JsonData(data); } public static implicit operator JsonData(int data) { return new JsonData(data); } public static implicit operator JsonData(long data) { return new JsonData(data); } public static implicit operator JsonData(string data) { return new JsonData(data); } public static explicit operator bool(JsonData data) { if (data.type != JsonType.Boolean) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_boolean; } public static explicit operator double(JsonData data) { if (data.type != JsonType.Double) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_double; } public static explicit operator int(JsonData data) { if (data.type != JsonType.Int) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_int; } public static explicit operator long(JsonData data) { if (data.type != JsonType.Long) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_long; } public static explicit operator string(JsonData data) { if (data.type != JsonType.String) { throw new InvalidCastException("Instance of JsonData doesn't hold a string"); } return data.inst_string; } void ICollection.CopyTo(Array array, int index) { EnsureCollection().CopyTo(array, index); } void IDictionary.Add(object key, object value) { JsonData value2 = ToJsonData(value); EnsureDictionary().Add(key, value2); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>((string)key, value2); object_list.Add(item); json = null; } void IDictionary.Clear() { EnsureDictionary().Clear(); object_list.Clear(); json = null; } bool IDictionary.Contains(object key) { return EnsureDictionary().Contains(key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return ((IOrderedDictionary)this).GetEnumerator(); } void IDictionary.Remove(object key) { EnsureDictionary().Remove(key); for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == (string)key) { object_list.RemoveAt(i); break; } } json = null; } IEnumerator IEnumerable.GetEnumerator() { return EnsureCollection().GetEnumerator(); } bool IJsonWrapper.GetBoolean() { if (type != JsonType.Boolean) { throw new InvalidOperationException("JsonData instance doesn't hold a boolean"); } return inst_boolean; } double IJsonWrapper.GetDouble() { if (type != JsonType.Double) { throw new InvalidOperationException("JsonData instance doesn't hold a double"); } return inst_double; } int IJsonWrapper.GetInt() { if (type != JsonType.Int) { throw new InvalidOperationException("JsonData instance doesn't hold an int"); } return inst_int; } long IJsonWrapper.GetLong() { if (type != JsonType.Long) { throw new InvalidOperationException("JsonData instance doesn't hold a long"); } return inst_long; } string IJsonWrapper.GetString() { if (type != JsonType.String) { throw new InvalidOperationException("JsonData instance doesn't hold a string"); } return inst_string; } void IJsonWrapper.SetBoolean(bool val) { type = JsonType.Boolean; inst_boolean = val; json = null; } void IJsonWrapper.SetDouble(double val) { type = JsonType.Double; inst_double = val; json = null; } void IJsonWrapper.SetInt(int val) { type = JsonType.Int; inst_int = val; json = null; } void IJsonWrapper.SetLong(long val) { type = JsonType.Long; inst_long = val; json = null; } void IJsonWrapper.SetString(string val) { type = JsonType.String; inst_string = val; json = null; } string IJsonWrapper.ToJson() { return ToJson(); } void IJsonWrapper.ToJson(JsonWriter writer) { ToJson(writer); } int IList.Add(object value) { return Add(value); } void IList.Clear() { EnsureList().Clear(); json = null; } bool IList.Contains(object value) { return EnsureList().Contains(value); } int IList.IndexOf(object value) { return EnsureList().IndexOf(value); } void IList.Insert(int index, object value) { EnsureList().Insert(index, value); json = null; } void IList.Remove(object value) { EnsureList().Remove(value); json = null; } void IList.RemoveAt(int index) { EnsureList().RemoveAt(index); json = null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { EnsureDictionary(); return new OrderedDictionaryEnumerator(object_list.GetEnumerator()); } void IOrderedDictionary.Insert(int idx, object key, object value) { string text = (string)key; JsonData value2 = (this[text] = ToJsonData(value)); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>(text, value2); object_list.Insert(idx, item); } void IOrderedDictionary.RemoveAt(int idx) { EnsureDictionary(); inst_object.Remove(object_list[idx].Key); object_list.RemoveAt(idx); } private ICollection EnsureCollection() { if (type == JsonType.Array) { return (ICollection)inst_array; } if (type == JsonType.Object) { return (ICollection)inst_object; } throw new InvalidOperationException("The JsonData instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == JsonType.Object) { return (IDictionary)inst_object; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a dictionary"); } type = JsonType.Object; inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == JsonType.Array) { return (IList)inst_array; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a list"); } type = JsonType.Array; inst_array = new List<JsonData>(); return (IList)inst_array; } private JsonData ToJsonData(object obj) { if (obj == null) { return null; } if (obj is JsonData) { return (JsonData)obj; } return new JsonData(obj); } private static void WriteJson(IJsonWrapper obj, JsonWriter writer) { if (obj == null) { writer.Write(null); } else if (obj.IsString) { writer.Write(obj.GetString()); } else if (obj.IsBoolean) { writer.Write(obj.GetBoolean()); } else if (obj.IsDouble) { writer.Write(obj.GetDouble()); } else if (obj.IsInt) { writer.Write(obj.GetInt()); } else if (obj.IsLong) { writer.Write(obj.GetLong()); } else if (obj.IsArray) { writer.WriteArrayStart(); foreach (object item in (IEnumerable)obj) { WriteJson((JsonData)item, writer); } writer.WriteArrayEnd(); } else { if (!obj.IsObject) { return; } writer.WriteObjectStart(); foreach (DictionaryEntry item2 in (IDictionary)obj) { writer.WritePropertyName((string)item2.Key); WriteJson((JsonData)item2.Value, writer); } writer.WriteObjectEnd(); } } public int Add(object value) { JsonData value2 = ToJsonData(value); json = null; return EnsureList().Add(value2); } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); } else if (IsArray) { ((IList)this).Clear(); } } public bool Equals(JsonData x) { if (x == null) { return false; } if (x.type != type) { return false; } return type switch { JsonType.None => true, JsonType.Object => inst_object.Equals(x.inst_object), JsonType.Array => inst_array.Equals(x.inst_array), JsonType.String => inst_string.Equals(x.inst_string), JsonType.Int => inst_int.Equals(x.inst_int), JsonType.Long => inst_long.Equals(x.inst_long), JsonType.Double => inst_double.Equals(x.inst_double), JsonType.Boolean => inst_boolean.Equals(x.inst_boolean), _ => false, }; } public JsonType GetJsonType() { return type; } public void SetJsonType(JsonType type) { if (this.type != type) { switch (type) { case JsonType.Object: inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); break; case JsonType.Array: inst_array = new List<JsonData>(); break; case JsonType.String: inst_string = null; break; case JsonType.Int: inst_int = 0; break; case JsonType.Long: inst_long = 0L; break; case JsonType.Double: inst_double = 0.0; break; case JsonType.Boolean: inst_boolean = false; break; } this.type = type; } } public string ToJson() { if (json != null) { return json; } StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.Validate = false; WriteJson(this, jsonWriter); json = stringWriter.ToString(); return json; } public void ToJson(JsonWriter writer) { bool validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = validate; } public override string ToString() { return type switch { JsonType.Array => "JsonData array", JsonType.Boolean => inst_boolean.ToString(), JsonType.Double => inst_double.ToString(), JsonType.Int => inst_int.ToString(), JsonType.Long => inst_long.ToString(), JsonType.Object => "JsonData object", JsonType.String => inst_string, _ => "Uninitialized JsonData", }; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private IEnumerator<KeyValuePair<string, JsonData>> list_enumerator; public object Current => Entry; public DictionaryEntry Entry { get { KeyValuePair<string, JsonData> current = list_enumerator.Current; return new DictionaryEntry(current.Key, current.Value); } } public object Key => list_enumerator.Current.Key; public object Value => list_enumerator.Current.Value; public OrderedDictionaryEnumerator(IEnumerator<KeyValuePair<string, JsonData>> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } internal class JsonException : ApplicationException { public JsonException() { } internal JsonException(ParserToken token) : base($"Invalid token '{token}' in input string") { } internal JsonException(ParserToken token, Exception inner_exception) : base($"Invalid token '{token}' in input string", inner_exception) { } internal JsonException(int c) : base($"Invalid character '{(char)c}' in input string") { } internal JsonException(int c, Exception inner_exception) : base($"Invalid character '{(char)c}' in input string", inner_exception) { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception inner_exception) : base(message, inner_exception) { } } internal struct PropertyMetadata { public MemberInfo Info; public bool IsField; public Type Type; } internal struct ArrayMetadata { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsArray { get { return is_array; } set { is_array = value; } } public bool IsList { get { return is_list; } set { is_list = value; } } } internal struct ObjectMetadata { private Type element_type; private bool is_dictionary; private IDictionary<string, PropertyMetadata> properties; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary<string, PropertyMetadata> Properties { get { return properties; } set { properties = value; } } } internal delegate void ExporterFunc(object obj, JsonWriter writer); internal delegate void ExporterFunc<T>(T obj, JsonWriter writer); internal delegate object ImporterFunc(object input); internal delegate TValue ImporterFunc<TJson, TValue>(TJson input); internal delegate IJsonWrapper WrapperFactory(); internal class JsonMapper { private static int max_nesting_depth; private static IFormatProvider datetime_format; private static IDictionary<Type, ExporterFunc> base_exporters_table; private static IDictionary<Type, ExporterFunc> custom_exporters_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table; private static IDictionary<Type, ArrayMetadata> array_metadata; private static readonly object array_metadata_lock; private static IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops; private static readonly object conv_ops_lock; private static IDictionary<Type, ObjectMetadata> object_metadata; private static readonly object object_metadata_lock; private static IDictionary<Type, IList<PropertyMetadata>> type_properties; private static readonly object type_properties_lock; private static JsonWriter static_writer; private static readonly object static_writer_lock; static JsonMapper() { array_metadata_lock = new object(); conv_ops_lock = new object(); object_metadata_lock = new object(); type_properties_lock = new object(); static_writer_lock = new object(); max_nesting_depth = 100; array_metadata = new Dictionary<Type, ArrayMetadata>(); conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); object_metadata = new Dictionary<Type, ObjectMetadata>(); type_properties = new Dictionary<Type, IList<PropertyMetadata>>(); static_writer = new JsonWriter(); datetime_format = DateTimeFormatInfo.InvariantInfo; base_exporters_table = new Dictionary<Type, ExporterFunc>(); custom_exporters_table = new Dictionary<Type, ExporterFunc>(); base_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); custom_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); RegisterBaseExporters(); RegisterBaseImporters(); } private static void AddArrayMetadata(Type type) { if (array_metadata.ContainsKey(type)) { return; } ArrayMetadata value = default(ArrayMetadata); value.IsArray = type.IsArray; if (type.GetInterface("System.Collections.IList") != null) { value.IsList = true; } PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name != "Item")) { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(int)) { value.ElementType = propertyInfo.PropertyType; } } } lock (array_metadata_lock) { try { array_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddObjectMetadata(Type type) { if (object_metadata.ContainsKey(type)) { return; } ObjectMetadata value = default(ObjectMetadata); if (type.GetInterface("System.Collections.IDictionary") != null) { value.IsDictionary = true; } value.Properties = new Dictionary<string, PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.Name == "Item") { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(string)) { value.ElementType = propertyInfo.PropertyType; } } else { PropertyMetadata value2 = default(PropertyMetadata); value2.Info = propertyInfo; value2.Type = propertyInfo.PropertyType; value.Properties.Add(propertyInfo.Name, value2); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo fieldInfo in fields) { PropertyMetadata value3 = default(PropertyMetadata); value3.Info = fieldInfo; value3.IsField = true; value3.Type = fieldInfo.FieldType; value.Properties.Add(fieldInfo.Name, value3); } lock (object_metadata_lock) { try { object_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddTypeProperties(Type type) { if (type_properties.ContainsKey(type)) { return; } IList<PropertyMetadata> list = new List<PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name == "Item")) { PropertyMetadata item = default(PropertyMetadata); item.Info = propertyInfo; item.IsField = false; list.Add(item); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo info in fields) { PropertyMetadata item2 = default(PropertyMetadata); item2.Info = info; item2.IsField = true; list.Add(item2); } lock (type_properties_lock) { try { type_properties.Add(type, list); } catch (ArgumentException) { } } } private static MethodInfo GetConvOp(Type t1, Type t2) { lock (conv_ops_lock) { if (!conv_ops.ContainsKey(t1)) { conv_ops.Add(t1, new Dictionary<Type, MethodInfo>()); } } if (conv_ops[t1].ContainsKey(t2)) { return conv_ops[t1][t2]; } MethodInfo method = t1.GetMethod("op_Implicit", new Type[1] { t2 }); lock (conv_ops_lock) { try { conv_ops[t1].Add(t2, method); return method; } catch (ArgumentException) { return conv_ops[t1][t2]; } } } private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd) { return null; } Type underlyingType = Nullable.GetUnderlyingType(inst_type); Type type = underlyingType ?? inst_type; if (reader.Token == JsonToken.Null) { if (inst_type.IsClass || underlyingType != null) { return null; } throw new JsonException($"Can't assign null to an instance of type {inst_type}"); } if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean) { Type type2 = reader.Value.GetType(); if (type.IsAssignableFrom(type2)) { return reader.Value; } if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type)) { ImporterFunc importerFunc = custom_importers_table[type2][type]; return importerFunc(reader.Value); } if (base_importers_table.ContainsKey(type2) && base_importers_table[type2].ContainsKey(type)) { ImporterFunc importerFunc2 = base_importers_table[type2][type]; return importerFunc2(reader.Value); } if (type.IsEnum) { return Enum.ToObject(type, reader.Value); } MethodInfo convOp = GetConvOp(type, type2); if (convOp != null) { return convOp.Invoke(null, new object[1] { reader.Value }); } throw new JsonException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}"); } object obj = null; if (reader.Token == JsonToken.ArrayStart) { AddArrayMetadata(inst_type); ArrayMetadata arrayMetadata = array_metadata[inst_type]; if (!arrayMetadata.IsArray && !arrayMetadata.IsList) { throw new JsonException($"Type {inst_type} can't act as an array"); } IList list; Type elementType; if (!arrayMetadata.IsArray) { list = (IList)Activator.CreateInstance(inst_type); elementType = arrayMetadata.ElementType; } else { list = new ArrayList(); elementType = inst_type.GetElementType(); } while (true) { object obj2 = ReadValue(elementType, reader); if (obj2 == null && reader.Token == JsonToken.ArrayEnd) { break; } list.Add(obj2); } if (arrayMetadata.IsArray) { int count = list.Count; obj = Array.CreateInstance(elementType, count); for (int i = 0; i < count; i++) { ((Array)obj).SetValue(list[i], i); } } else { obj = list; } } else if (reader.Token == JsonToken.ObjectStart) { AddObjectMetadata(type); ObjectMetadata objectMetadata = object_metadata[type]; obj = Activator.CreateInstance(type); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string text = (string)reader.Value; if (objectMetadata.Properties.ContainsKey(text)) { PropertyMetadata propertyMetadata = objectMetadata.Properties[text]; if (propertyMetadata.IsField) { ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader)); continue; } PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info; if (propertyInfo.CanWrite) { propertyInfo.SetValue(obj, ReadValue(propertyMetadata.Type, reader), null); } else { ReadValue(propertyMetadata.Type, reader); } } else if (!objectMetadata.IsDictionary) { if (!reader.SkipNonMembers) { throw new JsonException($"The type {inst_type} doesn't have the property '{text}'"); } ReadSkip(reader); } else { ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader)); } } } return obj; } private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null) { return null; } IJsonWrapper jsonWrapper = factory(); if (reader.Token == JsonToken.String) { jsonWrapper.SetString((string)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Double) { jsonWrapper.SetDouble((double)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Int) { jsonWrapper.SetInt((int)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Long) { jsonWrapper.SetLong((long)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Boolean) { jsonWrapper.SetBoolean((bool)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.ArrayStart) { jsonWrapper.SetJsonType(JsonType.Array); while (true) { IJsonWrapper jsonWrapper2 = ReadValue(factory, reader); if (jsonWrapper2 == null && reader.Token == JsonToken.ArrayEnd) { break; } jsonWrapper.Add(jsonWrapper2); } } else if (reader.Token == JsonToken.ObjectStart) { jsonWrapper.SetJsonType(JsonType.Object); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string key = (string)reader.Value; jsonWrapper[key] = ReadValue(factory, reader); } } return jsonWrapper; } private static void ReadSkip(JsonReader reader) { ToWrapper(() => new JsonMockWrapper(), reader); } private static void RegisterBaseExporters() { base_exporters_table[typeof(byte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((byte)obj)); }; base_exporters_table[typeof(char)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((char)obj)); }; base_exporters_table[typeof(DateTime)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((DateTime)obj, datetime_format)); }; base_exporters_table[typeof(decimal)] = delegate(object obj, JsonWriter writer) { writer.Write((decimal)obj); }; base_exporters_table[typeof(sbyte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((sbyte)obj)); }; base_exporters_table[typeof(short)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((short)obj)); }; base_exporters_table[typeof(ushort)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((ushort)obj)); }; base_exporters_table[typeof(uint)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToUInt64((uint)obj)); }; base_exporters_table[typeof(ulong)] = delegate(object obj, JsonWriter writer) { writer.Write((ulong)obj); }; } private static void RegisterBaseImporters() { ImporterFunc importer = (object input) => Convert.ToByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(byte), importer); importer = (object input) => Convert.ToUInt64((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ulong), importer); importer = (object input) => Convert.ToSByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(sbyte), importer); importer = (object input) => Convert.ToInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(short), importer); importer = (object input) => Convert.ToUInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ushort), importer); importer = (object input) => Convert.ToUInt32((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(uint), importer); importer = (object input) => Convert.ToSingle((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(float), importer); importer = (object input) => Convert.ToDouble((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(double), importer); importer = (object input) => Convert.ToDecimal((double)input); RegisterImporter(base_importers_table, typeof(double), typeof(decimal), importer); importer = (object input) => Convert.ToUInt32((long)input); RegisterImporter(base_importers_table, typeof(long), typeof(uint), importer); importer = (object input) => Convert.ToChar((string)input); RegisterImporter(base_importers_table, typeof(string), typeof(char), importer); importer = (object input) => Convert.ToDateTime((string)input, datetime_format); RegisterImporter(base_importers_table, typeof(string), typeof(DateTime), importer); } private static void RegisterImporter(IDictionary<Type, IDictionary<Type, ImporterFunc>> table, Type json_type, Type value_type, ImporterFunc importer) { if (!table.ContainsKey(json_type)) { table.Add(json_type, new Dictionary<Type, ImporterFunc>()); } table[json_type][value_type] = importer; } private static void WriteValue(object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) { throw new JsonException($"Max allowed object depth reached while trying to export from type {obj.GetType()}"); } if (obj == null) { writer.Write(null); return; } if (obj is IJsonWrapper) { if (writer_is_private) { writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); } else { ((IJsonWrapper)obj).ToJson(writer); } return; } if (obj is string) { writer.Write((string)obj); return; } if (obj is double) { writer.Write((double)obj); return; } if (obj is int) { writer.Write((int)obj); return; } if (obj is bool) { writer.Write((bool)obj); return; } if (obj is long) { writer.Write((long)obj); return; } if (obj is Array) { writer.WriteArrayStart(); foreach (object item in (Array)obj) { WriteValue(item, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IList) { writer.WriteArrayStart(); foreach (object item2 in (IList)obj) { WriteValue(item2, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IDictionary) { writer.WriteObjectStart(); foreach (DictionaryEntry item3 in (IDictionary)obj) { writer.WritePropertyName((string)item3.Key); WriteValue(item3.Value, writer, writer_is_private, depth + 1); } writer.WriteObjectEnd(); return; } Type type = obj.GetType(); if (custom_exporters_table.ContainsKey(type)) { ExporterFunc exporterFunc = custom_exporters_table[type]; exporterFunc(obj, writer); return; } if (base_exporters_table.ContainsKey(type)) { ExporterFunc exporterFunc2 = base_exporters_table[type]; exporterFunc2(obj, writer); return; } if (obj is Enum) { Type underlyingType = Enum.GetUnderlyingType(type); if (underlyingType == typeof(long) || underlyingType == typeof(uint) || underlyingType == typeof(ulong)) { writer.Write((ulong)obj); } else { writer.Write((int)obj); } return; } AddTypeProperties(type); IList<PropertyMetadata> list = type_properties[type]; writer.WriteObjectStart(); foreach (PropertyMetadata item4 in list) { if (item4.IsField) { writer.WritePropertyName(item4.Info.Name); WriteValue(((FieldInfo)item4.Info).GetValue(obj), writer, writer_is_private, depth + 1); continue; } PropertyInfo propertyInfo = (PropertyInfo)item4.Info; if (propertyInfo.CanRead) { writer.WritePropertyName(item4.Info.Name); WriteValue(propertyInfo.GetValue(obj, null), writer, writer_is_private, depth + 1); } } writer.WriteObjectEnd(); } public static string ToJson(object obj) { lock (static_writer_lock) { static_writer.Reset(); WriteValue(obj, static_writer, writer_is_private: true, 0); return static_writer.ToString(); } } public static void ToJson(object obj, JsonWriter writer) { WriteValue(obj, writer, writer_is_private: false, 0); } public static JsonData ToObject(JsonReader reader) { return (JsonData)ToWrapper(() => new JsonData(), reader); } public static JsonData ToObject(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (JsonData)ToWrapper(() => new JsonData(), reader2); } public static JsonData ToObject(string json) { return (JsonData)ToWrapper(() => new JsonData(), json); } public static T ToObject<T>(JsonReader reader) { return (T)ReadValue(typeof(T), reader); } public static T ToObject<T>(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (T)ReadValue(typeof(T), reader2); } public static T ToObject<T>(string json) { JsonReader reader = new JsonReader(json); return (T)ReadValue(typeof(T), reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, JsonReader reader) { return ReadValue(factory, reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, string json) { JsonReader reader = new JsonReader(json); return ReadValue(factory, reader); } public static void RegisterExporter<T>(ExporterFunc<T> exporter) { ExporterFunc value = delegate(object obj, JsonWriter writer) { exporter((T)obj, writer); }; custom_exporters_table[typeof(T)] = value; } public static void RegisterImporter<TJson, TValue>(ImporterFunc<TJson, TValue> importer) { ImporterFunc importer2 = (object input) => importer((TJson)input); RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), importer2); } public static void UnregisterExporters() { custom_exporters_table.Clear(); } public static void UnregisterImporters() { custom_importers_table.Clear(); } } internal class JsonMockWrapper : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable { public bool IsArray => false; public bool IsBoolean => false; public bool IsDouble => false; public bool IsInt => false; public bool IsLong => false; public bool IsObject => false; public bool IsString => false; bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; object IList.this[int index] { get { return null; } set { } } int ICollection.Count => 0; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => null; bool IDictionary.IsFixedSize => true; bool IDictionary.IsReadOnly => true; ICollection IDictionary.Keys => null; ICollection IDictionary.Values => null; object IDictionary.this[object key] { get { return null; } set { } } object IOrderedDictionary.this[int idx] { get { return null; } set { } } public bool GetBoolean() { return false; } public double GetDouble() { return 0.0; } public int GetInt() { return 0; } public JsonType GetJsonType() { return JsonType.None; } public long GetLong() { return 0L; } public string GetString() { return ""; } public void SetBoolean(bool val) { } public void SetDouble(double val) { } public void SetInt(int val) { } public void SetJsonType(JsonType type) { } public void SetLong(long val) { } public void SetString(string val) { } public string ToJson() { return ""; } public void ToJson(JsonWriter writer) { } int IList.Add(object value) { return 0; } void IList.Clear() { } bool IList.Contains(object value) { return false; } int IList.IndexOf(object value) { return -1; } void IList.Insert(int i, object v) { } void IList.Remove(object value) { } void IList.RemoveAt(int index) { } void ICollection.CopyTo(Array array, int index) { } IEnumerator IEnumerable.GetEnumerator() { return null; } void IDictionary.Add(object k, object v) { } void IDictionary.Clear() { } bool IDictionary.Contains(object key) { return false; } void IDictionary.Remove(object key) { } IDictionaryEnumerator IDictionary.GetEnumerator() { return null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { return null; } void IOrderedDictionary.Insert(int i, object k, object v) { } void IOrderedDictionary.RemoveAt(int i) { } } internal enum JsonToken { None, ObjectStart, PropertyName, ObjectEnd, ArrayStart, ArrayEnd, Int, Long, Double, String, Boolean, Null } internal class JsonReader { private static IDictionary<int, IDictionary<int, int[]>> parse_table; private Stack<int> automaton_stack; private int current_input; private int current_symbol; private bool end_of_json; private bool end_of_input; private Lexer lexer; private bool parser_in_string; private bool parser_return; private bool read_started; private TextReader reader; private bool reader_is_owned; private bool skip_non_members; private object token_value; private JsonToken token; public bool AllowComments { get { return lexer.AllowComments; } set { lexer.AllowComments = value; } } public bool AllowSingleQuotedStrings { get { return lexer.AllowSingleQuotedStrings; } set { lexer.AllowSingleQuotedStrings = value; } } public bool SkipNonMembers { get { return skip_non_members; } set { skip_non_members = value; } } public bool EndOfInput => end_of_input; public bool EndOfJson => end_of_json; public JsonToken Token => token; public object Value => token_value; static JsonReader() { PopulateParseTable(); } public JsonReader(string json_text) : this(new StringReader(json_text), owned: true) { } public JsonReader(TextReader reader) : this(reader, owned: false) { } private JsonReader(TextReader reader, bool owned) { if (reader == null) { throw new ArgumentNullException("reader"); } parser_in_string = false; parser_return = false; read_started = false; automaton_stack = new Stack<int>(); automaton_stack.Push(65553); automaton_stack.Push(65543); lexer = new Lexer(reader); end_of_input = false; end_of_json = false; skip_non_members = true; this.reader = reader; reader_is_owned = owned; } private static void PopulateParseTable() { parse_table = new Dictionary<int, IDictionary<int, int[]>>(); TableAddRow(ParserToken.Array); TableAddCol(ParserToken.Array, 91, 91, 65549); TableAddRow(ParserToken.ArrayPrime); TableAddCol(ParserToken.ArrayPrime, 34, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 91, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 93, 93); TableAddCol(ParserToken.ArrayPrime, 123, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65537, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65538, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65539, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65540, 65550, 65551, 93); TableAddRow(ParserToken.Object); TableAddCol(ParserToken.Object, 123, 123, 65545); TableAddRow(ParserToken.ObjectPrime); TableAddCol(ParserToken.ObjectPrime, 34, 65546, 65547, 125); TableAddCol(ParserToken.ObjectPrime, 125, 125); TableAddRow(ParserToken.Pair); TableAddCol(ParserToken.Pair, 34, 65552, 58, 65550); TableAddRow(ParserToken.PairRest); TableAddCol(ParserToken.PairRest, 44, 44, 65546, 65547); TableAddCol(ParserToken.PairRest, 125, 65554); TableAddRow(ParserToken.String); TableAddCol(ParserToken.String, 34, 34, 65541, 34); TableAddRow(ParserToken.Text); TableAddCol(ParserToken.Text, 91, 65548); TableAddCol(ParserToken.Text, 123, 65544); TableAddRow(ParserToken.Value); TableAddCol(ParserToken.Value, 34, 65552); TableAddCol(ParserToken.Value, 91, 65548); TableAddCol(ParserToken.Value, 123, 65544); TableAddCol(ParserToken.Value, 65537, 65537); TableAddCol(ParserToken.Value, 65538, 65538); TableAddCol(ParserToken.Value, 65539, 65539); TableAddCol(ParserToken.Value, 65540, 65540); TableAddRow(ParserToken.ValueRest); TableAddCol(ParserToken.ValueRest, 44, 44, 65550, 65551); TableAddCol(ParserToken.ValueRest, 93, 65554); } private static void TableAddCol(ParserToken row, int col, params int[] symbols) { parse_table[(int)row].Add(col, symbols); } private static void TableAddRow(ParserToken rule) { parse_table.Add((int)rule, new Dictionary<int, int[]>()); } private void ProcessNumber(string number) { int result2; long result3; ulong result4; if ((number.IndexOf('.') != -1 || number.IndexOf('e') != -1 || number.IndexOf('E') != -1) && double.TryParse(number, out var result)) { token = JsonToken.Double; token_value = result; } else if (int.TryParse(number, out result2)) { token = JsonToken.Int; token_value = result2; } else if (long.TryParse(number, out result3)) { token = JsonToken.Long; token_value = result3; } else if (ulong.TryParse(number, out result4)) { token = JsonToken.Long; token_value = result4; } else { token = JsonToken.Int; token_value = 0; } } private void ProcessSymbol() { if (current_symbol == 91) { token = JsonToken.ArrayStart; parser_return = true; } else if (current_symbol == 93) { token = JsonToken.ArrayEnd; parser_return = true; } else if (current_symbol == 123) { token = JsonToken.ObjectStart; parser_return = true; } else if (current_symbol == 125) { token = JsonToken.ObjectEnd; parser_return = true; } else if (current_symbol == 34) { if (parser_in_string) { parser_in_string = false; parser_return = true; return; } if (token == JsonToken.None) { token = JsonToken.String; } parser_in_string = true; } else if (current_symbol == 65541) { token_value = lexer.StringValue; } else if (current_symbol == 65539) { token = JsonToken.Boolean; token_value = false; parser_return = true; } else if (current_symbol == 65540) { token = JsonToken.Null; parser_return = true; } else if (current_symbol == 65537) { ProcessNumber(lexer.StringValue); parser_return = true; } else if (current_symbol == 65546) { token = JsonToken.PropertyName; } else if (current_symbol == 65538) { token = JsonToken.Boolean; token_value = true; parser_return = true; } } private bool ReadToken() { if (end_of_input) { return false; } lexer.NextToken(); if (lexer.EndOfInput) { Close(); return false; } current_input = lexer.Token; return true; } public void Close() { if (!end_of_input) { end_of_input = true; end_of_json = true; if (reader_is_owned) { reader.Close(); } reader = null; } } public bool Read() { if (end_of_input) { return false; } if (end_of_json) { end_of_json = false; automaton_stack.Clear(); automaton_stack.Push(65553); automaton_stack.Push(65543); } parser_in_string = false; parser_return = false; token = JsonToken.None; token_value = null; if (!read_started) { read_started = true; if (!ReadToken()) { return false; } } while (true) { if (parser_return) { if (automaton_stack.Peek() == 65553) { end_of_json = true; } return true; } current_symbol = automaton_stack.Pop(); ProcessSymbol(); if (current_symbol == current_input) { if (!ReadToken()) { break; } continue; } int[] array; try { array = parse_table[current_symbol][current_input]; } catch (KeyNotFoundException inner_exception) { throw new JsonException((ParserToken)current_input, inner_exception); } if (array[0] != 65554) { for (int num = array.Length - 1; num >= 0; num--) { automaton_stack.Push(array[num]); } } } if (automaton_stack.Peek() != 65553) { throw new JsonException("Input doesn't evaluate to proper JSON text"); } if (parser_return) { return true; } return false; } } internal enum Condition { InArray, InObject, NotAProperty, Property, Value } internal class WriterContext { public int Count; public bool InArray; public bool InObject; public bool ExpectingValue; public int Padding; } internal class JsonWriter { private static NumberFormatInfo number_format; private WriterContext context; private Stack<WriterContext> ctx_stack; private bool has_reached_end; private char[] hex_seq; private int indentation; private int indent_value; private StringBuilder inst_string_builder; private bool pretty_print; private bool validate; private TextWriter writer; public int IndentValue { get { return indent_value; } set { indentation = indentation / indent_value * value; indent_value = value; } } public bool PrettyPrint { get { return pretty_print; } set { pretty_print = value; } } public TextWriter TextWriter => writer; public bool Validate { get { return validate; } set { validate = value; } } static JsonWriter() { number_format = NumberFormatInfo.InvariantInfo; } public JsonWriter() { inst_string_builder = new StringBuilder(); writer = new StringWriter(inst_string_builder); Init(); } public JsonWriter(StringBuilder sb) : this(new StringWriter(sb)) { } public JsonWriter(TextWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } this.writer = writer; Init(); } private void DoValidation(Condition cond) { if (!context.ExpectingValue) { context.Count++; } if (!validate) { return; } if (has_reached_end) { throw new JsonException("A complete JSON symbol has already been written"); } switch (cond) { case Condition.InArray: if (!context.InArray) { throw new JsonException("Can't close an array here"); } break; case Condition.InObject: if (!context.InObject || context.ExpectingValue) { throw new JsonException("Can't close an object here"); } break; case Condition.NotAProperty: if (context.InObject && !context.ExpectingValue) { throw new JsonException("Expected a property"); } break; case Condition.Property: if (!context.InObject || context.ExpectingValue) { throw new JsonException("Can't add a property here"); } break; case Condition.Value: if (!context.InArray && (!context.InObject || !context.ExpectingValue)) { throw new JsonException("Can't add a value here"); } break; } } private void Init() { has_reached_end = false; hex_seq = new char[4]; indentation = 0; indent_value = 4; pretty_print = false; validate = true; ctx_stack = new Stack<WriterContext>(); context = new WriterContext(); ctx_stack.Push(context); } priva