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 ToySupport v1.0.0
REPOToySupport.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Lovense.UnityKit.Remote; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using REPOToySupport.Patches; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("VoltaicGRiD")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("REPOToySupport")] [assembly: AssemblyTitle("REPOToySupport")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOToySupport { [HarmonyPatch(typeof(PlayerController))] internal static class ExamplePlayerControllerPatch { [HarmonyPrefix] [HarmonyPatch("Start")] private static void Start_Prefix(PlayerController __instance) { REPOToySupport.Logger.LogDebug((object)$"{__instance} Start Prefix"); } [HarmonyPostfix] [HarmonyPatch("Start")] private static void Start_Postfix(PlayerController __instance) { REPOToySupport.Logger.LogDebug((object)$"{__instance} Start Postfix"); } } [BepInPlugin("VoltaicGRiD.REPOToySupport", "REPOToySupport", "1.0")] public class REPOToySupport : BaseUnityPlugin { [CompilerGenerated] private sealed class <ImpactStopCoroutine>d__39 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public REPOToySupport <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ImpactStopCoroutine>d__39(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.SendStopCommandsToToys(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <UpdateValue>d__31 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PhysGrabObject obj; public REPOToySupport <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateValue>d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.SendStopCommandsToToys(); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.SendCommmandToToys(obj); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private List<RemoteAppData> allAppDatas; private RemoteAppData thisRemoteAppData; private LovenseRemoteToy thisToy; private List<LovenseRemoteToy> allToys = new List<LovenseRemoteToy>(); private List<LovenseRemoteToy> selectedToys = new List<LovenseRemoteToy>(); private REPOPopupPage toySettingsPage; private string lovenseIP = string.Empty; private int lovensePort = 30010; private PhysGrabObject lastGrab; private float lastGrabValue; private ConfigEntry<string> vibrationSetting; private ConfigEntry<float> vibrationMax; private ConfigEntry<float> vibrationTimeout; private ConfigEntry<bool> vibrateOnHurt; internal static REPOToySupport Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown Instance = this; vibrationSetting = ((BaseUnityPlugin)this).Config.Bind<string>("Toy Support", "Vibration Based On", "value", new ConfigDescription(" How should the toy interact with the environment? \r\n \\\"weight\\\" will use the weight of the grabbed object, scaled to the maximum weight of all objects in the level.\r\n \\\"value\\\" will use the value of the grabbed object, scaled to the maximum value of all valuables in the level.\r\n \\\"impact\\\" will use the impact severity of a collision while holding a valuable: light impacts = 'maxVibration' / 4, medium impacts = 'maxVibration' / 2, heavy impacts = 'maxVibration'.", (AcceptableValueBase)null, Array.Empty<object>())); vibrationMax = ((BaseUnityPlugin)this).Config.Bind<float>("Toy Support", "Max Vibration", 1f, new ConfigDescription("The maximum vibration strength that can be sent to the toys. This setting does not override the value in your Lovense app, and is instead, a percentage of that maximum.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); vibrationTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Toy Support", "Vibration Timeout", 100f, new ConfigDescription("The timeout for the vibration command in seconds. This is the time after which the toy will stop vibrating after grabbing an item.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); vibrateOnHurt = ((BaseUnityPlugin)this).Config.Bind<bool>("Toy Support", "Vibrate On Hurt", true, new ConfigDescription("Whether to vibrate the toys when the player is hurt. This is useful for adding an extra layer of immersion to the game.", (AcceptableValueBase)null, Array.Empty<object>())); ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; ((UnityEvent<List<RemoteAppData>>)(object)LovenseRemote.onGetAppsEvent).AddListener((UnityAction<List<RemoteAppData>>)OnSearchLocalApp); ((UnityEvent<string>)(object)LovenseRemote.onGetAppsErrorEvent).AddListener((UnityAction<string>)OnGetAppError); ((UnityEvent<List<LovenseRemoteToy>>)(object)LovenseRemote.onGetToysEvent).AddListener((UnityAction<List<LovenseRemoteToy>>)OnGetToys); ((UnityEvent<string>)(object)LovenseRemote.onGetToysErrorEvent).AddListener((UnityAction<string>)OnGetToysError); ((UnityEvent<string, ControlToysResult>)(object)LovenseRemote.onControlToysEvent).AddListener((UnityAction<string, ControlToysResult>)OnControlToysResult); MenuAPI.AddElementToSettingsMenu((BuilderDelegate)delegate(Transform parent) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) toySettingsPage = MenuAPI.CreateREPOPopupPage("Toy Support Settings", (PresetSide)1, true, false, 0f); toySettingsPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) REPOInputField val5 = MenuAPI.CreateREPOInputField("IP", (Action<string>)delegate(string ipAddress) { lovenseIP = ipAddress; }, scrollView, Vector2.zero, false, "", ""); return ((REPOElement)val5).rectTransform; }, 0f, 0f); toySettingsPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) REPOSlider val4 = MenuAPI.CreateREPOSlider("Port", "The SLL port", (Action<int>)delegate(int port) { lovensePort = port; }, scrollView, Vector2.zero, 0, 999999, 30010, "", "", (BarBehavior)0); return ((REPOElement)val4).rectTransform; }, 0f, 0f); toySettingsPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) REPOButton val3 = MenuAPI.CreateREPOButton("Search", (Action)delegate { DoSearchToys(lovenseIP, lovensePort); }, scrollView, Vector2.zero); return ((REPOElement)val3).rectTransform; }, 0f, 0f); foreach (LovenseRemoteToy toy in selectedToys) { toySettingsPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0048: 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) REPOToggle val2 = MenuAPI.CreateREPOToggle(toy.nickName + " (" + toy.name + ")", (Action<bool>)delegate(bool isToggled) { ToggleToy(toy, isToggled); }, scrollView, default(Vector2), "ON", "OFF", true); return ((REPOElement)val2).rectTransform; }, 0f, 0f); } REPOButton val = MenuAPI.CreateREPOButton("Toy Support", (Action)delegate { toySettingsPage.OpenPage(true); }, parent, Vector2.zero); }); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void Update() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown List<PhysGrabber> list = (from g in Object.FindObjectsOfType<PhysGrabber>() where g.isLocal select g).ToList(); if (list.Count == 0) { SendStopCommandsToToys(); lastGrab = null; return; } foreach (PhysGrabber item in list) { if ((Object)item == (Object)null) { SendStopCommandsToToys(); lastGrab = null; continue; } PhysGrabObject grabbedPhysGrabObject = item.grabbedPhysGrabObject; if ((Object)grabbedPhysGrabObject == (Object)null) { SendStopCommandsToToys(); lastGrab = null; } } if (Object.op_Implicit((Object)(object)lastGrab)) { if (lastGrab.dead || (Object)(object)lastGrab.rb == (Object)null || lastGrab.rb.isKinematic || lastGrab.rb.mass <= 0f || !lastGrab.grabbed || !lastGrab.grabbedLocal) { SendStopCommandsToToys(); lastGrab = null; } } else { SendStopCommandsToToys(); } } private void DoSearchToys(string domain, int port) { Logger.LogInfo((object)$"Searching for toys at {domain}:{port}"); LovenseRemote.GetInstance().GetToys(domain, port, true, 30); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(typeof(REPOToySupport)); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } [IteratorStateMachine(typeof(<UpdateValue>d__31))] private IEnumerator UpdateValue(PhysGrabObject obj) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UpdateValue>d__31(0) { <>4__this = this, obj = obj }; } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerHealth), "Hurt")] private static void Hurt_Patch(PlayerHealth __instance, int damage) { if (!(__instance.invincibleTimer > 0f) && (!GameManager.Multiplayer() || __instance.photonView.IsMine) && !__instance.playerAvatar.deadSet && !__instance.godMode && Instance.vibrateOnHurt.Value && Instance.selectedToys.Count > 0) { float num = Mathf.Clamp((float)damage, 0f, 1f); Logger.LogInfo((object)$"Player hurt with damage {num}. Vibrating toys."); float num2 = num * (100f * Instance.vibrationMax.Value); Logger.LogInfo((object)$"Player hurt with damage {damage}. Sending vibration command with strength {num2}."); LovenseRemote.GetInstance().SendPattern(Instance.selectedToys, new List<LovenseCommandType> { (LovenseCommandType)0 }, new List<int> { (int)num2 }, 2f, 150, 5); } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabber), "PhysGrabStarted")] private static void PhysGrabStarted_Patch(PhysGrabber __instance) { PhysGrabObject grabbedObject = __instance.GetGrabbedObject(); if (Object.op_Implicit((Object)(object)grabbedObject)) { PhysGrabObject val = grabbedObject; if ((Object)(object)val != (Object)null) { if (!((Object)(object)Instance.lastGrab != (Object)null) || !((Object)(object)Instance.lastGrab == (Object)(object)val)) { Logger.LogInfo((object)("PhysGrabber started grabbing object: " + ((Object)val).name)); Instance.SendCommmandToToys(val); Instance.lastGrab = val; } } else { Logger.LogWarning((object)"PhysGrabber started but grabbed object is null."); Instance.SendStopCommandsToToys(); } } else { Logger.LogWarning((object)"PhysGrabber started but no object was grabbed."); Instance.SendStopCommandsToToys(); } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "ImpactLight")] private static void ImpactLight_Patch(PhysGrabObjectImpactDetector __instance) { if (!(Instance.vibrationSetting.Value != "impact")) { } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "ImpactMedium")] private static void ImpactMedium_Patch(PhysGrabObjectImpactDetector __instance) { if ((!(Instance.vibrationSetting.Value != "impact") || !(Instance.vibrationSetting.Value != "value")) && !__instance.isCart && !__instance.inCart && __instance.physGrabObject.heldByLocalPlayer) { float num = (__instance.physGrabObject.isValuable ? __instance.valuableObject.dollarValueCurrent : 0f); if (Instance.vibrationSetting.Value == "value") { IEnumerator enumerator = Instance.UpdateValue(__instance.physGrabObject); ((MonoBehaviour)Instance).StartCoroutine(enumerator); } else { float num2 = 0.25f * (100f * Instance.vibrationMax.Value); Logger.LogInfo((object)$"Medium impact detected on object '{((Object)__instance.physGrabObject).name}'. Sending impact command with strength {num2}."); Instance.SendImpactCommandToToys((int)num2); } } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "ImpactHeavy")] private static void ImpactHeavy_Patch(PhysGrabObjectImpactDetector __instance) { if ((!(Instance.vibrationSetting.Value != "impact") || !(Instance.vibrationSetting.Value != "value")) && !__instance.isCart && !__instance.inCart && __instance.physGrabObject.heldByLocalPlayer) { float num = (__instance.physGrabObject.isValuable ? __instance.valuableObject.dollarValueCurrent : 0f); if (Instance.vibrationSetting.Value == "value") { IEnumerator enumerator = Instance.UpdateValue(__instance.physGrabObject); ((MonoBehaviour)Instance).StartCoroutine(enumerator); } else { float num2 = 0.5f * (100f * Instance.vibrationMax.Value); Logger.LogInfo((object)$"Heavy impact detected on object '{((Object)__instance.physGrabObject).name}'. Sending impact command with strength {num2}."); Instance.SendImpactCommandToToys((int)num2); } } } private void SendStopCommandsToToys() { LovenseRemote.GetInstance().SendStopFunction(selectedToys, 5); } private void SendImpactCommandToToys(int strength) { if (selectedToys.Count == 0) { Logger.LogWarning((object)"No toys selected or grabbed object is null, cannot send impact command."); return; } float num = Mathf.Clamp((float)strength, 0f, vibrationMax.Value) * 100f; Logger.LogInfo((object)$"Sending impact command to toys with strength: {num}%"); LovenseRemote.GetInstance().SendPattern(selectedToys, new List<LovenseCommandType> { (LovenseCommandType)0 }, new List<int> { (int)num, 0 }, 1f, 100, 1); IEnumerator enumerator = ImpactStopCoroutine(1f); ((MonoBehaviour)this).StartCoroutine(enumerator); } [IteratorStateMachine(typeof(<ImpactStopCoroutine>d__39))] private IEnumerator ImpactStopCoroutine(float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ImpactStopCoroutine>d__39(0) { <>4__this = this, delay = delay }; } private void SendCommmandToToys(PhysGrabObject obj) { float num = 0f; float num2 = 0f; if (obj.isValuable && vibrationSetting.Value == "value") { num = ((Component)obj).GetComponent<ValuableObject>().dollarValueCurrent; num2 = Object.FindObjectsOfType<ValuableObject>().Max((ValuableObject v) => v.dollarValueCurrent); } else { if (!obj.isValuable || !(vibrationSetting.Value == "weight")) { if (!(vibrationSetting.Value == "impact")) { Logger.LogWarning((object)("Unknown vibration setting: " + vibrationSetting.Value + ". No command sent to toys.")); } return; } num = obj.rb.mass; num2 = Object.FindObjectsOfType<PhysGrabObject>().Max((PhysGrabObject o) => o.rb.mass); } float num3 = Mathf.Clamp(num / num2, 0f, 1f) * (100f * vibrationMax.Value); Logger.LogInfo((object)$"Sending command to toys with strength percentage: {num3}% for object '{((Object)obj).name}' with value {num}. (Max scene value: {num2})"); if (selectedToys.Count == 0) { Logger.LogWarning((object)"No toys selected to send command to."); return; } LovenseRemote.GetInstance().SendPattern(selectedToys, new List<LovenseCommandType> { (LovenseCommandType)0 }, new List<int> { (int)num3 }, vibrationTimeout.Value, 150, 5); } private void OnSearchLocalApp(List<RemoteAppData> appDatas) { allAppDatas = appDatas; for (int i = 0; i < appDatas.Count; i++) { } } public void OnGetToys(List<LovenseRemoteToy> toys) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown foreach (LovenseRemoteToy toy in toys) { Logger.LogInfo((object)("Found toy: " + toy.name + " (ID: " + toy.id + ")")); toySettingsPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0048: 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) REPOToggle val = MenuAPI.CreateREPOToggle(toy.nickName + " (" + toy.name + ")", (Action<bool>)delegate(bool isToggled) { ToggleToy(toy, isToggled); }, scrollView, default(Vector2), "ON", "OFF", false); return ((REPOElement)val).rectTransform; }, 0f, 0f); } } public void ToggleToy(LovenseRemoteToy toToggle, bool isToggled) { if (isToggled) { if (!selectedToys.Contains(toToggle)) { selectedToys.Add(toToggle); LovenseRemote.GetInstance().SendPattern(selectedToys, new List<LovenseCommandType> { (LovenseCommandType)0 }, new List<int> { 10, 5 }, 2f, 150, 5); } } else if (selectedToys.Contains(toToggle)) { selectedToys.Remove(toToggle); } } public void OnGetToysError(string errorMsg) { ShowError(errorMsg); } public void OnGetAppError(string errorMsg) { ShowError(errorMsg); } private void OnControlToysResult(string id, ControlToysResult result) { if (result.code != 200) { if (result.code == 500) { ShowError("code:" + result.code + ",HTTP server not started or disabled."); } else if (result.code == 400) { ShowError("code:" + result.code + ",Invalid Command."); } else if (result.code == 401) { ShowError("code:" + result.code + ",Toy Not Found."); } else if (result.code == 402) { ShowError("code:" + result.code + ",Toy Not Connected."); } else if (result.code == 403) { ShowError("code:" + result.code + ",Toy Doesn't Support This Command."); } else if (result.code == 404) { ShowError("code:" + result.code + ",Invalid Parameter."); } else if (result.code == 506) { ShowError("code:" + result.code + ",Server Error.Restart Lovense Connect."); } else { ShowError("code:" + result.code + "," + result.type); } } } public void ShowError(string errorMsg) { Debug.LogError((object)("Toy Support Error: " + errorMsg)); } } } namespace REPOToySupport.Patches { public static class PhysGrabberAccess { private static readonly FieldInfo grabbedObjField; static PhysGrabberAccess() { grabbedObjField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject"); } public static PhysGrabObject GetGrabbedObject(this PhysGrabber instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown object value = grabbedObjField.GetValue(instance); return (PhysGrabObject)((value is PhysGrabObject) ? value : null); } } }
LovenseRemote.dll
Decompiled a year 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.Security.Authentication; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using WebSocketSharp; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: UnityAPICompatibilityVersion("2022.3.21f1", new string[] { "UnityEngine.CoreModule:5A79F7E2D2330A8A8B4B84BF3AD22E03E5183A13", "UnityEngine.UnityWebRequestModule:425E1B960E006EA925923326A4EB2DB5379B4131" })] [assembly: AssemblyVersion("0.0.0.0")] namespace Lovense.UnityKit { public class LovenseTokenConfig { public string token { get; set; } } public class AesUtil { public class AesModel { public byte[] Data { get; set; } public string Key { get; set; } public string IV { get; set; } public CipherMode Mode { get; set; } public PaddingMode Padding { get; set; } } public static byte[] Encrypt(AesModel aesModel) { byte[] array = new byte[32]; byte[] bytes = Encoding.UTF8.GetBytes(aesModel.Key.PadRight(array.Length)); Array.Copy(bytes, array, array.Length); byte[] array2 = new byte[16]; byte[] bytes2 = Encoding.UTF8.GetBytes(aesModel.IV.PadRight(array2.Length)); Array.Copy(bytes2, array2, array2.Length); RijndaelManaged rijndaelManaged = new RijndaelManaged(); rijndaelManaged.Mode = aesModel.Mode; rijndaelManaged.Padding = aesModel.Padding; rijndaelManaged.Key = array; rijndaelManaged.IV = array2; byte[] result = null; try { using MemoryStream memoryStream = new MemoryStream(); using CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(), CryptoStreamMode.Write); cryptoStream.Write(aesModel.Data, 0, aesModel.Data.Length); cryptoStream.FlushFinalBlock(); result = memoryStream.ToArray(); } catch { } return result; } public static byte[] Decrypt(AesModel aesModel) { byte[] array = new byte[32]; byte[] bytes = Encoding.UTF8.GetBytes(aesModel.Key.PadRight(array.Length)); Array.Copy(bytes, array, array.Length); byte[] array2 = new byte[16]; byte[] bytes2 = Encoding.UTF8.GetBytes(aesModel.IV.PadRight(array2.Length)); Array.Copy(bytes2, array2, array2.Length); RijndaelManaged rijndaelManaged = new RijndaelManaged(); rijndaelManaged.Mode = aesModel.Mode; rijndaelManaged.Padding = aesModel.Padding; rijndaelManaged.Key = array; rijndaelManaged.IV = array2; byte[] result = null; try { using MemoryStream stream = new MemoryStream(aesModel.Data); using CryptoStream cryptoStream = new CryptoStream(stream, rijndaelManaged.CreateDecryptor(), CryptoStreamMode.Read); using MemoryStream memoryStream = new MemoryStream(); byte[] array3 = new byte[1048576]; int num = 0; while ((num = cryptoStream.Read(array3, 0, array3.Length)) > 0) { memoryStream.Write(array3, 0, num); } result = memoryStream.ToArray(); } catch { } return result; } public static string Encrypt(string data, string key, string iv = "") { byte[] bytes = Encoding.UTF8.GetBytes(data); byte[] array = Encrypt(new AesModel { Data = bytes, Key = key, IV = iv, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }); if (array == null) { return ""; } return Convert.ToBase64String(array); } public static string Decrypt(string data, string key, string iv = "") { byte[] data2 = Convert.FromBase64String(data); byte[] array = Decrypt(new AesModel { Data = data2, Key = key, IV = iv, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }); if (array == null) { return ""; } return Encoding.UTF8.GetString(array); } public static string Decrypt2(string cipherText, byte[] key, byte[] iv) { byte[] buffer = Convert.FromBase64String(cipherText); string result = null; using (AesManaged aesManaged = new AesManaged()) { aesManaged.Key = key; aesManaged.IV = iv; ICryptoTransform transform = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV); using MemoryStream stream = new MemoryStream(buffer); using CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read); using StreamReader streamReader = new StreamReader(stream2); result = streamReader.ReadToEnd(); } return result; } } public class LovenseException : ApplicationException { public LovenseException() { } internal LovenseException(LovenseToken token) : base($"Invalid token '{token}' in input string") { } internal LovenseException(LovenseToken token, Exception inner_exception) : base($"Invalid token '{token}' in input string", inner_exception) { } internal LovenseException(int c) : base($"Invalid character '{(char)c}' in input string") { } internal LovenseException(int c, Exception inner_exception) : base($"Invalid character '{(char)c}' in input string", inner_exception) { } public LovenseException(string message) : base(message) { } public LovenseException(string message, Exception inner_exception) : base(message, inner_exception) { } } public class LovenseJD : LovenseJW, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary, IEquatable<LovenseJD> { private IList<LovenseJD> inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary<string, LovenseJD> inst_object; private string inst_string; private string json; private LovenseJt type; private IList<KeyValuePair<string, LovenseJD>> object_list; public int Count => EnsureCollection().Count; public bool IsArray => type == LovenseJt.Array; public bool IsBoolean => type == LovenseJt.Boolean; public bool IsDouble => type == LovenseJt.Double; public bool IsInt => type == LovenseJt.Int; public bool IsLong => type == LovenseJt.Long; public bool IsObject => type == LovenseJt.Object; public bool IsString => type == LovenseJt.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, LovenseJD> item in object_list) { list.Add(item.Key); } return (ICollection)list; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList<LovenseJD> list = new List<LovenseJD>(); foreach (KeyValuePair<string, LovenseJD> item in object_list) { list.Add(item.Value); } return (ICollection)list; } } bool LovenseJW.IsArray => IsArray; bool LovenseJW.IsBoolean => IsBoolean; bool LovenseJW.IsDouble => IsDouble; bool LovenseJW.IsInt => IsInt; bool LovenseJW.IsLong => IsLong; bool LovenseJW.IsObject => IsObject; bool LovenseJW.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"); } LovenseJD value2 = ToJsonData(value); this[(string)key] = value2; } } object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); LovenseJD value2 = ToJsonData(value); KeyValuePair<string, LovenseJD> keyValuePair = object_list[idx]; inst_object[keyValuePair.Key] = value2; KeyValuePair<string, LovenseJD> value3 = new KeyValuePair<string, LovenseJD>(keyValuePair.Key, value2); object_list[idx] = value3; } } object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); LovenseJD value2 = ToJsonData(value); this[index] = value2; } } public LovenseJD this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair<string, LovenseJD> keyValuePair = new KeyValuePair<string, LovenseJD>(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 LovenseJD this[int index] { get { EnsureCollection(); if (type == LovenseJt.Array) { return inst_array[index]; } return object_list[index].Value; } set { EnsureCollection(); if (type == LovenseJt.Array) { inst_array[index] = value; } else { KeyValuePair<string, LovenseJD> keyValuePair = object_list[index]; KeyValuePair<string, LovenseJD> value2 = new KeyValuePair<string, LovenseJD>(keyValuePair.Key, value); object_list[index] = value2; inst_object[keyValuePair.Key] = value; } json = null; } } public bool ContainsKey(string key) { EnsureDictionary(); return inst_object.Keys.Contains(key); } public LovenseJD() { } public LovenseJD(bool boolean) { type = LovenseJt.Boolean; inst_boolean = boolean; } public LovenseJD(double number) { type = LovenseJt.Double; inst_double = number; } public LovenseJD(int number) { type = LovenseJt.Int; inst_int = number; } public LovenseJD(long number) { type = LovenseJt.Long; inst_long = number; } public LovenseJD(object obj) { if (obj is bool) { type = LovenseJt.Boolean; inst_boolean = (bool)obj; return; } if (obj is double) { type = LovenseJt.Double; inst_double = (double)obj; return; } if (obj is int) { type = LovenseJt.Int; inst_int = (int)obj; return; } if (obj is long) { type = LovenseJt.Long; inst_long = (long)obj; return; } if (obj is string) { type = LovenseJt.String; inst_string = (string)obj; return; } throw new ArgumentException("Unable to wrap the given object with LovenseJD"); } public LovenseJD(string str) { type = LovenseJt.String; inst_string = str; } public static implicit operator LovenseJD(bool data) { return new LovenseJD(data); } public static implicit operator LovenseJD(double data) { return new LovenseJD(data); } public static implicit operator LovenseJD(int data) { return new LovenseJD(data); } public static implicit operator LovenseJD(long data) { return new LovenseJD(data); } public static implicit operator LovenseJD(string data) { return new LovenseJD(data); } public static explicit operator bool(LovenseJD data) { if (data.type != LovenseJt.Boolean) { throw new InvalidCastException("Instance of LovenseJD doesn't hold a double"); } return data.inst_boolean; } public static explicit operator double(LovenseJD data) { if (data.type != LovenseJt.Double) { throw new InvalidCastException("Instance of LovenseJD doesn't hold a double"); } return data.inst_double; } public static explicit operator int(LovenseJD data) { if (data.type != LovenseJt.Int && data.type != LovenseJt.Long) { throw new InvalidCastException("Instance of LovenseJD doesn't hold an int"); } return (int)((data.type == LovenseJt.Int) ? data.inst_int : data.inst_long); } public static explicit operator long(LovenseJD data) { if (data.type != LovenseJt.Long && data.type != LovenseJt.Int) { throw new InvalidCastException("Instance of LovenseJD doesn't hold a long"); } return (data.type == LovenseJt.Long) ? data.inst_long : data.inst_int; } public static explicit operator string(LovenseJD data) { if (data.type != LovenseJt.String) { throw new InvalidCastException("Instance of LovenseJD 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) { LovenseJD value2 = ToJsonData(value); EnsureDictionary().Add(key, value2); KeyValuePair<string, LovenseJD> item = new KeyValuePair<string, LovenseJD>((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 LovenseJW.GetBoolean() { if (type != LovenseJt.Boolean) { throw new InvalidOperationException("LovenseJD instance doesn't hold a boolean"); } return inst_boolean; } double LovenseJW.GetDouble() { if (type != LovenseJt.Double) { throw new InvalidOperationException("LovenseJD instance doesn't hold a double"); } return inst_double; } int LovenseJW.GetInt() { if (type != LovenseJt.Int) { throw new InvalidOperationException("LovenseJD instance doesn't hold an int"); } return inst_int; } long LovenseJW.GetLong() { if (type != LovenseJt.Long) { throw new InvalidOperationException("LovenseJD instance doesn't hold a long"); } return inst_long; } string LovenseJW.GetString() { if (type != LovenseJt.String) { throw new InvalidOperationException("LovenseJD instance doesn't hold a string"); } return inst_string; } void LovenseJW.SetBoolean(bool val) { type = LovenseJt.Boolean; inst_boolean = val; json = null; } void LovenseJW.SetDouble(double val) { type = LovenseJt.Double; inst_double = val; json = null; } void LovenseJW.SetInt(int val) { type = LovenseJt.Int; inst_int = val; json = null; } void LovenseJW.SetLong(long val) { type = LovenseJt.Long; inst_long = val; json = null; } void LovenseJW.SetString(string val) { type = LovenseJt.String; inst_string = val; json = null; } string LovenseJW.ToJson() { return ToJson(); } void LovenseJW.ToJson(LovenseWr 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; LovenseJD value2 = (this[text] = ToJsonData(value)); KeyValuePair<string, LovenseJD> item = new KeyValuePair<string, LovenseJD>(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 == LovenseJt.Array) { return (ICollection)inst_array; } if (type == LovenseJt.Object) { return (ICollection)inst_object; } throw new InvalidOperationException("The LovenseJD instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == LovenseJt.Object) { return (IDictionary)inst_object; } if (type != 0) { throw new InvalidOperationException("Instance of LovenseJD is not a dictionary"); } type = LovenseJt.Object; inst_object = new Dictionary<string, LovenseJD>(); object_list = new List<KeyValuePair<string, LovenseJD>>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == LovenseJt.Array) { return (IList)inst_array; } if (type != 0) { throw new InvalidOperationException("Instance of LovenseJD is not a list"); } type = LovenseJt.Array; inst_array = new List<LovenseJD>(); return (IList)inst_array; } private LovenseJD ToJsonData(object obj) { if (obj == null) { return null; } if (obj is LovenseJD) { return (LovenseJD)obj; } return new LovenseJD(obj); } private static void WriteJson(LovenseJW obj, LovenseWr 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((LovenseJD)item, writer); } writer.WriteArrayEnd(); } else { if (!obj.IsObject) { return; } writer.WriteObjectStart(); foreach (DictionaryEntry item2 in (IDictionary)obj) { writer.WritePropertyName((string)item2.Key); WriteJson((LovenseJD)item2.Value, writer); } writer.WriteObjectEnd(); } } public int Add(object value) { LovenseJD value2 = ToJsonData(value); json = null; return EnsureList().Add(value2); } public bool Remove(object obj) { json = null; if (IsObject) { LovenseJD value = null; if (inst_object.TryGetValue((string)obj, out value)) { return inst_object.Remove((string)obj) && object_list.Remove(new KeyValuePair<string, LovenseJD>((string)obj, value)); } throw new KeyNotFoundException("The specified key was not found in the LovenseJD object."); } if (IsArray) { return inst_array.Remove(ToJsonData(obj)); } throw new InvalidOperationException("Instance of LovenseJD is not an object or a list."); } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); } else if (IsArray) { ((IList)this).Clear(); } } public bool Equals(LovenseJD x) { if (x == null) { return false; } if (x.type != type && ((x.type != LovenseJt.Int && x.type != LovenseJt.Long) || (type != LovenseJt.Int && type != LovenseJt.Long))) { return false; } switch (type) { case LovenseJt.None: return true; case LovenseJt.Object: return inst_object.Equals(x.inst_object); case LovenseJt.Array: return inst_array.Equals(x.inst_array); case LovenseJt.String: return inst_string.Equals(x.inst_string); case LovenseJt.Int: if (x.IsLong) { if (x.inst_long < int.MinValue || x.inst_long > int.MaxValue) { return false; } return inst_int.Equals((int)x.inst_long); } return inst_int.Equals(x.inst_int); case LovenseJt.Long: if (x.IsInt) { if (inst_long < int.MinValue || inst_long > int.MaxValue) { return false; } return x.inst_int.Equals((int)inst_long); } return inst_long.Equals(x.inst_long); case LovenseJt.Double: return inst_double.Equals(x.inst_double); case LovenseJt.Boolean: return inst_boolean.Equals(x.inst_boolean); default: return false; } } public LovenseJt GetJsonType() { return type; } public void SetJsonType(LovenseJt type) { if (this.type != type) { switch (type) { case LovenseJt.Object: inst_object = new Dictionary<string, LovenseJD>(); object_list = new List<KeyValuePair<string, LovenseJD>>(); break; case LovenseJt.Array: inst_array = new List<LovenseJD>(); break; case LovenseJt.String: inst_string = null; break; case LovenseJt.Int: inst_int = 0; break; case LovenseJt.Long: inst_long = 0L; break; case LovenseJt.Double: inst_double = 0.0; break; case LovenseJt.Boolean: inst_boolean = false; break; } this.type = type; } } public string ToJson() { if (json != null) { return json; } StringWriter stringWriter = new StringWriter(); LovenseWr lovenseWr = new LovenseWr(stringWriter); lovenseWr.Validate = false; WriteJson(this, lovenseWr); json = stringWriter.ToString(); return json; } public void ToJson(LovenseWr writer) { bool validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = validate; } public override string ToString() { return type switch { LovenseJt.Array => "LovenseJD array", LovenseJt.Boolean => inst_boolean.ToString(), LovenseJt.Double => inst_double.ToString(), LovenseJt.Int => inst_int.ToString(), LovenseJt.Long => inst_long.ToString(), LovenseJt.Object => "LovenseJD object", LovenseJt.String => inst_string, _ => "Uninitialized LovenseJD", }; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private IEnumerator<KeyValuePair<string, LovenseJD>> list_enumerator; public object Current => Entry; public DictionaryEntry Entry { get { KeyValuePair<string, LovenseJD> 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, LovenseJD>> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } public enum LovenseJToken { None, ObjectStart, PropertyName, ObjectEnd, ArrayStart, ArrayEnd, Int, Long, Double, String, Boolean, Null } public class LovenseJRd { private static readonly 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 LovenseLx 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 LovenseJToken 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 LovenseJToken Token => token; public object Value => token_value; static LovenseJRd() { parse_table = PopulateParseTable(); } public LovenseJRd(string json_text) : this(new StringReader(json_text), owned: true) { } public LovenseJRd(TextReader reader) : this(reader, owned: false) { } private LovenseJRd(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 LovenseLx(reader); end_of_input = false; end_of_json = false; skip_non_members = true; this.reader = reader; reader_is_owned = owned; } private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable() { IDictionary<int, IDictionary<int, int[]>> result = new Dictionary<int, IDictionary<int, int[]>>(); TableAddRow(result, LovenseToken.Array); TableAddCol(result, LovenseToken.Array, 91, 91, 65549); TableAddRow(result, LovenseToken.ArrayPrime); TableAddCol(result, LovenseToken.ArrayPrime, 34, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 91, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 93, 93); TableAddCol(result, LovenseToken.ArrayPrime, 123, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 65537, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 65538, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 65539, 65550, 65551, 93); TableAddCol(result, LovenseToken.ArrayPrime, 65540, 65550, 65551, 93); TableAddRow(result, LovenseToken.Object); TableAddCol(result, LovenseToken.Object, 123, 123, 65545); TableAddRow(result, LovenseToken.ObjectPrime); TableAddCol(result, LovenseToken.ObjectPrime, 34, 65546, 65547, 125); TableAddCol(result, LovenseToken.ObjectPrime, 125, 125); TableAddRow(result, LovenseToken.Pair); TableAddCol(result, LovenseToken.Pair, 34, 65552, 58, 65550); TableAddRow(result, LovenseToken.PairRest); TableAddCol(result, LovenseToken.PairRest, 44, 44, 65546, 65547); TableAddCol(result, LovenseToken.PairRest, 125, 65554); TableAddRow(result, LovenseToken.String); TableAddCol(result, LovenseToken.String, 34, 34, 65541, 34); TableAddRow(result, LovenseToken.Text); TableAddCol(result, LovenseToken.Text, 91, 65548); TableAddCol(result, LovenseToken.Text, 123, 65544); TableAddRow(result, LovenseToken.Value); TableAddCol(result, LovenseToken.Value, 34, 65552); TableAddCol(result, LovenseToken.Value, 91, 65548); TableAddCol(result, LovenseToken.Value, 123, 65544); TableAddCol(result, LovenseToken.Value, 65537, 65537); TableAddCol(result, LovenseToken.Value, 65538, 65538); TableAddCol(result, LovenseToken.Value, 65539, 65539); TableAddCol(result, LovenseToken.Value, 65540, 65540); TableAddRow(result, LovenseToken.ValueRest); TableAddCol(result, LovenseToken.ValueRest, 44, 44, 65550, 65551); TableAddCol(result, LovenseToken.ValueRest, 93, 65554); return result; } private static void TableAddCol(IDictionary<int, IDictionary<int, int[]>> parse_table, LovenseToken row, int col, params int[] symbols) { parse_table[(int)row].Add(col, symbols); } private static void TableAddRow(IDictionary<int, IDictionary<int, int[]>> parse_table, LovenseToken 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, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { token = LovenseJToken.Double; token_value = result; } else if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2)) { token = LovenseJToken.Int; token_value = result2; } else if (long.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result3)) { token = LovenseJToken.Long; token_value = result3; } else if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result4)) { token = LovenseJToken.Long; token_value = result4; } else { token = LovenseJToken.Int; token_value = 0; } } private void ProcessSymbol() { if (current_symbol == 91) { token = LovenseJToken.ArrayStart; parser_return = true; } else if (current_symbol == 93) { token = LovenseJToken.ArrayEnd; parser_return = true; } else if (current_symbol == 123) { token = LovenseJToken.ObjectStart; parser_return = true; } else if (current_symbol == 125) { token = LovenseJToken.ObjectEnd; parser_return = true; } else if (current_symbol == 34) { if (parser_in_string) { parser_in_string = false; parser_return = true; return; } if (token == LovenseJToken.None) { token = LovenseJToken.String; } parser_in_string = true; } else if (current_symbol == 65541) { token_value = lexer.StringValue; } else if (current_symbol == 65539) { token = LovenseJToken.Boolean; token_value = false; parser_return = true; } else if (current_symbol == 65540) { token = LovenseJToken.Null; parser_return = true; } else if (current_symbol == 65537) { ProcessNumber(lexer.StringValue); parser_return = true; } else if (current_symbol == 65546) { token = LovenseJToken.PropertyName; } else if (current_symbol == 65538) { token = LovenseJToken.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) { return; } end_of_input = true; end_of_json = true; if (reader_is_owned) { using (reader) { } } 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 = LovenseJToken.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 LovenseException((LovenseToken)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 LovenseException("Input doesn't evaluate to proper JSON text"); } if (parser_return) { return true; } return false; } } internal struct LovensePMD { public MemberInfo Info; public bool IsField; public Type Type; } internal struct LovenseArrMd { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { if (element_type == null) { return typeof(LovenseJD); } 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 LovenseObjMd { private Type element_type; private bool is_dictionary; private IDictionary<string, LovensePMD> properties; public Type ElementType { get { if (element_type == null) { return typeof(LovenseJD); } return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary<string, LovensePMD> Properties { get { return properties; } set { properties = value; } } } internal delegate void ExporterFunc(object obj, LovenseWr writer); public delegate void ExporterFunc<T>(T obj, LovenseWr writer); internal delegate object ImporterFunc(object input); public delegate TValue ImporterFunc<TJson, TValue>(TJson input); public delegate LovenseJW WrapperFactory(); public class LovenseJsonUtils { private static readonly int max_nesting_depth; private static readonly IFormatProvider datetime_format; private static readonly IDictionary<Type, ExporterFunc> base_exporters_table; private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table; private static readonly IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table; private static readonly IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table; private static readonly IDictionary<Type, LovenseArrMd> array_metadata; private static readonly object array_metadata_lock; private static readonly IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops; private static readonly object conv_ops_lock; private static readonly IDictionary<Type, LovenseObjMd> object_metadata; private static readonly object object_metadata_lock; private static readonly IDictionary<Type, IList<LovensePMD>> type_properties; private static readonly object type_properties_lock; private static readonly LovenseWr static_writer; private static readonly object static_writer_lock; static LovenseJsonUtils() { 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, LovenseArrMd>(); conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); object_metadata = new Dictionary<Type, LovenseObjMd>(); type_properties = new Dictionary<Type, IList<LovensePMD>>(); static_writer = new LovenseWr(); 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; } LovenseArrMd value = default(LovenseArrMd); 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; } LovenseObjMd value = default(LovenseObjMd); if (type.GetInterface("System.Collections.IDictionary") != null) { value.IsDictionary = true; } value.Properties = new Dictionary<string, LovensePMD>(); 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 { LovensePMD value2 = default(LovensePMD); value2.Info = propertyInfo; value2.Type = propertyInfo.PropertyType; value.Properties.Add(propertyInfo.Name, value2); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo fieldInfo in fields) { LovensePMD value3 = default(LovensePMD); 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<LovensePMD> list = new List<LovensePMD>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name == "Item")) { LovensePMD item = default(LovensePMD); item.Info = propertyInfo; item.IsField = false; list.Add(item); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo info in fields) { LovensePMD item2 = default(LovensePMD); 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); } catch (ArgumentException) { return conv_ops[t1][t2]; } } return method; } private static object ReadValue(Type inst_type, LovenseJRd reader) { reader.Read(); if (reader.Token == LovenseJToken.ArrayEnd) { return null; } Type underlyingType = Nullable.GetUnderlyingType(inst_type); Type type = underlyingType ?? inst_type; if (reader.Token == LovenseJToken.Null) { if (inst_type.IsClass || underlyingType != null) { return null; } throw new LovenseException($"Can't assign null to an instance of type {inst_type}"); } if (reader.Token == LovenseJToken.Double || reader.Token == LovenseJToken.Int || reader.Token == LovenseJToken.Long || reader.Token == LovenseJToken.String || reader.Token == LovenseJToken.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 LovenseException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}"); } object obj = null; if (reader.Token == LovenseJToken.ArrayStart) { AddArrayMetadata(inst_type); LovenseArrMd lovenseArrMd = array_metadata[inst_type]; if (!lovenseArrMd.IsArray && !lovenseArrMd.IsList) { throw new LovenseException($"Type {inst_type} can't act as an array"); } IList list; Type elementType; if (!lovenseArrMd.IsArray) { list = (IList)Activator.CreateInstance(inst_type); elementType = lovenseArrMd.ElementType; } else { list = new ArrayList(); elementType = inst_type.GetElementType(); } list.Clear(); while (true) { object obj2 = ReadValue(elementType, reader); if (obj2 == null && reader.Token == LovenseJToken.ArrayEnd) { break; } list.Add(obj2); } if (lovenseArrMd.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 == LovenseJToken.ObjectStart) { AddObjectMetadata(type); LovenseObjMd lovenseObjMd = object_metadata[type]; obj = Activator.CreateInstance(type); while (true) { reader.Read(); if (reader.Token == LovenseJToken.ObjectEnd) { break; } string text = (string)reader.Value; if (lovenseObjMd.Properties.ContainsKey(text)) { LovensePMD lovensePMD = lovenseObjMd.Properties[text]; if (lovensePMD.IsField) { ((FieldInfo)lovensePMD.Info).SetValue(obj, ReadValue(lovensePMD.Type, reader)); continue; } PropertyInfo propertyInfo = (PropertyInfo)lovensePMD.Info; if (propertyInfo.CanWrite) { propertyInfo.SetValue(obj, ReadValue(lovensePMD.Type, reader), null); } else { ReadValue(lovensePMD.Type, reader); } } else if (!lovenseObjMd.IsDictionary) { if (!reader.SkipNonMembers) { throw new LovenseException($"The type {inst_type} doesn't have the property '{text}'"); } ReadSkip(reader); } else { ((IDictionary)obj).Add(text, ReadValue(lovenseObjMd.ElementType, reader)); } } } return obj; } private static LovenseJW ReadValue(WrapperFactory factory, LovenseJRd reader) { reader.Read(); if (reader.Token == LovenseJToken.ArrayEnd || reader.Token == LovenseJToken.Null) { return null; } LovenseJW lovenseJW = factory(); if (reader.Token == LovenseJToken.String) { lovenseJW.SetString((string)reader.Value); return lovenseJW; } if (reader.Token == LovenseJToken.Double) { lovenseJW.SetDouble((double)reader.Value); return lovenseJW; } if (reader.Token == LovenseJToken.Int) { lovenseJW.SetInt((int)reader.Value); return lovenseJW; } if (reader.Token == LovenseJToken.Long) { lovenseJW.SetLong((long)reader.Value); return lovenseJW; } if (reader.Token == LovenseJToken.Boolean) { lovenseJW.SetBoolean((bool)reader.Value); return lovenseJW; } if (reader.Token == LovenseJToken.ArrayStart) { lovenseJW.SetJsonType(LovenseJt.Array); while (true) { LovenseJW lovenseJW2 = ReadValue(factory, reader); if (lovenseJW2 == null && reader.Token == LovenseJToken.ArrayEnd) { break; } lovenseJW.Add(lovenseJW2); } } else if (reader.Token == LovenseJToken.ObjectStart) { lovenseJW.SetJsonType(LovenseJt.Object); while (true) { reader.Read(); if (reader.Token == LovenseJToken.ObjectEnd) { break; } string key = (string)reader.Value; lovenseJW[key] = ReadValue(factory, reader); } } return lovenseJW; } private static void ReadSkip(LovenseJRd reader) { ToWrapper(() => new LovenseMW(), reader); } private static void RegisterBaseExporters() { base_exporters_table[typeof(byte)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToInt32((byte)obj)); }; base_exporters_table[typeof(char)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToString((char)obj)); }; base_exporters_table[typeof(DateTime)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToString((DateTime)obj, datetime_format)); }; base_exporters_table[typeof(decimal)] = delegate(object obj, LovenseWr writer) { writer.Write((decimal)obj); }; base_exporters_table[typeof(sbyte)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToInt32((sbyte)obj)); }; base_exporters_table[typeof(short)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToInt32((short)obj)); }; base_exporters_table[typeof(ushort)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToInt32((ushort)obj)); }; base_exporters_table[typeof(uint)] = delegate(object obj, LovenseWr writer) { writer.Write(Convert.ToUInt64((uint)obj)); }; base_exporters_table[typeof(ulong)] = delegate(object obj, LovenseWr writer) { writer.Write((ulong)obj); }; base_exporters_table[typeof(DateTimeOffset)] = delegate(object obj, LovenseWr writer) { writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); }; } 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.ToInt64((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(long), 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.ToSingle((double)input); RegisterImporter(base_importers_table, typeof(double), typeof(float), 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); importer = (object input) => DateTimeOffset.Parse((string)input, datetime_format); RegisterImporter(base_importers_table, typeof(string), typeof(DateTimeOffset), 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, LovenseWr writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) { throw new LovenseException($"Max allowed object depth reached while trying to export from type {obj.GetType()}"); } if (obj == null) { writer.Write(null); return; } if (obj is LovenseJW) { if (writer_is_private) { writer.TextWriter.Write(((LovenseJW)obj).ToJson()); } else { ((LovenseJW)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 float) { writer.Write((float)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) { IDictionary dictionary = (IDictionary)obj; writer.WriteObjectStart(); foreach (DictionaryEntry item3 in dictionary) { string property_name = ((item3.Key is string) ? ((string)item3.Key) : Convert.ToString(item3.Key, CultureInfo.InvariantCulture)); writer.WritePropertyName(property_name); 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)) { writer.Write((long)obj); } else if (underlyingType == typeof(uint)) { writer.Write((uint)obj); } else if (underlyingType == typeof(ulong)) { writer.Write((ulong)obj); } else if (underlyingType == typeof(ushort)) { writer.Write((ushort)obj); } else if (underlyingType == typeof(short)) { writer.Write((short)obj); } else if (underlyingType == typeof(byte)) { writer.Write((byte)obj); } else if (underlyingType == typeof(sbyte)) { writer.Write((sbyte)obj); } else { writer.Write((int)obj); } return; } AddTypeProperties(type); IList<LovensePMD> list = type_properties[type]; writer.WriteObjectStart(); foreach (LovensePMD 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, LovenseWr writer) { WriteValue(obj, writer, writer_is_private: false, 0); } public static LovenseJD ToObject(LovenseJRd reader) { return (LovenseJD)ToWrapper(() => new LovenseJD(), reader); } public static LovenseJD ToObject(TextReader reader) { LovenseJRd reader2 = new LovenseJRd(reader); return (LovenseJD)ToWrapper(() => new LovenseJD(), reader2); } public static LovenseJD ToObject(string json) { return (LovenseJD)ToWrapper(() => new LovenseJD(), json); } public static T ToObject<T>(LovenseJRd reader) { return (T)ReadValue(typeof(T), reader); } public static T ToObject<T>(TextReader reader) { LovenseJRd reader2 = new LovenseJRd(reader); return (T)ReadValue(typeof(T), reader2); } public static T ToObject<T>(string json) { LovenseJRd reader = new LovenseJRd(json); return (T)ReadValue(typeof(T), reader); } public static object ToObject(string json, Type ConvertType) { LovenseJRd reader = new LovenseJRd(json); return ReadValue(ConvertType, reader); } public static LovenseJW ToWrapper(WrapperFactory factory, LovenseJRd reader) { return ReadValue(factory, reader); } public static LovenseJW ToWrapper(WrapperFactory factory, string json) { LovenseJRd reader = new LovenseJRd(json); return ReadValue(factory, reader); } public static void RegisterExporter<T>(ExporterFunc<T> exporter) { ExporterFunc value = delegate(object obj, LovenseWr 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(); } } public enum LovenseJt { None, Object, Array, String, Int, Long, Double, Boolean } public interface LovenseJW : IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary { 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(); LovenseJt GetJsonType(); long GetLong(); string GetString(); void SetBoolean(bool val); void SetDouble(double val); void SetInt(int val); void SetJsonType(LovenseJt type); void SetLong(long val); void SetString(string val); string ToJson(); void ToJson(LovenseWr writer); } internal class LovenseFsmContent { public bool Return; public int NextState; public LovenseLx L; public int StateStack; } internal class LovenseLx { private delegate bool StateHandler(LovenseFsmContent ctx); private static readonly int[] fsm_return_table; private static readonly StateHandler[] fsm_handler_table; private bool allow_comments; private bool allow_single_quoted_strings; private bool end_of_input; private LovenseFsmContent fsm_context; private int input_buffer; private int input_char; private TextReader reader; private int state; private StringBuilder string_buffer; private string string_value; private int token; private int unichar; public bool AllowComments { get { return allow_comments; } set { allow_comments = value; } } public bool AllowSingleQuotedStrings { get { return allow_single_quoted_strings; } set { allow_single_quoted_strings = value; } } public bool EndOfInput => end_of_input; public int Token => token; public string StringValue => string_value; static LovenseLx() { PopulateFsmTables(out fsm_handler_table, out fsm_return_table); } public LovenseLx(TextReader reader) { allow_comments = true; allow_single_quoted_strings = true; input_buffer = 0; string_buffer = new StringBuilder(128); state = 1; end_of_input = false; this.reader = reader; fsm_context = new LovenseFsmContent(); fsm_context.L = this; } private static int HexValue(int digit) { switch (digit) { case 65: case 97: return 10; case 66: case 98: return 11; case 67: case 99: return 12; case 68: case 100: return 13; case 69: case 101: return 14; case 70: case 102: return 15; default: return digit - 48; } } private static void PopulateFsmTables(out StateHandler[] fsm_handler_table, out int[] fsm_return_table) { fsm_handler_table = new StateHandler[28] { State1, State2, State3, State4, State5, State6, State7, State8, State9, State10, State11, State12, State13, State14, State15, State16, State17, State18, State19, State20, State21, State22, State23, State24, State25, State26, State27, State28 }; fsm_return_table = new int[28] { 65542, 0, 65537, 65537, 0, 65537, 0, 65537, 0, 0, 65538, 0, 0, 0, 65539, 0, 0, 65540, 65541, 65542, 0, 0, 65541, 65542, 0, 0, 0, 0 }; } private static char ProcessEscChar(int esc_char) { switch (esc_char) { case 34: case 39: case 47: case 92: return Convert.ToChar(esc_char); case 110: return '\n'; case 116: return '\t'; case 114: return '\r'; case 98: return '\b'; case 102: return '\f'; default: return '?'; } } private static bool State1(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { continue; } if (ctx.L.input_char >= 49 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 3; return true; } switch (ctx.L.input_char) { case 34: ctx.NextState = 19; ctx.Return = true; return true; case 44: case 58: case 91: case 93: case 123: case 125: ctx.NextState = 1; ctx.Return = true; return true; case 45: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 2; return true; case 48: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 4; return true; case 102: ctx.NextState = 12; return true; case 110: ctx.NextState = 16; return true; case 116: ctx.NextState = 9; return true; case 39: if (!ctx.L.allow_single_quoted_strings) { return false; } ctx.L.input_char = 34; ctx.NextState = 23; ctx.Return = true; return true; case 47: if (!ctx.L.allow_comments) { return false; } ctx.NextState = 25; return true; default: return false; } } return true; } private static bool State2(LovenseFsmContent ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 49 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 3; return true; } int num = ctx.L.input_char; int num2 = num; if (num2 == 48) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 4; return true; } return false; } private static bool State3(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 46: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 5; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } return true; } private static bool State4(LovenseFsmContent ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 46: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 5; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } private static bool State5(LovenseFsmContent ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 6; return true; } return false; } private static bool State6(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } return true; } private static bool State7(LovenseFsmContent ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 8; return true; } int num = ctx.L.input_char; int num2 = num; if (num2 == 43 || num2 == 45) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 8; return true; } return false; } private static bool State8(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } int num = ctx.L.input_char; int num2 = num; if (num2 == 44 || num2 == 93 || num2 == 125) { ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; } return false; } return true; } private static bool State9(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 114) { ctx.NextState = 10; return true; } return false; } private static bool State10(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 117) { ctx.NextState = 11; return true; } return false; } private static bool State11(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 101) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State12(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 97) { ctx.NextState = 13; return true; } return false; } private static bool State13(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 108) { ctx.NextState = 14; return true; } return false; } private static bool State14(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 115) { ctx.NextState = 15; return true; } return false; } private static bool State15(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 101) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State16(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 117) { ctx.NextState = 17; return true; } return false; } private static bool State17(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 108) { ctx.NextState = 18; return true; } return false; } private static bool State18(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 108) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State19(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { switch (ctx.L.input_char) { case 34: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 20; return true; case 92: ctx.StateStack = 19; ctx.NextState = 21; return true; } ctx.L.string_buffer.Append((char)ctx.L.input_char); } return true; } private static bool State20(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 34) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State21(LovenseFsmContent ctx) { ctx.L.GetChar(); switch (ctx.L.input_char) { case 117: ctx.NextState = 22; return true; case 34: case 39: case 47: case 92: case 98: case 102: case 110: case 114: case 116: ctx.L.string_buffer.Append(ProcessEscChar(ctx.L.input_char)); ctx.NextState = ctx.StateStack; return true; default: return false; } } private static bool State22(LovenseFsmContent ctx) { int num = 0; int num2 = 4096; ctx.L.unichar = 0; while (ctx.L.GetChar()) { if ((ctx.L.input_char >= 48 && ctx.L.input_char <= 57) || (ctx.L.input_char >= 65 && ctx.L.input_char <= 70) || (ctx.L.input_char >= 97 && ctx.L.input_char <= 102)) { ctx.L.unichar += HexValue(ctx.L.input_char) * num2; num++; num2 /= 16; if (num == 4) { ctx.L.string_buffer.Append(Convert.ToChar(ctx.L.unichar)); ctx.NextState = ctx.StateStack; return true; } continue; } return false; } return true; } private static bool State23(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { switch (ctx.L.input_char) { case 39: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 24; return true; case 92: ctx.StateStack = 23; ctx.NextState = 21; return true; } ctx.L.string_buffer.Append((char)ctx.L.input_char); } return true; } private static bool State24(LovenseFsmContent ctx) { ctx.L.GetChar(); int num = ctx.L.input_char; int num2 = num; if (num2 == 39) { ctx.L.input_char = 34; ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State25(LovenseFsmContent ctx) { ctx.L.GetChar(); switch (ctx.L.input_char) { case 42: ctx.NextState = 27; return true; case 47: ctx.NextState = 26; return true; default: return false; } } private static bool State26(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 10) { ctx.NextState = 1; return true; } } return true; } private static bool State27(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 42) { ctx.NextState = 28; return true; } } return true; } private static bool State28(LovenseFsmContent ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 42) { continue; } if (ctx.L.input_char == 47) { ctx.NextState = 1; return true; } ctx.NextState = 27; return true; } return true; } private bool GetChar() { if ((input_char = NextChar()) != -1) { return true; } end_of_input = true; return false; } private int NextChar() { if (input_buffer != 0) { int result = input_buffer; input_buffer = 0; return result; } return reader.Read(); } public bool NextToken() { fsm_context.Return = false; while (true) { StateHandler stateHandler = fsm_handler_table[state - 1]; if (!stateHandler(fsm_context)) { throw new LovenseException(input_char); } if (end_of_input) { return false; } if (fsm_context.Return) { break; } state = fsm_context.NextState; } string_value = string_buffer.ToString(); string_buffer.Remove(0, string_buffer.Length); token = fsm_return_table[state - 1]; if (token == 65542) { token = input_char; } state = fsm_context.NextState; return true; } private void UngetChar() { input_buffer = input_char; } } public class LovenseMW : LovenseJW, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary { 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 LovenseJt GetJsonType() { return LovenseJt.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(LovenseJt type) { } public void SetLong(long val) { } public void SetString(string val) { } public string ToJson() { return ""; } public void ToJson(LovenseWr 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 LovenseToken { None = 65536, Number, True, False, Null, CharSeq, Char, Text, Object, ObjectPrime, Pair, PairRest, Array, ArrayPrime, Value, ValueRest, String, End, Epsilon } internal enum Condition { InArray, InObject, NotAProperty, Property, Value } internal class LovenseWrC { public int Count; public bool InArray; public bool InObject; public bool ExpectingValue; public int Padding; } public class LovenseWr { private static readonly NumberFormatInfo number_format; private LovenseWrC context; private Stack<LovenseWrC> 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 bool lower_case_properties; 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; } } public bool LowerCaseProperties { get { return lower_case_properties; } set { lower_case_properties = value; } } static LovenseWr() { number_format = NumberFormatInfo.InvariantInfo; } public LovenseWr() { inst_string_builder = new StringBuilder(); writer = new StringWriter(inst_string_builder); Init(); } public LovenseWr(StringBuilder sb) : this(new StringWriter(sb)) { } public LovenseWr(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 LovenseException("A complete JSON symbol has already been written"); } switch (cond) { case Condition.InArray: if (!context.InArray) { throw new LovenseException("Can't close an array here"); } break; case Condition.InObject: if (!context.InObject || context.ExpectingValue) { throw new LovenseException("Can't close an object here"); } break; case Condition.NotAProperty: if (context.InObject && !context.ExpectingValue) { throw new LovenseException("Expected a property"); } break; case Condition.Property: if (!context.InObject || context.ExpectingValue) { throw new LovenseException("Can't add a property here"); } break; case Condition.Value: if (!context.InArray && (!context.InObject || !context.ExpectingValue)) { throw new LovenseException("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; lower_case_properties = false; ctx_stack = new Stack<LovenseWrC>(); context = new LovenseWrC(); ctx_stack.Push(context); } private static void IntToHex(int n, char[] hex) { for (int i = 0; i < 4; i++) { int num = n % 16; if (num < 10) { hex[3 - i] = (char)(48 + num); } else { hex[3 - i] = (char)(65 + (num - 10)); } n >>= 4; } } private void Indent() { if (pretty_print) { indentation += indent_value; } } private void Put(string str) { if (pretty_print && !context.ExpectingValue) { for (int i = 0; i < indentation; i++) { writer.Write(' '); } } writer.Write(str); } private void PutNewline() { PutNewline(add_comma: true); } private void PutNewline(bool add_comma) { if (add_comma && !context.ExpectingValue && context.Count > 1) { writer.Write(','); } if (pretty_print && !context.ExpectingValue) { writer.Write(Environment.NewLine); } } private void PutString(string str) { Put(string.Empty); writer.Write('"'); int length = str.Length; for (int i = 0; i < length; i++) { switch (str[i]) { case '\n': writer.Write("\\n"); continue; case '\r': writer.Write("\\r"); continue; case '\t': writer.Write("\\t"); continue; case '"': case '\\': writer.Write('\\'); writer.Write(str[i]); continue; case '\f': writer.Write("\\f"); continue; case '\b': writer.Write("\\b"); continue; } if (str[i] >= ' ' && str[i] <= '~') { writer.Write(str[i]); continue; } IntToHex(str[i], hex_seq); writer.Write("\\u"); writer.Write(hex_seq); } writer.Write('"'); } private void Unindent() { if (pretty_print) { indentation -= indent_value; } } public override string ToString() { if (inst_string_builder == null) { return string.Empty; } return inst_string_builder.ToString(); } public void Reset() { has_reached_end = false; ctx_stack.Clear(); context = new LovenseWrC(); ctx_stack.Push(context); if (inst_string_builder != null) { inst_string_builder.Remove(0, inst_string_builder.Length); } } public void Write(bool boolean) { DoValidation(Condition.Value); PutNewline(); Put(boolean ? "true" : "false"); context.ExpectingValue = false; } public void Write(decimal number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(double number) { DoValidation(Condition.Value); PutNewline(); string text = Convert.ToString(number, number_format); Put(text); if (text.IndexOf('.') == -1 && text.IndexOf('E') == -1) { writer.Write(".0"); } context.ExpectingValue = false; } public void Write(float number) { DoValidation(Condition.Value); PutNewline(); string str = Convert.ToString(number, number_format); Put(str); context.ExpectingValue = false; } public void Write(int number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(long number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(string str) { DoValidation(Condition.Value); PutNewline(); if (str == null) { Put("null"); } else { PutString(str); } context.ExpectingValue = false; } public void Write(ulong number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void WriteArrayEnd() { DoValidation(Condition.InArray); PutNewline(add_comma: false); ctx_stack.Pop(); if (ctx_stack.Count == 1) { has_reached_end = true; } else { context = ctx_stack.Peek(); context.ExpectingValue = false; } Unindent(); Put("]"); } public void WriteArrayStart() { DoValidation(Condition.NotAProperty); PutNewline(); Put("["); context = new LovenseWrC(); context.InArray = true; ctx_stack.Push(context); Indent(); } public void WriteObjectEnd() { DoValidation(Condition.InObject); PutNewline(add_comma: false); ctx_stack.Pop(); if (ctx_stack.Count == 1) { has_reached_end = true; } else { context = ctx_stack.Peek(); context.ExpectingValue = false; } Unindent(); Put("}"); } public void WriteObjectStart() { DoValidation(Condition.NotAProperty); PutNewline(); Put("{"); context = new LovenseWrC(); context.InObject = true; ctx_stack.Push(context); Indent(); } public void WritePropertyName(string property_name) { DoValidation(Condition.Property); PutNewline(); string text = ((property_name == null || !lower_case_properties) ? property_name : property_name.ToLowerInvariant()); PutString(text); if (pretty_print) { if (text.Length > context.Padding) { context.Padding = text.Length; } for (int num = context.Padding - text.Length; num >= 0; num--) { writer.Write(' '); } writer.Write(": "); } else { writer.Write(':'); } context.ExpectingValue = true; } } public class LovenseForUnity : MonoBehaviour { public struct DelayedQueueItem { public float time; public Action action; } private static LovenseForUnity _current; public static int maxThreads = 8; private static int numThreads; private int _count; private static bool initialized; private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); private List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>(); private List<Action> _actions = new List<Action>(); private List<Action> _currentActions = new List<Action>(); public static LovenseForUnity Current { get { Initialize(); return _current; } } private void Awake() { if ((Object)(object)_current == (Object)null) { _current = this; } else { Object.Destroy((Object)(object)((Component)this).gameObject); } initialized = true; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private static void Initialize() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if (!initialized && Application.isPlaying) { initialized = true; GameObject val = new GameObject("LovenseUpdate"); _current = val.AddComponent<LovenseForUnity>(); } } public static void QueueOnMainThread(Action action) { QueueOnMainThread(action, 0f); } public static void QueueOnMainThread(Action action, float time) { if (time != 0f) { lock (Current._delayed) { Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action }); return; } } lock (Current._actions) { Current._actions.Add(action); } } public static Thread RunAsync(Action a) { Initialize(); while (numThreads >= maxThreads) { Thread.Sleep(1); } Interlocked.Increment(ref numThreads); ThreadPool.QueueUserWorkItem(RunAction, a); return null; } private static void RunAction(object action) { try { ((Action)action)(); } catch { } finally { Interlocked.Decrement(ref numThreads); } } private void OnDisable() { if ((Object)(object)_current == (Object)(object)this) { _current = null; } } private void Update() { lock (_actions) { _currentActions.Clear(); _currentActions.AddRange(_actions); _actions.Clear(); } foreach (Action currentAction in _currentActions) { currentAction(); } lock (_delayed) { _currentDelayed.Clear(); _currentDelayed.AddRange(_delayed.Where((DelayedQueueItem d) => d.time <= Time.time)); foreach (DelayedQueueItem item in _currentDelayed) { _delayed.Remove(item); } } foreach (DelayedQueueItem item2 in _currentDelayed) { item2.action(); } } } } namespace Lovense.UnityKit.Remote { public class LovenseRemote : MonoBehaviour { private class CustomCertificateHandler : CertificateHandler { protected override bool ValidateCertificate(byte[] certificateData) { return true; } } private class ToyRawData { public string toy { get; set; } public ToyRawData() { toy = null; } } [Serializable] private class AllLovenseToys { public string toys { get; set; } public Dictionary<string, LovenseRemoteToy> allToys { get; set; } public string platform { get; set; } public string appType { get; set; } public string gameAppId { get; set; } } [Serializable] private class AllLovenseToysResult { public int code { get; set; } public AllLovenseToys data { get; set; } public string type { get; set; } } [Serializable] private class LovenseToysNameResult { public int code { get; set; } public List<string> data { get; set; } public string type { get; set; } } [Serializable] private class SearchResult { public int code { get; set; } public string message { get; set; } public List<RemoteAppData> data { get; set; } public SearchResult() { code = 0; message = ""; data = null; } } private class LovenseRemoteToy1 { public string domain; public int port; public string id; public int status; public string version; public string name; public int battery; public string nickName; public bool isHttps; public string platform; } private class SupportClasses { public string info { get; set; } public string version { get; set; } public SupportClasses() { info = ""; version = "1.31"; } } private class MyClass { public List<string> symbol { get; set; } public string type { get; set; } public SupportCommand func { get; set; } public MyClass() { symbol = new List<string>(); type = ""; func = new SupportCommand(); } } private class SupportCommand { public bool r { get; set; } public bool p { get; set; } public bool v { get; set; } public bool v1 { get; set; } public bool v2 { get; set; } public bool v3 { get; set; } public bool t { get; set; } public bool f { get; set; } public bool s { get; set; } public bool d { get; set; } public bool pos { get; set; } public bool o { get; set; } public SupportCommand() { r = false; p = false; v = false; v1 = false; v2 = false; v3 = false; t = false; f = false; s = false; d = false; pos = false; o = false; } } [Serializable] public class OnGetToysEvent : UnityEvent<List<LovenseRemoteToy>> { } public class OnGetToysErrorEvent : UnityEvent<string> { } public class OnGetAppErrorEvent : UnityEvent<string> { } public class OnControlToysEvent : UnityEvent<string, ControlToysResult> { } public class OnLocalAppGetEvent : UnityEvent<List<RemoteAppData>> { } public class OnPatternSyncTimeEvent : UnityEvent<float> { } public class OnPatternV2Event : UnityEvent<PatternV2_REQ_TYPE, ControlToysResult> { } [Serializable] private class TypeInfo { public string type { get; set; } public TypeInfo() { type = ""; } } private class ToyStatus { public string type { get; set; } public string toyId { get; set; } public EventConnectStatus data { get; set; } public ToyStatus() { type = ""; toyId = ""; } } private class EventConnectStatus { public bool connected { get; set; } public EventConnectStatus() { connected = false; } } private class ButtonEvent { public string type { get; set; } public string toyId { get; set; } public ButtonIndex data { get; set; } public ButtonEvent() { type = ""; toyId = ""; } } private class ButtonIndex { public int index { get; set; } public ButtonIndex() { index = 0; } } private class FunctionEvent { public FunctionVal data; public string type { get; set; } public string toyId { get; set; } public FunctionEvent() { type = ""; toyId = ""; } } private class FunctionVal { public string function { get; set; } public int value { get; set; } public int index { get; set; } public FunctionVal() { function = ""; value = 0; index = 0; } } private class ShakeEvent { public string type { get; set; } public string toyId { get; set; } public ShakeEvent() { type = ""; toyId = ""; } } private class ShakeChanged { public string type { get; set; } public string toyId { get; set; } public ShakeChangedValue data { get; set; } public ShakeChanged() { type = ""; toyId = ""; } } private class ShakeChangedValue { public float value { get; set; } public ShakeChangedValue() { value = 0f; } } private class DepthEvent { public string type { get; set; } public string toyId { get; set; } public DepthChangeValue data { get; set; } public DepthEvent() { type = ""; toyId = ""; } } private class DepthChangeValue { public int value { get; set; } public DepthChangeValue() { value = 0; } } public class EventOfGetToys : UnityEvent<string, List<EventToy>> { } public class EventOfToyStatus : UnityEvent<string, string, bool> { } public class EventOfButton : UnityEvent<string, string, int, ButtonActionType> { } [Serializable] public class EventOfFunction : UnityEvent<string, string, FunctionValue> { } public class EventOfShakeFrequencyChanged : UnityEvent<string, string, float> { } public class EventOfEveryShake : UnityEvent<string, string> { } public class EventOfApi : UnityEvent<string, EventApiType> { } private static LovenseRemote Instance; private static string contentType = "application/json"; public static OnGetToysEvent onGetToysEvent = new OnGetToysEvent(); public static OnGetAppErrorEvent onGetAppsErrorEvent = new OnGetAppErrorEvent(); public static OnGetToysErrorEvent onGetToysErrorEvent = new OnGetToysErrorEvent(); public static OnControlToysEvent onControlToysEvent = new OnControlToysEvent(); public static OnLocalAppGetEvent onGetAppsEvent = new OnLocalAppGetEvent(); public static OnPatternV2Event onPatternV2Event = new OnPatternV2Event(); public static OnPatternSyncTimeEvent onPatternSyncTimeEvent = new OnPatternSyncTimeEvent(); public static Dictionary<string, List<LovenseCommandType>> LovenseSupportCommands = new Dictionary<string, List<LovenseCommandType>>(); private float lastRequestTime = 0f; private Dictionary<string, WebSocket> listenEventApiDic = new Dictionary<string, WebSocket>(); private Dictionary<string, Thread> eventApiThreads = new Dictionary<string, Thread>(); private List<string> hasAddListening = new List<string>(); private object lockAccessObj; public static EventOfGetToys eventOfGetToys = new EventOfGetToys(); public static EventOfToyStatus eventOfToyStatus = new EventOfToyStatus(); public static EventOfButton eventOfButton = new EventOfButton(); public static EventOfApi eventOfApi = new EventOfApi(); public static EventOfFunction eventOfFunction = new EventOfFunction(); public static EventOfShakeFrequencyChanged eventOfShakeFrequencyChanged = new EventOfShakeFrequencyChanged(); public static EventOfEveryShake eventOfEveryShake = new EventOfEveryShake(); [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void RemoteAwake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown string name = ((Object)LovenseForUnity.Current).name; if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("LovesenRemote"); Instance = val.AddComponent<LovenseRemote>(); Object.DontDestroyOnLoad((Object)(object)val.gameObject); } } private void Awake() { lockAccessObj = new object(); InitClass(); ((MonoBehaviour)this).StartCoroutine(getSupportText()); } private void InitClass() { SupportClasses supportClasses = new SupportClasses(); MyClass myClass = new MyClass(); SearchResult searchResult = new SearchResult(); AllLovenseToysResult allLovenseToysResult = new AllLovenseToysResult(); LovenseRemoteToy lovenseRemoteToy = new LovenseRemoteToy(); LovenseRemoteToy1 lovenseRemoteToy2 = new LovenseRemoteToy1(); ToyRawData toyRawData = new ToyRawData(); ControlToysResult controlToysResult = new ControlToysResult(); TypeInfo typeInfo = new TypeInfo(); EventToy eventToy = new EventToy(); ToyStatus toyStatus = new ToyStatus(); ButtonEvent buttonEvent = new ButtonEvent(); FunctionEvent functionEvent = new FunctionEvent(); ShakeEvent shakeEvent = new ShakeEvent(); ShakeChanged shakeChanged = new ShakeChanged(); DepthEvent depthEvent = new DepthEvent(); } public List<LovenseCommandType> GetSupportCommandsByName(string name) { if (LovenseSupportCommands.ContainsKey(name.ToLower())) { return LovenseSupportCommands[name.ToLower()]; } return new List<LovenseCommandType>(); } private IEnumerator getSupportText() { string text = ""; string filePath = Path.Combine(Application.streamingAssetsPath, "LovenseToySupportConfig.json"); UnityWebRequest www = UnityWebRequest.Get(filePath); yield return www.SendWebRequest(); while (!www.isDone) { } if (string.IsNullOrEmpty(www.error)) { text = www.downloadHandler.text; } else { Debug.LogError((object)("Failed to load config file: " + www.error)); } if (!(text != "")) { yield break; } SupportClasses ss = LovenseJsonUtils.ToObject<SupportClasses>(text); List<MyClass> cls = LovenseJsonUtils.ToObject<List<MyClass>>(ss.info); for (int i = 0; i < cls.Count; i++) { MyClass clss = cls[i]; List<LovenseCommandType> commandTypes = new List<LovenseCommandType>(); if (clss.func.f) { commandTypes.Add(LovenseCommandType.FINGERING); } if (clss.func.v) { commandTypes.Add(LovenseCommandType.VIBRATE); } if (clss.func.v1) { commandTypes.Add(LovenseCommandType.VIBRATE1); } if (clss.func.v2) { commandTypes.Add(LovenseCommandType.VIBRATE2); } if (clss.func.v3) { commandTypes.Add(LovenseCommandType.VIBRATE3); } if (clss.func.p) { commandTypes.Add(LovenseCommandType.PUMP); } if (clss.func.r) { commandTypes.Add(LovenseCommandType.ROTATE); } if (clss.func.t) { commandTypes.Add(LovenseCommandType.THRUSTRING); } if (clss.func.d) { commandTypes.Add(LovenseCommandType.DEPTH); } if (clss.func.pos) { commandTypes.Add(LovenseCommandType.POSITION); } if (clss.func.o) { commandTypes.Add(LovenseCommandType.OSCILLATE); } if (!LovenseSupportCommands.ContainsKey(clss.type.ToLower())) { LovenseSupportCommands.Add(clss.type.ToLower(), commandTypes); } foreach (string c in clss.symbol) { if (!LovenseSupportCommands.ContainsKey(c.ToLower())) { LovenseSupportCommands.Add(c.ToLower(), commandTypes); } } } } public static LovenseRemote GetInstance() { if ((Object)(object)Instance == (Object)null) { Instance = new LovenseRemote(); } return Instance; } public void SearchRemoteApp(int timeout = 5) { UnityWebRequest val = UnityWebRequest.PostWwwForm("https://api.lovense-api.com/api/lan/v2/app", ""); val.timeout = timeout; val.certificateHandler = (CertificateHandler)(object)new CustomCertificateHandler(); ((AsyncOperation)val.SendWebRequest()).completed += OnSearchCompleted; } private void OnSearchCompleted(AsyncOperation asyncOperation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 UnityWebRequest webRequest = ((UnityWebRequestAsyncOperation)asyncOperation).webRequest; if ((int)webRequest.result == 3 || (int)webRequest.result == 2) { ((UnityEvent<string>)onGetAppsErrorEvent).Invoke(webRequest.error); } else { try { string text = webRequest.downloadHandler.text; string pattern = "\"fVersion\"\\s*:\\s*null"; Regex regex = new Regex(pattern); text = regex.Replace(text, "\"fVersion\":0"); List<RemoteAppData> datas = new List<RemoteAppData>(); SearchResult searchResult = LovenseJsonUtils.ToObject<SearchResult>(text); if (searchResult.data != null) { foreach (RemoteAppData datum in searchResult.data) { if (datum.appType.ToLower() == "remote") { datas.Add(datum); } LovenseForUnity.QueueOnMainThread(delegate { ((UnityEvent<List<RemoteAppData>>)onGetAppsEvent).Invoke(datas); }); } } else { LovenseForUnity.QueueOnMainThread(delegate { ((UnityEvent<List<RemoteAppData>>)onGetAppsEvent).Invoke(new List<RemoteAppData>()); }); } } catch (Exception) { LovenseForUnity.QueueOnMainThread(delegate { ((UnityEvent<List<RemoteAppData>>)onGetAppsEvent).Invoke(new List<RemoteAppData>()); }); } } webRequest.Dispose(); } public void GetToys(string domain, int port, bool isUseHttps = true, int timeout = 5) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown Dictionary<string, object> dictionary = new Dictionary<string, object>(); dictionary.Add("command", "GetToys"); string s = LovenseJsonUtils.ToJson(dictionary); string text = ""; text = (isUseHttps ? $"https://{domain}:{port}/command" : $"http://{domain}:{port}/command"); UnityWebRequest val = UnityWebRequest.PostWwwForm(text, ""); val.timeout = timeout; byte[] bytes = Encoding.UTF8.GetBytes(s); val.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes); val.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); val.certificateHandler = (CertificateHandler)(object)new CustomCertificateHandler(); val.SetRequestHeader("Content-Type", contentType); ((AsyncOperation)val.SendWebRequest()).completed += OnGetToysCompleted; } private void OnGetToysCompleted(AsyncOperation asyncOperation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Invalid comparison between Unknown and I4 //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Invalid comparison between Unknown and I4 UnityWebRequest webRequest = ((UnityWebRequestAsyncOperation)asyncOperation).webRequest; string url = webRequest.url; string scheme = webRequest.uri.Scheme; bool isHttps = false; if (scheme.Equals("http", StringComparison.OrdinalIgnoreCase)) { isHttps = false; } else if (scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) { isHttps = true; } Regex regex = new Regex("^(?:https?://)?(?<domain>[^:/\\s]+)(?::(?<port>\\d+))?", RegexOptions.IgnoreCase); Match match = regex.Match(url); string domain = ""; string value = ""; if (match.Success) { domain = match.Groups["domain"].Value; value = match.Groups["port"].Value; } if ((int)webRequest.result == 3 || (int)webRequest.result == 2) { string error = ((webRequest.error == null) ? "" : webRequest.error); LovenseForUnity.QueueOnMainThread(delegate { ((UnityEvent<string>)onGetToysErrorEvent).Invoke(error); }); } else { string text = webRequest.downloadHandler.text; string pattern = ":null"; Regex regex2 = new Regex(pattern); text = regex2.Replace(text, ":0"); try { AllLovenseToysResult allLovenseToysResult = LovenseJsonUtils.ToObject<AllLovenseToysResult>(text); Dictionary<string, LovenseRemoteToy1> dictionary = null; try { allLovenseToysResult.data.allToys = LovenseJsonUtils.ToObject<Dictionary<string, LovenseRemoteToy>>(allLovenseToysResult.data.toys); } catch (Exception) { dictionary = LovenseJsonUtils.ToObject<Dictionary<string, LovenseRemoteToy1>>(allLovenseToysResult.data.toys); } if (allLovenseToysResult.data.appType == "remote") { if (dictionary != null) { List<LovenseRemoteToy> toys2 = new List<LovenseRemoteToy>(); foreach (KeyValuePair<string, LovenseRemoteToy1> item in dictionary) {