Decompiled source of DiscordRP v1.0.1

plugins/DiscordRP.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using DiscordRP.Core;
using DiscordRPC;
using DiscordRPC.Events;
using DiscordRPC.Message;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[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: AssemblyCompany("DiscordRP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+727e94a82ade1f2ea71d0c2a41837bb821131287")]
[assembly: AssemblyProduct("DiscordRP")]
[assembly: AssemblyTitle("DiscordRP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Discord
{
	public class ActivityManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ActivityJoinHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)] string secret);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ActivitySpectateHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)] string secret);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ActivityJoinRequestHandler(IntPtr ptr, ref User user);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ActivityInviteHandler(IntPtr ptr, ActivityActionType type, ref User user, ref Activity activity);

			internal ActivityJoinHandler OnActivityJoin;

			internal ActivitySpectateHandler OnActivitySpectate;

			internal ActivityJoinRequestHandler OnActivityJoinRequest;

			internal ActivityInviteHandler OnActivityInvite;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result RegisterCommandMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string command);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result RegisterSteamMethod(IntPtr methodsPtr, uint steamId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateActivityCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateActivityMethod(IntPtr methodsPtr, ref Activity activity, IntPtr callbackData, UpdateActivityCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ClearActivityCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ClearActivityMethod(IntPtr methodsPtr, IntPtr callbackData, ClearActivityCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendRequestReplyCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendRequestReplyMethod(IntPtr methodsPtr, long userId, ActivityJoinRequestReply reply, IntPtr callbackData, SendRequestReplyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendInviteCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendInviteMethod(IntPtr methodsPtr, long userId, ActivityActionType type, [MarshalAs(UnmanagedType.LPStr)] string content, IntPtr callbackData, SendInviteCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void AcceptInviteCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void AcceptInviteMethod(IntPtr methodsPtr, long userId, IntPtr callbackData, AcceptInviteCallback callback);

			internal RegisterCommandMethod RegisterCommand;

			internal RegisterSteamMethod RegisterSteam;

			internal UpdateActivityMethod UpdateActivity;

			internal ClearActivityMethod ClearActivity;

			internal SendRequestReplyMethod SendRequestReply;

			internal SendInviteMethod SendInvite;

			internal AcceptInviteMethod AcceptInvite;
		}

		public delegate void UpdateActivityHandler(Result result);

		public delegate void ClearActivityHandler(Result result);

		public delegate void SendRequestReplyHandler(Result result);

		public delegate void SendInviteHandler(Result result);

		public delegate void AcceptInviteHandler(Result result);

		public delegate void ActivityJoinHandler(string secret);

		public delegate void ActivitySpectateHandler(string secret);

		public delegate void ActivityJoinRequestHandler(ref User user);

		public delegate void ActivityInviteHandler(ActivityActionType type, ref User user, ref Activity activity);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event ActivityJoinHandler OnActivityJoin;

		public event ActivitySpectateHandler OnActivitySpectate;

		public event ActivityJoinRequestHandler OnActivityJoinRequest;

		public event ActivityInviteHandler OnActivityInvite;

		public void RegisterCommand()
		{
			RegisterCommand(null);
		}

		internal ActivityManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnActivityJoin = OnActivityJoinImpl;
			events.OnActivitySpectate = OnActivitySpectateImpl;
			events.OnActivityJoinRequest = OnActivityJoinRequestImpl;
			events.OnActivityInvite = OnActivityInviteImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public void RegisterCommand(string command)
		{
			Result result = Methods.RegisterCommand(MethodsPtr, command);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void RegisterSteam(uint steamId)
		{
			Result result = Methods.RegisterSteam(MethodsPtr, steamId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		[MonoPInvokeCallback]
		private static void UpdateActivityCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			UpdateActivityHandler updateActivityHandler = (UpdateActivityHandler)gCHandle.Target;
			gCHandle.Free();
			updateActivityHandler(result);
		}

		public void UpdateActivity(Activity activity, UpdateActivityHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.UpdateActivity(MethodsPtr, ref activity, GCHandle.ToIntPtr(value), UpdateActivityCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void ClearActivityCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			ClearActivityHandler clearActivityHandler = (ClearActivityHandler)gCHandle.Target;
			gCHandle.Free();
			clearActivityHandler(result);
		}

		public void ClearActivity(ClearActivityHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.ClearActivity(MethodsPtr, GCHandle.ToIntPtr(value), ClearActivityCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void SendRequestReplyCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SendRequestReplyHandler sendRequestReplyHandler = (SendRequestReplyHandler)gCHandle.Target;
			gCHandle.Free();
			sendRequestReplyHandler(result);
		}

		public void SendRequestReply(long userId, ActivityJoinRequestReply reply, SendRequestReplyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SendRequestReply(MethodsPtr, userId, reply, GCHandle.ToIntPtr(value), SendRequestReplyCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void SendInviteCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SendInviteHandler sendInviteHandler = (SendInviteHandler)gCHandle.Target;
			gCHandle.Free();
			sendInviteHandler(result);
		}

		public void SendInvite(long userId, ActivityActionType type, string content, SendInviteHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SendInvite(MethodsPtr, userId, type, content, GCHandle.ToIntPtr(value), SendInviteCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void AcceptInviteCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			AcceptInviteHandler acceptInviteHandler = (AcceptInviteHandler)gCHandle.Target;
			gCHandle.Free();
			acceptInviteHandler(result);
		}

		public void AcceptInvite(long userId, AcceptInviteHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.AcceptInvite(MethodsPtr, userId, GCHandle.ToIntPtr(value), AcceptInviteCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void OnActivityJoinImpl(IntPtr ptr, string secret)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.ActivityManagerInstance.OnActivityJoin != null)
			{
				discord.ActivityManagerInstance.OnActivityJoin(secret);
			}
		}

		[MonoPInvokeCallback]
		private static void OnActivitySpectateImpl(IntPtr ptr, string secret)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.ActivityManagerInstance.OnActivitySpectate != null)
			{
				discord.ActivityManagerInstance.OnActivitySpectate(secret);
			}
		}

		[MonoPInvokeCallback]
		private static void OnActivityJoinRequestImpl(IntPtr ptr, ref User user)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.ActivityManagerInstance.OnActivityJoinRequest != null)
			{
				discord.ActivityManagerInstance.OnActivityJoinRequest(ref user);
			}
		}

		[MonoPInvokeCallback]
		private static void OnActivityInviteImpl(IntPtr ptr, ActivityActionType type, ref User user, ref Activity activity)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.ActivityManagerInstance.OnActivityInvite != null)
			{
				discord.ActivityManagerInstance.OnActivityInvite(type, ref user, ref activity);
			}
		}
	}
	internal static class Constants
	{
		public const string DllName = "discord_game_sdk";
	}
	public enum Result
	{
		Ok,
		ServiceUnavailable,
		InvalidVersion,
		LockFailed,
		InternalError,
		InvalidPayload,
		InvalidCommand,
		InvalidPermissions,
		NotFetched,
		NotFound,
		Conflict,
		InvalidSecret,
		InvalidJoinSecret,
		NoEligibleActivity,
		InvalidInvite,
		NotAuthenticated,
		InvalidAccessToken,
		ApplicationMismatch,
		InvalidDataUrl,
		InvalidBase64,
		NotFiltered,
		LobbyFull,
		InvalidLobbySecret,
		InvalidFilename,
		InvalidFileSize,
		InvalidEntitlement,
		NotInstalled,
		NotRunning,
		InsufficientBuffer,
		PurchaseCanceled,
		InvalidGuild,
		InvalidEvent,
		InvalidChannel,
		InvalidOrigin,
		RateLimited,
		OAuth2Error,
		SelectChannelTimeout,
		GetGuildTimeout,
		SelectVoiceForceRequired,
		CaptureShortcutAlreadyListening,
		UnauthorizedForAchievement,
		InvalidGiftCode,
		PurchaseError,
		TransactionAborted,
		DrawingInitFailed
	}
	public enum CreateFlags
	{
		Default,
		NoRequireDiscord
	}
	public enum LogLevel
	{
		Error = 1,
		Warn,
		Info,
		Debug
	}
	public enum UserFlag
	{
		Partner = 2,
		HypeSquadEvents = 4,
		HypeSquadHouse1 = 0x40,
		HypeSquadHouse2 = 0x80,
		HypeSquadHouse3 = 0x100
	}
	public enum PremiumType
	{
		None,
		Tier1,
		Tier2
	}
	public enum ImageType
	{
		User
	}
	public enum ActivityPartyPrivacy
	{
		Private,
		Public
	}
	public enum ActivityType
	{
		Playing,
		Streaming,
		Listening,
		Watching
	}
	public enum ActivityActionType
	{
		Join = 1,
		Spectate
	}
	public enum ActivitySupportedPlatformFlags
	{
		Desktop = 1,
		Android = 2,
		iOS = 4
	}
	public enum ActivityJoinRequestReply
	{
		No,
		Yes,
		Ignore
	}
	public enum Status
	{
		Offline,
		Online,
		Idle,
		DoNotDisturb
	}
	public enum RelationshipType
	{
		None,
		Friend,
		Blocked,
		PendingIncoming,
		PendingOutgoing,
		Implicit
	}
	public enum LobbyType
	{
		Private = 1,
		Public
	}
	public enum LobbySearchComparison
	{
		LessThanOrEqual = -2,
		LessThan,
		Equal,
		GreaterThan,
		GreaterThanOrEqual,
		NotEqual
	}
	public enum LobbySearchCast
	{
		String = 1,
		Number
	}
	public enum LobbySearchDistance
	{
		Local,
		Default,
		Extended,
		Global
	}
	public enum KeyVariant
	{
		Normal,
		Right,
		Left
	}
	public enum MouseButton
	{
		Left,
		Middle,
		Right
	}
	public enum EntitlementType
	{
		Purchase = 1,
		PremiumSubscription,
		DeveloperGift,
		TestModePurchase,
		FreePurchase,
		UserGift,
		PremiumPurchase
	}
	public enum SkuType
	{
		Application = 1,
		DLC,
		Consumable,
		Bundle
	}
	public enum InputModeType
	{
		VoiceActivity,
		PushToTalk
	}
	public struct User
	{
		public long Id;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
		public string Username;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
		public string Discriminator;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Avatar;

		public bool Bot;
	}
	public struct OAuth2Token
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string AccessToken;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
		public string Scopes;

		public long Expires;
	}
	public struct ImageHandle
	{
		public ImageType Type;

		public long Id;

		public uint Size;

		public static ImageHandle User(long id)
		{
			return User(id, 128u);
		}

		public static ImageHandle User(long id, uint size)
		{
			ImageHandle result = default(ImageHandle);
			result.Type = ImageType.User;
			result.Id = id;
			result.Size = size;
			return result;
		}
	}
	public struct ImageDimensions
	{
		public uint Width;

		public uint Height;
	}
	public struct ActivityTimestamps
	{
		public long Start;

		public long End;
	}
	public struct ActivityAssets
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string LargeImage;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string LargeText;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string SmallImage;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string SmallText;
	}
	public struct PartySize
	{
		public int CurrentSize;

		public int MaxSize;
	}
	public struct ActivityParty
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Id;

		public PartySize Size;

		public ActivityPartyPrivacy Privacy;
	}
	public struct ActivitySecrets
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Match;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Join;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Spectate;
	}
	public struct Activity
	{
		public ActivityType Type;

		public long ApplicationId;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Name;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string State;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Details;

		public ActivityTimestamps Timestamps;

		public ActivityAssets Assets;

		public ActivityParty Party;

		public ActivitySecrets Secrets;

		public bool Instance;

		public uint SupportedPlatforms;
	}
	public struct Presence
	{
		public Status Status;

		public Activity Activity;
	}
	public struct Relationship
	{
		public RelationshipType Type;

		public User User;

		public Presence Presence;
	}
	public struct Lobby
	{
		public long Id;

		public LobbyType Type;

		public long OwnerId;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string Secret;

		public uint Capacity;

		public bool Locked;
	}
	public struct ImeUnderline
	{
		public int From;

		public int To;

		public uint Color;

		public uint BackgroundColor;

		public bool Thick;
	}
	public struct Rect
	{
		public int Left;

		public int Top;

		public int Right;

		public int Bottom;
	}
	public struct FileStat
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
		public string Filename;

		public ulong Size;

		public ulong LastModified;
	}
	public struct Entitlement
	{
		public long Id;

		public EntitlementType Type;

		public long SkuId;
	}
	public struct SkuPrice
	{
		public uint Amount;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
		public string Currency;
	}
	public struct Sku
	{
		public long Id;

		public SkuType Type;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
		public string Name;

		public SkuPrice Price;
	}
	public struct InputMode
	{
		public InputModeType Type;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
		public string Shortcut;
	}
	public struct UserAchievement
	{
		public long UserId;

		public long AchievementId;

		public byte PercentComplete;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
		public string UnlockedAt;
	}
	public struct LobbyTransaction
	{
		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetTypeMethod(IntPtr methodsPtr, LobbyType type);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetOwnerMethod(IntPtr methodsPtr, long ownerId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetCapacityMethod(IntPtr methodsPtr, uint capacity);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key, [MarshalAs(UnmanagedType.LPStr)] string value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result DeleteMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetLockedMethod(IntPtr methodsPtr, bool locked);

			internal SetTypeMethod SetType;

			internal SetOwnerMethod SetOwner;

			internal SetCapacityMethod SetCapacity;

			internal SetMetadataMethod SetMetadata;

			internal DeleteMetadataMethod DeleteMetadata;

			internal SetLockedMethod SetLocked;
		}

		internal IntPtr MethodsPtr;

		internal object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public void SetType(LobbyType type)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetType(MethodsPtr, type);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void SetOwner(long ownerId)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetOwner(MethodsPtr, ownerId);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void SetCapacity(uint capacity)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetCapacity(MethodsPtr, capacity);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void SetMetadata(string key, string value)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetMetadata(MethodsPtr, key, value);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void DeleteMetadata(string key)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.DeleteMetadata(MethodsPtr, key);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void SetLocked(bool locked)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetLocked(MethodsPtr, locked);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}
	}
	public struct LobbyMemberTransaction
	{
		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SetMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key, [MarshalAs(UnmanagedType.LPStr)] string value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result DeleteMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key);

			internal SetMetadataMethod SetMetadata;

			internal DeleteMetadataMethod DeleteMetadata;
		}

		internal IntPtr MethodsPtr;

		internal object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public void SetMetadata(string key, string value)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.SetMetadata(MethodsPtr, key, value);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void DeleteMetadata(string key)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.DeleteMetadata(MethodsPtr, key);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}
	}
	public struct LobbySearchQuery
	{
		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result FilterMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key, LobbySearchComparison comparison, LobbySearchCast cast, [MarshalAs(UnmanagedType.LPStr)] string value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SortMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string key, LobbySearchCast cast, [MarshalAs(UnmanagedType.LPStr)] string value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result LimitMethod(IntPtr methodsPtr, uint limit);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result DistanceMethod(IntPtr methodsPtr, LobbySearchDistance distance);

			internal FilterMethod Filter;

			internal SortMethod Sort;

			internal LimitMethod Limit;

			internal DistanceMethod Distance;
		}

		internal IntPtr MethodsPtr;

		internal object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public void Filter(string key, LobbySearchComparison comparison, LobbySearchCast cast, string value)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.Filter(MethodsPtr, key, comparison, cast, value);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void Sort(string key, LobbySearchCast cast, string value)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.Sort(MethodsPtr, key, cast, value);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void Limit(uint limit)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.Limit(MethodsPtr, limit);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}

		public void Distance(LobbySearchDistance distance)
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Result result = Methods.Distance(MethodsPtr, distance);
				if (result != 0)
				{
					throw new ResultException(result);
				}
			}
		}
	}
	public class ResultException : Exception
	{
		public readonly Result Result;

		public ResultException(Result result)
			: base(result.ToString())
		{
		}
	}
	public class Discord : IDisposable
	{
		internal struct FFIEvents
		{
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DestroyHandler(IntPtr MethodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result RunCallbacksMethod(IntPtr methodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetLogHookCallback(IntPtr ptr, LogLevel level, [MarshalAs(UnmanagedType.LPStr)] string message);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetLogHookMethod(IntPtr methodsPtr, LogLevel minLevel, IntPtr callbackData, SetLogHookCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetApplicationManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetUserManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetImageManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetActivityManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetRelationshipManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetLobbyManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetNetworkManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetOverlayManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetStorageManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetStoreManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetVoiceManagerMethod(IntPtr discordPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate IntPtr GetAchievementManagerMethod(IntPtr discordPtr);

			internal DestroyHandler Destroy;

			internal RunCallbacksMethod RunCallbacks;

			internal SetLogHookMethod SetLogHook;

			internal GetApplicationManagerMethod GetApplicationManager;

			internal GetUserManagerMethod GetUserManager;

			internal GetImageManagerMethod GetImageManager;

			internal GetActivityManagerMethod GetActivityManager;

			internal GetRelationshipManagerMethod GetRelationshipManager;

			internal GetLobbyManagerMethod GetLobbyManager;

			internal GetNetworkManagerMethod GetNetworkManager;

			internal GetOverlayManagerMethod GetOverlayManager;

			internal GetStorageManagerMethod GetStorageManager;

			internal GetStoreManagerMethod GetStoreManager;

			internal GetVoiceManagerMethod GetVoiceManager;

			internal GetAchievementManagerMethod GetAchievementManager;
		}

		internal struct FFICreateParams
		{
			internal long ClientId;

			internal ulong Flags;

			internal IntPtr Events;

			internal IntPtr EventData;

			internal IntPtr ApplicationEvents;

			internal uint ApplicationVersion;

			internal IntPtr UserEvents;

			internal uint UserVersion;

			internal IntPtr ImageEvents;

			internal uint ImageVersion;

			internal IntPtr ActivityEvents;

			internal uint ActivityVersion;

			internal IntPtr RelationshipEvents;

			internal uint RelationshipVersion;

			internal IntPtr LobbyEvents;

			internal uint LobbyVersion;

			internal IntPtr NetworkEvents;

			internal uint NetworkVersion;

			internal IntPtr OverlayEvents;

			internal uint OverlayVersion;

			internal IntPtr StorageEvents;

			internal uint StorageVersion;

			internal IntPtr StoreEvents;

			internal uint StoreVersion;

			internal IntPtr VoiceEvents;

			internal uint VoiceVersion;

			internal IntPtr AchievementEvents;

			internal uint AchievementVersion;
		}

		public delegate void SetLogHookHandler(LogLevel level, string message);

		private GCHandle SelfHandle;

		private IntPtr EventsPtr;

		private FFIEvents Events;

		private IntPtr ApplicationEventsPtr;

		private ApplicationManager.FFIEvents ApplicationEvents;

		internal ApplicationManager ApplicationManagerInstance;

		private IntPtr UserEventsPtr;

		private UserManager.FFIEvents UserEvents;

		internal UserManager UserManagerInstance;

		private IntPtr ImageEventsPtr;

		private ImageManager.FFIEvents ImageEvents;

		internal ImageManager ImageManagerInstance;

		private IntPtr ActivityEventsPtr;

		private ActivityManager.FFIEvents ActivityEvents;

		internal ActivityManager ActivityManagerInstance;

		private IntPtr RelationshipEventsPtr;

		private RelationshipManager.FFIEvents RelationshipEvents;

		internal RelationshipManager RelationshipManagerInstance;

		private IntPtr LobbyEventsPtr;

		private LobbyManager.FFIEvents LobbyEvents;

		internal LobbyManager LobbyManagerInstance;

		private IntPtr NetworkEventsPtr;

		private NetworkManager.FFIEvents NetworkEvents;

		internal NetworkManager NetworkManagerInstance;

		private IntPtr OverlayEventsPtr;

		private OverlayManager.FFIEvents OverlayEvents;

		internal OverlayManager OverlayManagerInstance;

		private IntPtr StorageEventsPtr;

		private StorageManager.FFIEvents StorageEvents;

		internal StorageManager StorageManagerInstance;

		private IntPtr StoreEventsPtr;

		private StoreManager.FFIEvents StoreEvents;

		internal StoreManager StoreManagerInstance;

		private IntPtr VoiceEventsPtr;

		private VoiceManager.FFIEvents VoiceEvents;

		internal VoiceManager VoiceManagerInstance;

		private IntPtr AchievementEventsPtr;

		private AchievementManager.FFIEvents AchievementEvents;

		internal AchievementManager AchievementManagerInstance;

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private GCHandle? setLogHook;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		[DllImport("discord_game_sdk", ExactSpelling = true)]
		private static extern Result DiscordCreate(uint version, ref FFICreateParams createParams, out IntPtr manager);

		public Discord(long clientId, ulong flags)
		{
			FFICreateParams createParams = default(FFICreateParams);
			createParams.ClientId = clientId;
			createParams.Flags = flags;
			Events = default(FFIEvents);
			EventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Events));
			createParams.Events = EventsPtr;
			SelfHandle = GCHandle.Alloc(this);
			createParams.EventData = GCHandle.ToIntPtr(SelfHandle);
			ApplicationEvents = default(ApplicationManager.FFIEvents);
			ApplicationEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ApplicationEvents));
			createParams.ApplicationEvents = ApplicationEventsPtr;
			createParams.ApplicationVersion = 1u;
			UserEvents = default(UserManager.FFIEvents);
			UserEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(UserEvents));
			createParams.UserEvents = UserEventsPtr;
			createParams.UserVersion = 1u;
			ImageEvents = default(ImageManager.FFIEvents);
			ImageEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ImageEvents));
			createParams.ImageEvents = ImageEventsPtr;
			createParams.ImageVersion = 1u;
			ActivityEvents = default(ActivityManager.FFIEvents);
			ActivityEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ActivityEvents));
			createParams.ActivityEvents = ActivityEventsPtr;
			createParams.ActivityVersion = 1u;
			RelationshipEvents = default(RelationshipManager.FFIEvents);
			RelationshipEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(RelationshipEvents));
			createParams.RelationshipEvents = RelationshipEventsPtr;
			createParams.RelationshipVersion = 1u;
			LobbyEvents = default(LobbyManager.FFIEvents);
			LobbyEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(LobbyEvents));
			createParams.LobbyEvents = LobbyEventsPtr;
			createParams.LobbyVersion = 1u;
			NetworkEvents = default(NetworkManager.FFIEvents);
			NetworkEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(NetworkEvents));
			createParams.NetworkEvents = NetworkEventsPtr;
			createParams.NetworkVersion = 1u;
			OverlayEvents = default(OverlayManager.FFIEvents);
			OverlayEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(OverlayEvents));
			createParams.OverlayEvents = OverlayEventsPtr;
			createParams.OverlayVersion = 2u;
			StorageEvents = default(StorageManager.FFIEvents);
			StorageEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StorageEvents));
			createParams.StorageEvents = StorageEventsPtr;
			createParams.StorageVersion = 1u;
			StoreEvents = default(StoreManager.FFIEvents);
			StoreEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StoreEvents));
			createParams.StoreEvents = StoreEventsPtr;
			createParams.StoreVersion = 1u;
			VoiceEvents = default(VoiceManager.FFIEvents);
			VoiceEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(VoiceEvents));
			createParams.VoiceEvents = VoiceEventsPtr;
			createParams.VoiceVersion = 1u;
			AchievementEvents = default(AchievementManager.FFIEvents);
			AchievementEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(AchievementEvents));
			createParams.AchievementEvents = AchievementEventsPtr;
			createParams.AchievementVersion = 1u;
			InitEvents(EventsPtr, ref Events);
			Result result = DiscordCreate(3u, ref createParams, out MethodsPtr);
			if (result != 0)
			{
				Dispose();
				throw new ResultException(result);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public void Dispose()
		{
			if (MethodsPtr != IntPtr.Zero)
			{
				Methods.Destroy(MethodsPtr);
			}
			SelfHandle.Free();
			Marshal.FreeHGlobal(EventsPtr);
			Marshal.FreeHGlobal(ApplicationEventsPtr);
			Marshal.FreeHGlobal(UserEventsPtr);
			Marshal.FreeHGlobal(ImageEventsPtr);
			Marshal.FreeHGlobal(ActivityEventsPtr);
			Marshal.FreeHGlobal(RelationshipEventsPtr);
			Marshal.FreeHGlobal(LobbyEventsPtr);
			Marshal.FreeHGlobal(NetworkEventsPtr);
			Marshal.FreeHGlobal(OverlayEventsPtr);
			Marshal.FreeHGlobal(StorageEventsPtr);
			Marshal.FreeHGlobal(StoreEventsPtr);
			Marshal.FreeHGlobal(VoiceEventsPtr);
			Marshal.FreeHGlobal(AchievementEventsPtr);
			if (setLogHook.HasValue)
			{
				setLogHook.Value.Free();
			}
		}

		public void RunCallbacks()
		{
			Result result = Methods.RunCallbacks(MethodsPtr);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		[MonoPInvokeCallback]
		private static void SetLogHookCallbackImpl(IntPtr ptr, LogLevel level, string message)
		{
			SetLogHookHandler setLogHookHandler = (SetLogHookHandler)GCHandle.FromIntPtr(ptr).Target;
			setLogHookHandler(level, message);
		}

		public void SetLogHook(LogLevel minLevel, SetLogHookHandler callback)
		{
			if (setLogHook.HasValue)
			{
				setLogHook.Value.Free();
			}
			setLogHook = GCHandle.Alloc(callback);
			Methods.SetLogHook(MethodsPtr, minLevel, GCHandle.ToIntPtr(setLogHook.Value), SetLogHookCallbackImpl);
		}

		public ApplicationManager GetApplicationManager()
		{
			if (ApplicationManagerInstance == null)
			{
				ApplicationManagerInstance = new ApplicationManager(Methods.GetApplicationManager(MethodsPtr), ApplicationEventsPtr, ref ApplicationEvents);
			}
			return ApplicationManagerInstance;
		}

		public UserManager GetUserManager()
		{
			if (UserManagerInstance == null)
			{
				UserManagerInstance = new UserManager(Methods.GetUserManager(MethodsPtr), UserEventsPtr, ref UserEvents);
			}
			return UserManagerInstance;
		}

		public ImageManager GetImageManager()
		{
			if (ImageManagerInstance == null)
			{
				ImageManagerInstance = new ImageManager(Methods.GetImageManager(MethodsPtr), ImageEventsPtr, ref ImageEvents);
			}
			return ImageManagerInstance;
		}

		public ActivityManager GetActivityManager()
		{
			if (ActivityManagerInstance == null)
			{
				ActivityManagerInstance = new ActivityManager(Methods.GetActivityManager(MethodsPtr), ActivityEventsPtr, ref ActivityEvents);
			}
			return ActivityManagerInstance;
		}

		public RelationshipManager GetRelationshipManager()
		{
			if (RelationshipManagerInstance == null)
			{
				RelationshipManagerInstance = new RelationshipManager(Methods.GetRelationshipManager(MethodsPtr), RelationshipEventsPtr, ref RelationshipEvents);
			}
			return RelationshipManagerInstance;
		}

		public LobbyManager GetLobbyManager()
		{
			if (LobbyManagerInstance == null)
			{
				LobbyManagerInstance = new LobbyManager(Methods.GetLobbyManager(MethodsPtr), LobbyEventsPtr, ref LobbyEvents);
			}
			return LobbyManagerInstance;
		}

		public NetworkManager GetNetworkManager()
		{
			if (NetworkManagerInstance == null)
			{
				NetworkManagerInstance = new NetworkManager(Methods.GetNetworkManager(MethodsPtr), NetworkEventsPtr, ref NetworkEvents);
			}
			return NetworkManagerInstance;
		}

		public OverlayManager GetOverlayManager()
		{
			if (OverlayManagerInstance == null)
			{
				OverlayManagerInstance = new OverlayManager(Methods.GetOverlayManager(MethodsPtr), OverlayEventsPtr, ref OverlayEvents);
			}
			return OverlayManagerInstance;
		}

		public StorageManager GetStorageManager()
		{
			if (StorageManagerInstance == null)
			{
				StorageManagerInstance = new StorageManager(Methods.GetStorageManager(MethodsPtr), StorageEventsPtr, ref StorageEvents);
			}
			return StorageManagerInstance;
		}

		public StoreManager GetStoreManager()
		{
			if (StoreManagerInstance == null)
			{
				StoreManagerInstance = new StoreManager(Methods.GetStoreManager(MethodsPtr), StoreEventsPtr, ref StoreEvents);
			}
			return StoreManagerInstance;
		}

		public VoiceManager GetVoiceManager()
		{
			if (VoiceManagerInstance == null)
			{
				VoiceManagerInstance = new VoiceManager(Methods.GetVoiceManager(MethodsPtr), VoiceEventsPtr, ref VoiceEvents);
			}
			return VoiceManagerInstance;
		}

		public AchievementManager GetAchievementManager()
		{
			if (AchievementManagerInstance == null)
			{
				AchievementManagerInstance = new AchievementManager(Methods.GetAchievementManager(MethodsPtr), AchievementEventsPtr, ref AchievementEvents);
			}
			return AchievementManagerInstance;
		}
	}
	internal class MonoPInvokeCallbackAttribute : Attribute
	{
	}
	public class ApplicationManager
	{
		internal struct FFIEvents
		{
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ValidateOrExitCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ValidateOrExitMethod(IntPtr methodsPtr, IntPtr callbackData, ValidateOrExitCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetCurrentLocaleMethod(IntPtr methodsPtr, StringBuilder locale);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetCurrentBranchMethod(IntPtr methodsPtr, StringBuilder branch);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetOAuth2TokenCallback(IntPtr ptr, Result result, ref OAuth2Token oauth2Token);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetOAuth2TokenMethod(IntPtr methodsPtr, IntPtr callbackData, GetOAuth2TokenCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetTicketCallback(IntPtr ptr, Result result, [MarshalAs(UnmanagedType.LPStr)] ref string data);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetTicketMethod(IntPtr methodsPtr, IntPtr callbackData, GetTicketCallback callback);

			internal ValidateOrExitMethod ValidateOrExit;

			internal GetCurrentLocaleMethod GetCurrentLocale;

			internal GetCurrentBranchMethod GetCurrentBranch;

			internal GetOAuth2TokenMethod GetOAuth2Token;

			internal GetTicketMethod GetTicket;
		}

		public delegate void ValidateOrExitHandler(Result result);

		public delegate void GetOAuth2TokenHandler(Result result, ref OAuth2Token oauth2Token);

		public delegate void GetTicketHandler(Result result, ref string data);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		internal ApplicationManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		[MonoPInvokeCallback]
		private static void ValidateOrExitCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			ValidateOrExitHandler validateOrExitHandler = (ValidateOrExitHandler)gCHandle.Target;
			gCHandle.Free();
			validateOrExitHandler(result);
		}

		public void ValidateOrExit(ValidateOrExitHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.ValidateOrExit(MethodsPtr, GCHandle.ToIntPtr(value), ValidateOrExitCallbackImpl);
		}

		public string GetCurrentLocale()
		{
			StringBuilder stringBuilder = new StringBuilder(128);
			Methods.GetCurrentLocale(MethodsPtr, stringBuilder);
			return stringBuilder.ToString();
		}

		public string GetCurrentBranch()
		{
			StringBuilder stringBuilder = new StringBuilder(4096);
			Methods.GetCurrentBranch(MethodsPtr, stringBuilder);
			return stringBuilder.ToString();
		}

		[MonoPInvokeCallback]
		private static void GetOAuth2TokenCallbackImpl(IntPtr ptr, Result result, ref OAuth2Token oauth2Token)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			GetOAuth2TokenHandler getOAuth2TokenHandler = (GetOAuth2TokenHandler)gCHandle.Target;
			gCHandle.Free();
			getOAuth2TokenHandler(result, ref oauth2Token);
		}

		public void GetOAuth2Token(GetOAuth2TokenHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.GetOAuth2Token(MethodsPtr, GCHandle.ToIntPtr(value), GetOAuth2TokenCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void GetTicketCallbackImpl(IntPtr ptr, Result result, ref string data)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			GetTicketHandler getTicketHandler = (GetTicketHandler)gCHandle.Target;
			gCHandle.Free();
			getTicketHandler(result, ref data);
		}

		public void GetTicket(GetTicketHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.GetTicket(MethodsPtr, GCHandle.ToIntPtr(value), GetTicketCallbackImpl);
		}
	}
	public class UserManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void CurrentUserUpdateHandler(IntPtr ptr);

			internal CurrentUserUpdateHandler OnCurrentUserUpdate;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetCurrentUserMethod(IntPtr methodsPtr, ref User currentUser);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetUserCallback(IntPtr ptr, Result result, ref User user);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetUserMethod(IntPtr methodsPtr, long userId, IntPtr callbackData, GetUserCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetCurrentUserPremiumTypeMethod(IntPtr methodsPtr, ref PremiumType premiumType);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result CurrentUserHasFlagMethod(IntPtr methodsPtr, UserFlag flag, ref bool hasFlag);

			internal GetCurrentUserMethod GetCurrentUser;

			internal GetUserMethod GetUser;

			internal GetCurrentUserPremiumTypeMethod GetCurrentUserPremiumType;

			internal CurrentUserHasFlagMethod CurrentUserHasFlag;
		}

		public delegate void GetUserHandler(Result result, ref User user);

		public delegate void CurrentUserUpdateHandler();

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event CurrentUserUpdateHandler OnCurrentUserUpdate;

		internal UserManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnCurrentUserUpdate = OnCurrentUserUpdateImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public User GetCurrentUser()
		{
			User currentUser = default(User);
			Result result = Methods.GetCurrentUser(MethodsPtr, ref currentUser);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return currentUser;
		}

		[MonoPInvokeCallback]
		private static void GetUserCallbackImpl(IntPtr ptr, Result result, ref User user)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			GetUserHandler getUserHandler = (GetUserHandler)gCHandle.Target;
			gCHandle.Free();
			getUserHandler(result, ref user);
		}

		public void GetUser(long userId, GetUserHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.GetUser(MethodsPtr, userId, GCHandle.ToIntPtr(value), GetUserCallbackImpl);
		}

		public PremiumType GetCurrentUserPremiumType()
		{
			PremiumType premiumType = PremiumType.None;
			Result result = Methods.GetCurrentUserPremiumType(MethodsPtr, ref premiumType);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return premiumType;
		}

		public bool CurrentUserHasFlag(UserFlag flag)
		{
			bool hasFlag = false;
			Result result = Methods.CurrentUserHasFlag(MethodsPtr, flag, ref hasFlag);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return hasFlag;
		}

		[MonoPInvokeCallback]
		private static void OnCurrentUserUpdateImpl(IntPtr ptr)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.UserManagerInstance.OnCurrentUserUpdate != null)
			{
				discord.UserManagerInstance.OnCurrentUserUpdate();
			}
		}
	}
	public class ImageManager
	{
		internal struct FFIEvents
		{
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void FetchCallback(IntPtr ptr, Result result, ImageHandle handleResult);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void FetchMethod(IntPtr methodsPtr, ImageHandle handle, bool refresh, IntPtr callbackData, FetchCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetDimensionsMethod(IntPtr methodsPtr, ImageHandle handle, ref ImageDimensions dimensions);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetDataMethod(IntPtr methodsPtr, ImageHandle handle, byte[] data, int dataLen);

			internal FetchMethod Fetch;

			internal GetDimensionsMethod GetDimensions;

			internal GetDataMethod GetData;
		}

		public delegate void FetchHandler(Result result, ImageHandle handleResult);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		internal ImageManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		[MonoPInvokeCallback]
		private static void FetchCallbackImpl(IntPtr ptr, Result result, ImageHandle handleResult)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			FetchHandler fetchHandler = (FetchHandler)gCHandle.Target;
			gCHandle.Free();
			fetchHandler(result, handleResult);
		}

		public void Fetch(ImageHandle handle, bool refresh, FetchHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.Fetch(MethodsPtr, handle, refresh, GCHandle.ToIntPtr(value), FetchCallbackImpl);
		}

		public ImageDimensions GetDimensions(ImageHandle handle)
		{
			ImageDimensions dimensions = default(ImageDimensions);
			Result result = Methods.GetDimensions(MethodsPtr, handle, ref dimensions);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return dimensions;
		}

		public void GetData(ImageHandle handle, byte[] data)
		{
			Result result = Methods.GetData(MethodsPtr, handle, data, data.Length);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void Fetch(ImageHandle handle, FetchHandler callback)
		{
			Fetch(handle, refresh: false, callback);
		}

		public byte[] GetData(ImageHandle handle)
		{
			ImageDimensions dimensions = GetDimensions(handle);
			byte[] array = new byte[dimensions.Width * dimensions.Height * 4];
			GetData(handle, array);
			return array;
		}
	}
	public class RelationshipManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void RefreshHandler(IntPtr ptr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void RelationshipUpdateHandler(IntPtr ptr, ref Relationship relationship);

			internal RefreshHandler OnRefresh;

			internal RelationshipUpdateHandler OnRelationshipUpdate;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate bool FilterCallback(IntPtr ptr, ref Relationship relationship);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void FilterMethod(IntPtr methodsPtr, IntPtr callbackData, FilterCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result CountMethod(IntPtr methodsPtr, ref int count);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMethod(IntPtr methodsPtr, long userId, ref Relationship relationship);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetAtMethod(IntPtr methodsPtr, uint index, ref Relationship relationship);

			internal FilterMethod Filter;

			internal CountMethod Count;

			internal GetMethod Get;

			internal GetAtMethod GetAt;
		}

		public delegate bool FilterHandler(ref Relationship relationship);

		public delegate void RefreshHandler();

		public delegate void RelationshipUpdateHandler(ref Relationship relationship);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event RefreshHandler OnRefresh;

		public event RelationshipUpdateHandler OnRelationshipUpdate;

		internal RelationshipManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnRefresh = OnRefreshImpl;
			events.OnRelationshipUpdate = OnRelationshipUpdateImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		[MonoPInvokeCallback]
		private static bool FilterCallbackImpl(IntPtr ptr, ref Relationship relationship)
		{
			FilterHandler filterHandler = (FilterHandler)GCHandle.FromIntPtr(ptr).Target;
			return filterHandler(ref relationship);
		}

		public void Filter(FilterHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.Filter(MethodsPtr, GCHandle.ToIntPtr(value), FilterCallbackImpl);
			value.Free();
		}

		public int Count()
		{
			int count = 0;
			Result result = Methods.Count(MethodsPtr, ref count);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return count;
		}

		public Relationship Get(long userId)
		{
			Relationship relationship = default(Relationship);
			Result result = Methods.Get(MethodsPtr, userId, ref relationship);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return relationship;
		}

		public Relationship GetAt(uint index)
		{
			Relationship relationship = default(Relationship);
			Result result = Methods.GetAt(MethodsPtr, index, ref relationship);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return relationship;
		}

		[MonoPInvokeCallback]
		private static void OnRefreshImpl(IntPtr ptr)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.RelationshipManagerInstance.OnRefresh != null)
			{
				discord.RelationshipManagerInstance.OnRefresh();
			}
		}

		[MonoPInvokeCallback]
		private static void OnRelationshipUpdateImpl(IntPtr ptr, ref Relationship relationship)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.RelationshipManagerInstance.OnRelationshipUpdate != null)
			{
				discord.RelationshipManagerInstance.OnRelationshipUpdate(ref relationship);
			}
		}
	}
	public class LobbyManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void LobbyUpdateHandler(IntPtr ptr, long lobbyId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void LobbyDeleteHandler(IntPtr ptr, long lobbyId, uint reason);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MemberConnectHandler(IntPtr ptr, long lobbyId, long userId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MemberUpdateHandler(IntPtr ptr, long lobbyId, long userId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MemberDisconnectHandler(IntPtr ptr, long lobbyId, long userId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void LobbyMessageHandler(IntPtr ptr, long lobbyId, long userId, IntPtr dataPtr, int dataLen);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SpeakingHandler(IntPtr ptr, long lobbyId, long userId, bool speaking);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void NetworkMessageHandler(IntPtr ptr, long lobbyId, long userId, byte channelId, IntPtr dataPtr, int dataLen);

			internal LobbyUpdateHandler OnLobbyUpdate;

			internal LobbyDeleteHandler OnLobbyDelete;

			internal MemberConnectHandler OnMemberConnect;

			internal MemberUpdateHandler OnMemberUpdate;

			internal MemberDisconnectHandler OnMemberDisconnect;

			internal LobbyMessageHandler OnLobbyMessage;

			internal SpeakingHandler OnSpeaking;

			internal NetworkMessageHandler OnNetworkMessage;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyCreateTransactionMethod(IntPtr methodsPtr, ref IntPtr transaction);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyUpdateTransactionMethod(IntPtr methodsPtr, long lobbyId, ref IntPtr transaction);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMemberUpdateTransactionMethod(IntPtr methodsPtr, long lobbyId, long userId, ref IntPtr transaction);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void CreateLobbyCallback(IntPtr ptr, Result result, ref Lobby lobby);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void CreateLobbyMethod(IntPtr methodsPtr, IntPtr transaction, IntPtr callbackData, CreateLobbyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateLobbyCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateLobbyMethod(IntPtr methodsPtr, long lobbyId, IntPtr transaction, IntPtr callbackData, UpdateLobbyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DeleteLobbyCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DeleteLobbyMethod(IntPtr methodsPtr, long lobbyId, IntPtr callbackData, DeleteLobbyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectLobbyCallback(IntPtr ptr, Result result, ref Lobby lobby);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectLobbyMethod(IntPtr methodsPtr, long lobbyId, [MarshalAs(UnmanagedType.LPStr)] string secret, IntPtr callbackData, ConnectLobbyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectLobbyWithActivitySecretCallback(IntPtr ptr, Result result, ref Lobby lobby);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectLobbyWithActivitySecretMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string activitySecret, IntPtr callbackData, ConnectLobbyWithActivitySecretCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DisconnectLobbyCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DisconnectLobbyMethod(IntPtr methodsPtr, long lobbyId, IntPtr callbackData, DisconnectLobbyCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyMethod(IntPtr methodsPtr, long lobbyId, ref Lobby lobby);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyActivitySecretMethod(IntPtr methodsPtr, long lobbyId, StringBuilder secret);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyMetadataValueMethod(IntPtr methodsPtr, long lobbyId, [MarshalAs(UnmanagedType.LPStr)] string key, StringBuilder value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyMetadataKeyMethod(IntPtr methodsPtr, long lobbyId, int index, StringBuilder key);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result LobbyMetadataCountMethod(IntPtr methodsPtr, long lobbyId, ref int count);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result MemberCountMethod(IntPtr methodsPtr, long lobbyId, ref int count);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMemberUserIdMethod(IntPtr methodsPtr, long lobbyId, int index, ref long userId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMemberUserMethod(IntPtr methodsPtr, long lobbyId, long userId, ref User user);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMemberMetadataValueMethod(IntPtr methodsPtr, long lobbyId, long userId, [MarshalAs(UnmanagedType.LPStr)] string key, StringBuilder value);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetMemberMetadataKeyMethod(IntPtr methodsPtr, long lobbyId, long userId, int index, StringBuilder key);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result MemberMetadataCountMethod(IntPtr methodsPtr, long lobbyId, long userId, ref int count);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateMemberCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void UpdateMemberMethod(IntPtr methodsPtr, long lobbyId, long userId, IntPtr transaction, IntPtr callbackData, UpdateMemberCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendLobbyMessageCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SendLobbyMessageMethod(IntPtr methodsPtr, long lobbyId, byte[] data, int dataLen, IntPtr callbackData, SendLobbyMessageCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetSearchQueryMethod(IntPtr methodsPtr, ref IntPtr query);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SearchCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SearchMethod(IntPtr methodsPtr, IntPtr query, IntPtr callbackData, SearchCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void LobbyCountMethod(IntPtr methodsPtr, ref int count);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result GetLobbyIdMethod(IntPtr methodsPtr, int index, ref long lobbyId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectVoiceCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ConnectVoiceMethod(IntPtr methodsPtr, long lobbyId, IntPtr callbackData, ConnectVoiceCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DisconnectVoiceCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void DisconnectVoiceMethod(IntPtr methodsPtr, long lobbyId, IntPtr callbackData, DisconnectVoiceCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result ConnectNetworkMethod(IntPtr methodsPtr, long lobbyId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result DisconnectNetworkMethod(IntPtr methodsPtr, long lobbyId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result FlushNetworkMethod(IntPtr methodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result OpenNetworkChannelMethod(IntPtr methodsPtr, long lobbyId, byte channelId, bool reliable);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SendNetworkMessageMethod(IntPtr methodsPtr, long lobbyId, long userId, byte channelId, byte[] data, int dataLen);

			internal GetLobbyCreateTransactionMethod GetLobbyCreateTransaction;

			internal GetLobbyUpdateTransactionMethod GetLobbyUpdateTransaction;

			internal GetMemberUpdateTransactionMethod GetMemberUpdateTransaction;

			internal CreateLobbyMethod CreateLobby;

			internal UpdateLobbyMethod UpdateLobby;

			internal DeleteLobbyMethod DeleteLobby;

			internal ConnectLobbyMethod ConnectLobby;

			internal ConnectLobbyWithActivitySecretMethod ConnectLobbyWithActivitySecret;

			internal DisconnectLobbyMethod DisconnectLobby;

			internal GetLobbyMethod GetLobby;

			internal GetLobbyActivitySecretMethod GetLobbyActivitySecret;

			internal GetLobbyMetadataValueMethod GetLobbyMetadataValue;

			internal GetLobbyMetadataKeyMethod GetLobbyMetadataKey;

			internal LobbyMetadataCountMethod LobbyMetadataCount;

			internal MemberCountMethod MemberCount;

			internal GetMemberUserIdMethod GetMemberUserId;

			internal GetMemberUserMethod GetMemberUser;

			internal GetMemberMetadataValueMethod GetMemberMetadataValue;

			internal GetMemberMetadataKeyMethod GetMemberMetadataKey;

			internal MemberMetadataCountMethod MemberMetadataCount;

			internal UpdateMemberMethod UpdateMember;

			internal SendLobbyMessageMethod SendLobbyMessage;

			internal GetSearchQueryMethod GetSearchQuery;

			internal SearchMethod Search;

			internal LobbyCountMethod LobbyCount;

			internal GetLobbyIdMethod GetLobbyId;

			internal ConnectVoiceMethod ConnectVoice;

			internal DisconnectVoiceMethod DisconnectVoice;

			internal ConnectNetworkMethod ConnectNetwork;

			internal DisconnectNetworkMethod DisconnectNetwork;

			internal FlushNetworkMethod FlushNetwork;

			internal OpenNetworkChannelMethod OpenNetworkChannel;

			internal SendNetworkMessageMethod SendNetworkMessage;
		}

		public delegate void CreateLobbyHandler(Result result, ref Lobby lobby);

		public delegate void UpdateLobbyHandler(Result result);

		public delegate void DeleteLobbyHandler(Result result);

		public delegate void ConnectLobbyHandler(Result result, ref Lobby lobby);

		public delegate void ConnectLobbyWithActivitySecretHandler(Result result, ref Lobby lobby);

		public delegate void DisconnectLobbyHandler(Result result);

		public delegate void UpdateMemberHandler(Result result);

		public delegate void SendLobbyMessageHandler(Result result);

		public delegate void SearchHandler(Result result);

		public delegate void ConnectVoiceHandler(Result result);

		public delegate void DisconnectVoiceHandler(Result result);

		public delegate void LobbyUpdateHandler(long lobbyId);

		public delegate void LobbyDeleteHandler(long lobbyId, uint reason);

		public delegate void MemberConnectHandler(long lobbyId, long userId);

		public delegate void MemberUpdateHandler(long lobbyId, long userId);

		public delegate void MemberDisconnectHandler(long lobbyId, long userId);

		public delegate void LobbyMessageHandler(long lobbyId, long userId, byte[] data);

		public delegate void SpeakingHandler(long lobbyId, long userId, bool speaking);

		public delegate void NetworkMessageHandler(long lobbyId, long userId, byte channelId, byte[] data);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event LobbyUpdateHandler OnLobbyUpdate;

		public event LobbyDeleteHandler OnLobbyDelete;

		public event MemberConnectHandler OnMemberConnect;

		public event MemberUpdateHandler OnMemberUpdate;

		public event MemberDisconnectHandler OnMemberDisconnect;

		public event LobbyMessageHandler OnLobbyMessage;

		public event SpeakingHandler OnSpeaking;

		public event NetworkMessageHandler OnNetworkMessage;

		internal LobbyManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnLobbyUpdate = OnLobbyUpdateImpl;
			events.OnLobbyDelete = OnLobbyDeleteImpl;
			events.OnMemberConnect = OnMemberConnectImpl;
			events.OnMemberUpdate = OnMemberUpdateImpl;
			events.OnMemberDisconnect = OnMemberDisconnectImpl;
			events.OnLobbyMessage = OnLobbyMessageImpl;
			events.OnSpeaking = OnSpeakingImpl;
			events.OnNetworkMessage = OnNetworkMessageImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public LobbyTransaction GetLobbyCreateTransaction()
		{
			LobbyTransaction result = default(LobbyTransaction);
			Result result2 = Methods.GetLobbyCreateTransaction(MethodsPtr, ref result.MethodsPtr);
			if (result2 != 0)
			{
				throw new ResultException(result2);
			}
			return result;
		}

		public LobbyTransaction GetLobbyUpdateTransaction(long lobbyId)
		{
			LobbyTransaction result = default(LobbyTransaction);
			Result result2 = Methods.GetLobbyUpdateTransaction(MethodsPtr, lobbyId, ref result.MethodsPtr);
			if (result2 != 0)
			{
				throw new ResultException(result2);
			}
			return result;
		}

		public LobbyMemberTransaction GetMemberUpdateTransaction(long lobbyId, long userId)
		{
			LobbyMemberTransaction result = default(LobbyMemberTransaction);
			Result result2 = Methods.GetMemberUpdateTransaction(MethodsPtr, lobbyId, userId, ref result.MethodsPtr);
			if (result2 != 0)
			{
				throw new ResultException(result2);
			}
			return result;
		}

		[MonoPInvokeCallback]
		private static void CreateLobbyCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			CreateLobbyHandler createLobbyHandler = (CreateLobbyHandler)gCHandle.Target;
			gCHandle.Free();
			createLobbyHandler(result, ref lobby);
		}

		public void CreateLobby(LobbyTransaction transaction, CreateLobbyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.CreateLobby(MethodsPtr, transaction.MethodsPtr, GCHandle.ToIntPtr(value), CreateLobbyCallbackImpl);
			transaction.MethodsPtr = IntPtr.Zero;
		}

		[MonoPInvokeCallback]
		private static void UpdateLobbyCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			UpdateLobbyHandler updateLobbyHandler = (UpdateLobbyHandler)gCHandle.Target;
			gCHandle.Free();
			updateLobbyHandler(result);
		}

		public void UpdateLobby(long lobbyId, LobbyTransaction transaction, UpdateLobbyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.UpdateLobby(MethodsPtr, lobbyId, transaction.MethodsPtr, GCHandle.ToIntPtr(value), UpdateLobbyCallbackImpl);
			transaction.MethodsPtr = IntPtr.Zero;
		}

		[MonoPInvokeCallback]
		private static void DeleteLobbyCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			DeleteLobbyHandler deleteLobbyHandler = (DeleteLobbyHandler)gCHandle.Target;
			gCHandle.Free();
			deleteLobbyHandler(result);
		}

		public void DeleteLobby(long lobbyId, DeleteLobbyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.DeleteLobby(MethodsPtr, lobbyId, GCHandle.ToIntPtr(value), DeleteLobbyCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void ConnectLobbyCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			ConnectLobbyHandler connectLobbyHandler = (ConnectLobbyHandler)gCHandle.Target;
			gCHandle.Free();
			connectLobbyHandler(result, ref lobby);
		}

		public void ConnectLobby(long lobbyId, string secret, ConnectLobbyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.ConnectLobby(MethodsPtr, lobbyId, secret, GCHandle.ToIntPtr(value), ConnectLobbyCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void ConnectLobbyWithActivitySecretCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			ConnectLobbyWithActivitySecretHandler connectLobbyWithActivitySecretHandler = (ConnectLobbyWithActivitySecretHandler)gCHandle.Target;
			gCHandle.Free();
			connectLobbyWithActivitySecretHandler(result, ref lobby);
		}

		public void ConnectLobbyWithActivitySecret(string activitySecret, ConnectLobbyWithActivitySecretHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.ConnectLobbyWithActivitySecret(MethodsPtr, activitySecret, GCHandle.ToIntPtr(value), ConnectLobbyWithActivitySecretCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void DisconnectLobbyCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			DisconnectLobbyHandler disconnectLobbyHandler = (DisconnectLobbyHandler)gCHandle.Target;
			gCHandle.Free();
			disconnectLobbyHandler(result);
		}

		public void DisconnectLobby(long lobbyId, DisconnectLobbyHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.DisconnectLobby(MethodsPtr, lobbyId, GCHandle.ToIntPtr(value), DisconnectLobbyCallbackImpl);
		}

		public Lobby GetLobby(long lobbyId)
		{
			Lobby lobby = default(Lobby);
			Result result = Methods.GetLobby(MethodsPtr, lobbyId, ref lobby);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return lobby;
		}

		public string GetLobbyActivitySecret(long lobbyId)
		{
			StringBuilder stringBuilder = new StringBuilder(128);
			Result result = Methods.GetLobbyActivitySecret(MethodsPtr, lobbyId, stringBuilder);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return stringBuilder.ToString();
		}

		public string GetLobbyMetadataValue(long lobbyId, string key)
		{
			StringBuilder stringBuilder = new StringBuilder(4096);
			Result result = Methods.GetLobbyMetadataValue(MethodsPtr, lobbyId, key, stringBuilder);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return stringBuilder.ToString();
		}

		public string GetLobbyMetadataKey(long lobbyId, int index)
		{
			StringBuilder stringBuilder = new StringBuilder(256);
			Result result = Methods.GetLobbyMetadataKey(MethodsPtr, lobbyId, index, stringBuilder);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return stringBuilder.ToString();
		}

		public int LobbyMetadataCount(long lobbyId)
		{
			int count = 0;
			Result result = Methods.LobbyMetadataCount(MethodsPtr, lobbyId, ref count);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return count;
		}

		public int MemberCount(long lobbyId)
		{
			int count = 0;
			Result result = Methods.MemberCount(MethodsPtr, lobbyId, ref count);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return count;
		}

		public long GetMemberUserId(long lobbyId, int index)
		{
			long userId = 0L;
			Result result = Methods.GetMemberUserId(MethodsPtr, lobbyId, index, ref userId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return userId;
		}

		public User GetMemberUser(long lobbyId, long userId)
		{
			User user = default(User);
			Result result = Methods.GetMemberUser(MethodsPtr, lobbyId, userId, ref user);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return user;
		}

		public string GetMemberMetadataValue(long lobbyId, long userId, string key)
		{
			StringBuilder stringBuilder = new StringBuilder(4096);
			Result result = Methods.GetMemberMetadataValue(MethodsPtr, lobbyId, userId, key, stringBuilder);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return stringBuilder.ToString();
		}

		public string GetMemberMetadataKey(long lobbyId, long userId, int index)
		{
			StringBuilder stringBuilder = new StringBuilder(256);
			Result result = Methods.GetMemberMetadataKey(MethodsPtr, lobbyId, userId, index, stringBuilder);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return stringBuilder.ToString();
		}

		public int MemberMetadataCount(long lobbyId, long userId)
		{
			int count = 0;
			Result result = Methods.MemberMetadataCount(MethodsPtr, lobbyId, userId, ref count);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return count;
		}

		[MonoPInvokeCallback]
		private static void UpdateMemberCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			UpdateMemberHandler updateMemberHandler = (UpdateMemberHandler)gCHandle.Target;
			gCHandle.Free();
			updateMemberHandler(result);
		}

		public void UpdateMember(long lobbyId, long userId, LobbyMemberTransaction transaction, UpdateMemberHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.UpdateMember(MethodsPtr, lobbyId, userId, transaction.MethodsPtr, GCHandle.ToIntPtr(value), UpdateMemberCallbackImpl);
			transaction.MethodsPtr = IntPtr.Zero;
		}

		[MonoPInvokeCallback]
		private static void SendLobbyMessageCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SendLobbyMessageHandler sendLobbyMessageHandler = (SendLobbyMessageHandler)gCHandle.Target;
			gCHandle.Free();
			sendLobbyMessageHandler(result);
		}

		public void SendLobbyMessage(long lobbyId, byte[] data, SendLobbyMessageHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SendLobbyMessage(MethodsPtr, lobbyId, data, data.Length, GCHandle.ToIntPtr(value), SendLobbyMessageCallbackImpl);
		}

		public LobbySearchQuery GetSearchQuery()
		{
			LobbySearchQuery result = default(LobbySearchQuery);
			Result result2 = Methods.GetSearchQuery(MethodsPtr, ref result.MethodsPtr);
			if (result2 != 0)
			{
				throw new ResultException(result2);
			}
			return result;
		}

		[MonoPInvokeCallback]
		private static void SearchCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SearchHandler searchHandler = (SearchHandler)gCHandle.Target;
			gCHandle.Free();
			searchHandler(result);
		}

		public void Search(LobbySearchQuery query, SearchHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.Search(MethodsPtr, query.MethodsPtr, GCHandle.ToIntPtr(value), SearchCallbackImpl);
			query.MethodsPtr = IntPtr.Zero;
		}

		public int LobbyCount()
		{
			int count = 0;
			Methods.LobbyCount(MethodsPtr, ref count);
			return count;
		}

		public long GetLobbyId(int index)
		{
			long lobbyId = 0L;
			Result result = Methods.GetLobbyId(MethodsPtr, index, ref lobbyId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
			return lobbyId;
		}

		[MonoPInvokeCallback]
		private static void ConnectVoiceCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			ConnectVoiceHandler connectVoiceHandler = (ConnectVoiceHandler)gCHandle.Target;
			gCHandle.Free();
			connectVoiceHandler(result);
		}

		public void ConnectVoice(long lobbyId, ConnectVoiceHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.ConnectVoice(MethodsPtr, lobbyId, GCHandle.ToIntPtr(value), ConnectVoiceCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void DisconnectVoiceCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			DisconnectVoiceHandler disconnectVoiceHandler = (DisconnectVoiceHandler)gCHandle.Target;
			gCHandle.Free();
			disconnectVoiceHandler(result);
		}

		public void DisconnectVoice(long lobbyId, DisconnectVoiceHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.DisconnectVoice(MethodsPtr, lobbyId, GCHandle.ToIntPtr(value), DisconnectVoiceCallbackImpl);
		}

		public void ConnectNetwork(long lobbyId)
		{
			Result result = Methods.ConnectNetwork(MethodsPtr, lobbyId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void DisconnectNetwork(long lobbyId)
		{
			Result result = Methods.DisconnectNetwork(MethodsPtr, lobbyId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void FlushNetwork()
		{
			Result result = Methods.FlushNetwork(MethodsPtr);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void OpenNetworkChannel(long lobbyId, byte channelId, bool reliable)
		{
			Result result = Methods.OpenNetworkChannel(MethodsPtr, lobbyId, channelId, reliable);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void SendNetworkMessage(long lobbyId, long userId, byte channelId, byte[] data)
		{
			Result result = Methods.SendNetworkMessage(MethodsPtr, lobbyId, userId, channelId, data, data.Length);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		[MonoPInvokeCallback]
		private static void OnLobbyUpdateImpl(IntPtr ptr, long lobbyId)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnLobbyUpdate != null)
			{
				discord.LobbyManagerInstance.OnLobbyUpdate(lobbyId);
			}
		}

		[MonoPInvokeCallback]
		private static void OnLobbyDeleteImpl(IntPtr ptr, long lobbyId, uint reason)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnLobbyDelete != null)
			{
				discord.LobbyManagerInstance.OnLobbyDelete(lobbyId, reason);
			}
		}

		[MonoPInvokeCallback]
		private static void OnMemberConnectImpl(IntPtr ptr, long lobbyId, long userId)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnMemberConnect != null)
			{
				discord.LobbyManagerInstance.OnMemberConnect(lobbyId, userId);
			}
		}

		[MonoPInvokeCallback]
		private static void OnMemberUpdateImpl(IntPtr ptr, long lobbyId, long userId)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnMemberUpdate != null)
			{
				discord.LobbyManagerInstance.OnMemberUpdate(lobbyId, userId);
			}
		}

		[MonoPInvokeCallback]
		private static void OnMemberDisconnectImpl(IntPtr ptr, long lobbyId, long userId)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnMemberDisconnect != null)
			{
				discord.LobbyManagerInstance.OnMemberDisconnect(lobbyId, userId);
			}
		}

		[MonoPInvokeCallback]
		private static void OnLobbyMessageImpl(IntPtr ptr, long lobbyId, long userId, IntPtr dataPtr, int dataLen)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnLobbyMessage != null)
			{
				byte[] array = new byte[dataLen];
				Marshal.Copy(dataPtr, array, 0, dataLen);
				discord.LobbyManagerInstance.OnLobbyMessage(lobbyId, userId, array);
			}
		}

		[MonoPInvokeCallback]
		private static void OnSpeakingImpl(IntPtr ptr, long lobbyId, long userId, bool speaking)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnSpeaking != null)
			{
				discord.LobbyManagerInstance.OnSpeaking(lobbyId, userId, speaking);
			}
		}

		[MonoPInvokeCallback]
		private static void OnNetworkMessageImpl(IntPtr ptr, long lobbyId, long userId, byte channelId, IntPtr dataPtr, int dataLen)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.LobbyManagerInstance.OnNetworkMessage != null)
			{
				byte[] array = new byte[dataLen];
				Marshal.Copy(dataPtr, array, 0, dataLen);
				discord.LobbyManagerInstance.OnNetworkMessage(lobbyId, userId, channelId, array);
			}
		}

		public IEnumerable<User> GetMemberUsers(long lobbyID)
		{
			int num = MemberCount(lobbyID);
			List<User> list = new List<User>();
			for (int i = 0; i < num; i++)
			{
				list.Add(GetMemberUser(lobbyID, GetMemberUserId(lobbyID, i)));
			}
			return list;
		}

		public void SendLobbyMessage(long lobbyID, string data, SendLobbyMessageHandler handler)
		{
			SendLobbyMessage(lobbyID, Encoding.UTF8.GetBytes(data), handler);
		}
	}
	public class NetworkManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MessageHandler(IntPtr ptr, ulong peerId, byte channelId, IntPtr dataPtr, int dataLen);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void RouteUpdateHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)] string routeData);

			internal MessageHandler OnMessage;

			internal RouteUpdateHandler OnRouteUpdate;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void GetPeerIdMethod(IntPtr methodsPtr, ref ulong peerId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result FlushMethod(IntPtr methodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result OpenPeerMethod(IntPtr methodsPtr, ulong peerId, [MarshalAs(UnmanagedType.LPStr)] string routeData);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result UpdatePeerMethod(IntPtr methodsPtr, ulong peerId, [MarshalAs(UnmanagedType.LPStr)] string routeData);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result ClosePeerMethod(IntPtr methodsPtr, ulong peerId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result OpenChannelMethod(IntPtr methodsPtr, ulong peerId, byte channelId, bool reliable);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result CloseChannelMethod(IntPtr methodsPtr, ulong peerId, byte channelId);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result SendMessageMethod(IntPtr methodsPtr, ulong peerId, byte channelId, byte[] data, int dataLen);

			internal GetPeerIdMethod GetPeerId;

			internal FlushMethod Flush;

			internal OpenPeerMethod OpenPeer;

			internal UpdatePeerMethod UpdatePeer;

			internal ClosePeerMethod ClosePeer;

			internal OpenChannelMethod OpenChannel;

			internal CloseChannelMethod CloseChannel;

			internal SendMessageMethod SendMessage;
		}

		public delegate void MessageHandler(ulong peerId, byte channelId, byte[] data);

		public delegate void RouteUpdateHandler(string routeData);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event MessageHandler OnMessage;

		public event RouteUpdateHandler OnRouteUpdate;

		internal NetworkManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnMessage = OnMessageImpl;
			events.OnRouteUpdate = OnRouteUpdateImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public ulong GetPeerId()
		{
			ulong peerId = 0uL;
			Methods.GetPeerId(MethodsPtr, ref peerId);
			return peerId;
		}

		public void Flush()
		{
			Result result = Methods.Flush(MethodsPtr);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void OpenPeer(ulong peerId, string routeData)
		{
			Result result = Methods.OpenPeer(MethodsPtr, peerId, routeData);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void UpdatePeer(ulong peerId, string routeData)
		{
			Result result = Methods.UpdatePeer(MethodsPtr, peerId, routeData);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void ClosePeer(ulong peerId)
		{
			Result result = Methods.ClosePeer(MethodsPtr, peerId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void OpenChannel(ulong peerId, byte channelId, bool reliable)
		{
			Result result = Methods.OpenChannel(MethodsPtr, peerId, channelId, reliable);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void CloseChannel(ulong peerId, byte channelId)
		{
			Result result = Methods.CloseChannel(MethodsPtr, peerId, channelId);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void SendMessage(ulong peerId, byte channelId, byte[] data)
		{
			Result result = Methods.SendMessage(MethodsPtr, peerId, channelId, data, data.Length);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		[MonoPInvokeCallback]
		private static void OnMessageImpl(IntPtr ptr, ulong peerId, byte channelId, IntPtr dataPtr, int dataLen)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.NetworkManagerInstance.OnMessage != null)
			{
				byte[] array = new byte[dataLen];
				Marshal.Copy(dataPtr, array, 0, dataLen);
				discord.NetworkManagerInstance.OnMessage(peerId, channelId, array);
			}
		}

		[MonoPInvokeCallback]
		private static void OnRouteUpdateImpl(IntPtr ptr, string routeData)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.NetworkManagerInstance.OnRouteUpdate != null)
			{
				discord.NetworkManagerInstance.OnRouteUpdate(routeData);
			}
		}
	}
	public class OverlayManager
	{
		internal struct FFIEvents
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ToggleHandler(IntPtr ptr, bool locked);

			internal ToggleHandler OnToggle;
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void IsEnabledMethod(IntPtr methodsPtr, ref bool enabled);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void IsLockedMethod(IntPtr methodsPtr, ref bool locked);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetLockedCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetLockedMethod(IntPtr methodsPtr, bool locked, IntPtr callbackData, SetLockedCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenActivityInviteCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenActivityInviteMethod(IntPtr methodsPtr, ActivityActionType type, IntPtr callbackData, OpenActivityInviteCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenGuildInviteCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenGuildInviteMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string code, IntPtr callbackData, OpenGuildInviteCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenVoiceSettingsCallback(IntPtr ptr, Result result);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OpenVoiceSettingsMethod(IntPtr methodsPtr, IntPtr callbackData, OpenVoiceSettingsCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result InitDrawingDxgiMethod(IntPtr methodsPtr, IntPtr swapchain, bool useMessageForwarding);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void OnPresentMethod(IntPtr methodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ForwardMessageMethod(IntPtr methodsPtr, IntPtr message);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void KeyEventMethod(IntPtr methodsPtr, bool down, [MarshalAs(UnmanagedType.LPStr)] string keyCode, KeyVariant variant);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void CharEventMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string character);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MouseButtonEventMethod(IntPtr methodsPtr, byte down, int clickCount, MouseButton which, int x, int y);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void MouseMotionEventMethod(IntPtr methodsPtr, int x, int y);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ImeCommitTextMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string text);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ImeSetCompositionMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] string text, ref ImeUnderline underlines, int from, int to);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void ImeCancelCompositionMethod(IntPtr methodsPtr);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetImeCompositionRangeCallbackCallback(IntPtr ptr, int from, int to, ref Rect bounds);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetImeCompositionRangeCallbackMethod(IntPtr methodsPtr, IntPtr callbackData, SetImeCompositionRangeCallbackCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetImeSelectionBoundsCallbackCallback(IntPtr ptr, Rect anchor, Rect focus, bool isAnchorFirst);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate void SetImeSelectionBoundsCallbackMethod(IntPtr methodsPtr, IntPtr callbackData, SetImeSelectionBoundsCallbackCallback callback);

			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate bool IsPointInsideClickZoneMethod(IntPtr methodsPtr, int x, int y);

			internal IsEnabledMethod IsEnabled;

			internal IsLockedMethod IsLocked;

			internal SetLockedMethod SetLocked;

			internal OpenActivityInviteMethod OpenActivityInvite;

			internal OpenGuildInviteMethod OpenGuildInvite;

			internal OpenVoiceSettingsMethod OpenVoiceSettings;

			internal InitDrawingDxgiMethod InitDrawingDxgi;

			internal OnPresentMethod OnPresent;

			internal ForwardMessageMethod ForwardMessage;

			internal KeyEventMethod KeyEvent;

			internal CharEventMethod CharEvent;

			internal MouseButtonEventMethod MouseButtonEvent;

			internal MouseMotionEventMethod MouseMotionEvent;

			internal ImeCommitTextMethod ImeCommitText;

			internal ImeSetCompositionMethod ImeSetComposition;

			internal ImeCancelCompositionMethod ImeCancelComposition;

			internal SetImeCompositionRangeCallbackMethod SetImeCompositionRangeCallback;

			internal SetImeSelectionBoundsCallbackMethod SetImeSelectionBoundsCallback;

			internal IsPointInsideClickZoneMethod IsPointInsideClickZone;
		}

		public delegate void SetLockedHandler(Result result);

		public delegate void OpenActivityInviteHandler(Result result);

		public delegate void OpenGuildInviteHandler(Result result);

		public delegate void OpenVoiceSettingsHandler(Result result);

		public delegate void SetImeCompositionRangeCallbackHandler(int from, int to, ref Rect bounds);

		public delegate void SetImeSelectionBoundsCallbackHandler(Rect anchor, Rect focus, bool isAnchorFirst);

		public delegate void ToggleHandler(bool locked);

		private IntPtr MethodsPtr;

		private object MethodsStructure;

		private FFIMethods Methods
		{
			get
			{
				if (MethodsStructure == null)
				{
					MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods));
				}
				return (FFIMethods)MethodsStructure;
			}
		}

		public event ToggleHandler OnToggle;

		internal OverlayManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events)
		{
			if (eventsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
			InitEvents(eventsPtr, ref events);
			MethodsPtr = ptr;
			if (MethodsPtr == IntPtr.Zero)
			{
				throw new ResultException(Result.InternalError);
			}
		}

		private void InitEvents(IntPtr eventsPtr, ref FFIEvents events)
		{
			events.OnToggle = OnToggleImpl;
			Marshal.StructureToPtr(events, eventsPtr, fDeleteOld: false);
		}

		public bool IsEnabled()
		{
			bool enabled = false;
			Methods.IsEnabled(MethodsPtr, ref enabled);
			return enabled;
		}

		public bool IsLocked()
		{
			bool locked = false;
			Methods.IsLocked(MethodsPtr, ref locked);
			return locked;
		}

		[MonoPInvokeCallback]
		private static void SetLockedCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SetLockedHandler setLockedHandler = (SetLockedHandler)gCHandle.Target;
			gCHandle.Free();
			setLockedHandler(result);
		}

		public void SetLocked(bool locked, SetLockedHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SetLocked(MethodsPtr, locked, GCHandle.ToIntPtr(value), SetLockedCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void OpenActivityInviteCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			OpenActivityInviteHandler openActivityInviteHandler = (OpenActivityInviteHandler)gCHandle.Target;
			gCHandle.Free();
			openActivityInviteHandler(result);
		}

		public void OpenActivityInvite(ActivityActionType type, OpenActivityInviteHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.OpenActivityInvite(MethodsPtr, type, GCHandle.ToIntPtr(value), OpenActivityInviteCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void OpenGuildInviteCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			OpenGuildInviteHandler openGuildInviteHandler = (OpenGuildInviteHandler)gCHandle.Target;
			gCHandle.Free();
			openGuildInviteHandler(result);
		}

		public void OpenGuildInvite(string code, OpenGuildInviteHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.OpenGuildInvite(MethodsPtr, code, GCHandle.ToIntPtr(value), OpenGuildInviteCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void OpenVoiceSettingsCallbackImpl(IntPtr ptr, Result result)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			OpenVoiceSettingsHandler openVoiceSettingsHandler = (OpenVoiceSettingsHandler)gCHandle.Target;
			gCHandle.Free();
			openVoiceSettingsHandler(result);
		}

		public void OpenVoiceSettings(OpenVoiceSettingsHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.OpenVoiceSettings(MethodsPtr, GCHandle.ToIntPtr(value), OpenVoiceSettingsCallbackImpl);
		}

		public void InitDrawingDxgi(IntPtr swapchain, bool useMessageForwarding)
		{
			Result result = Methods.InitDrawingDxgi(MethodsPtr, swapchain, useMessageForwarding);
			if (result != 0)
			{
				throw new ResultException(result);
			}
		}

		public void OnPresent()
		{
			Methods.OnPresent(MethodsPtr);
		}

		public void ForwardMessage(IntPtr message)
		{
			Methods.ForwardMessage(MethodsPtr, message);
		}

		public void KeyEvent(bool down, string keyCode, KeyVariant variant)
		{
			Methods.KeyEvent(MethodsPtr, down, keyCode, variant);
		}

		public void CharEvent(string character)
		{
			Methods.CharEvent(MethodsPtr, character);
		}

		public void MouseButtonEvent(byte down, int clickCount, MouseButton which, int x, int y)
		{
			Methods.MouseButtonEvent(MethodsPtr, down, clickCount, which, x, y);
		}

		public void MouseMotionEvent(int x, int y)
		{
			Methods.MouseMotionEvent(MethodsPtr, x, y);
		}

		public void ImeCommitText(string text)
		{
			Methods.ImeCommitText(MethodsPtr, text);
		}

		public void ImeSetComposition(string text, ImeUnderline underlines, int from, int to)
		{
			Methods.ImeSetComposition(MethodsPtr, text, ref underlines, from, to);
		}

		public void ImeCancelComposition()
		{
			Methods.ImeCancelComposition(MethodsPtr);
		}

		[MonoPInvokeCallback]
		private static void SetImeCompositionRangeCallbackCallbackImpl(IntPtr ptr, int from, int to, ref Rect bounds)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SetImeCompositionRangeCallbackHandler setImeCompositionRangeCallbackHandler = (SetImeCompositionRangeCallbackHandler)gCHandle.Target;
			gCHandle.Free();
			setImeCompositionRangeCallbackHandler(from, to, ref bounds);
		}

		public void SetImeCompositionRangeCallback(SetImeCompositionRangeCallbackHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SetImeCompositionRangeCallback(MethodsPtr, GCHandle.ToIntPtr(value), SetImeCompositionRangeCallbackCallbackImpl);
		}

		[MonoPInvokeCallback]
		private static void SetImeSelectionBoundsCallbackCallbackImpl(IntPtr ptr, Rect anchor, Rect focus, bool isAnchorFirst)
		{
			GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
			SetImeSelectionBoundsCallbackHandler setImeSelectionBoundsCallbackHandler = (SetImeSelectionBoundsCallbackHandler)gCHandle.Target;
			gCHandle.Free();
			setImeSelectionBoundsCallbackHandler(anchor, focus, isAnchorFirst);
		}

		public void SetImeSelectionBoundsCallback(SetImeSelectionBoundsCallbackHandler callback)
		{
			GCHandle value = GCHandle.Alloc(callback);
			Methods.SetImeSelectionBoundsCallback(MethodsPtr, GCHandle.ToIntPtr(value), SetImeSelectionBoundsCallbackCallbackImpl);
		}

		public bool IsPointInsideClickZone(int x, int y)
		{
			return Methods.IsPointInsideClickZone(MethodsPtr, x, y);
		}

		[MonoPInvokeCallback]
		private static void OnToggleImpl(IntPtr ptr, bool locked)
		{
			Discord discord = (Discord)GCHandle.FromIntPtr(ptr).Target;
			if (discord.OverlayManagerInstance.OnToggle != null)
			{
				discord.OverlayManagerInstance.OnToggle(locked);
			}
		}
	}
	public class StorageManager
	{
		internal struct FFIEvents
		{
		}

		internal struct FFIMethods
		{
			[UnmanagedFunctionPointer(CallingConvention.Winapi)]
			internal delegate Result ReadMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)] s

plugins/DiscordRPC.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using DiscordRPC.Converters;
using DiscordRPC.Events;
using DiscordRPC.Exceptions;
using DiscordRPC.Helper;
using DiscordRPC.IO;
using DiscordRPC.Logging;
using DiscordRPC.Message;
using DiscordRPC.RPC;
using DiscordRPC.RPC.Commands;
using DiscordRPC.RPC.Payload;
using DiscordRPC.Registry;
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Discord RPC")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Discord RPC")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("819d20d6-8d88-45c1-a4d2-aa21f10abd19")]
[assembly: AssemblyFileVersion("1.3.0.28")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyVersion("1.3.0.28")]
namespace DiscordRPC
{
	public class Configuration
	{
		[JsonProperty("api_endpoint")]
		public string ApiEndpoint { get; set; }

		[JsonProperty("cdn_host")]
		public string CdnHost { get; set; }

		[JsonProperty("environment")]
		public string Environment { get; set; }
	}
	public sealed class DiscordRpcClient : IDisposable
	{
		private ILogger _logger;

		private RpcConnection connection;

		private bool _shutdownOnly = true;

		private object _sync = new object();

		public bool HasRegisteredUriScheme { get; private set; }

		public string ApplicationID { get; private set; }

		public string SteamID { get; private set; }

		public int ProcessID { get; private set; }

		public int MaxQueueSize { get; private set; }

		public bool IsDisposed { get; private set; }

		public ILogger Logger
		{
			get
			{
				return _logger;
			}
			set
			{
				_logger = value;
				if (connection != null)
				{
					connection.Logger = value;
				}
			}
		}

		public bool AutoEvents { get; private set; }

		public bool SkipIdenticalPresence { get; set; }

		public int TargetPipe { get; private set; }

		public RichPresence CurrentPresence { get; private set; }

		public EventType Subscription { get; private set; }

		public User CurrentUser { get; private set; }

		public Configuration Configuration { get; private set; }

		public bool IsInitialized { get; private set; }

		public bool ShutdownOnly
		{
			get
			{
				return _shutdownOnly;
			}
			set
			{
				_shutdownOnly = value;
				if (connection != null)
				{
					connection.ShutdownOnly = value;
				}
			}
		}

		public event OnReadyEvent OnReady;

		public event OnCloseEvent OnClose;

		public event OnErrorEvent OnError;

		public event OnPresenceUpdateEvent OnPresenceUpdate;

		public event OnSubscribeEvent OnSubscribe;

		public event OnUnsubscribeEvent OnUnsubscribe;

		public event OnJoinEvent OnJoin;

		public event OnSpectateEvent OnSpectate;

		public event OnJoinRequestedEvent OnJoinRequested;

		public event OnConnectionEstablishedEvent OnConnectionEstablished;

		public event OnConnectionFailedEvent OnConnectionFailed;

		public event OnRpcMessageEvent OnRpcMessage;

		public DiscordRpcClient(string applicationID)
			: this(applicationID, -1, null, autoEvents: true, null)
		{
		}

		public DiscordRpcClient(string applicationID, int pipe = -1, ILogger logger = null, bool autoEvents = true, INamedPipeClient client = null)
		{
			if (string.IsNullOrEmpty(applicationID))
			{
				throw new ArgumentNullException("applicationID");
			}
			ApplicationID = applicationID.Trim();
			TargetPipe = pipe;
			ProcessID = Process.GetCurrentProcess().Id;
			HasRegisteredUriScheme = false;
			AutoEvents = autoEvents;
			SkipIdenticalPresence = true;
			_logger = logger ?? new NullLogger();
			connection = new RpcConnection(ApplicationID, ProcessID, TargetPipe, client ?? new ManagedNamedPipeClient(), (!autoEvents) ? 128u : 0u)
			{
				ShutdownOnly = _shutdownOnly,
				Logger = _logger
			};
			connection.OnRpcMessage += delegate(object sender, IMessage msg)
			{
				if (this.OnRpcMessage != null)
				{
					this.OnRpcMessage(this, msg);
				}
				if (AutoEvents)
				{
					ProcessMessage(msg);
				}
			};
		}

		public IMessage[] Invoke()
		{
			if (AutoEvents)
			{
				Logger.Error("Cannot Invoke client when AutomaticallyInvokeEvents has been set.");
				return new IMessage[0];
			}
			IMessage[] array = connection.DequeueMessages();
			foreach (IMessage message in array)
			{
				ProcessMessage(message);
			}
			return array;
		}

		private void ProcessMessage(IMessage message)
		{
			if (message == null)
			{
				return;
			}
			switch (message.Type)
			{
			case MessageType.PresenceUpdate:
				lock (_sync)
				{
					if (message is PresenceMessage presenceMessage)
					{
						if (presenceMessage.Presence == null)
						{
							CurrentPresence = null;
						}
						else if (CurrentPresence == null)
						{
							CurrentPresence = new RichPresence().Merge(presenceMessage.Presence);
						}
						else
						{
							CurrentPresence.Merge(presenceMessage.Presence);
						}
						presenceMessage.Presence = CurrentPresence;
					}
				}
				if (this.OnPresenceUpdate != null)
				{
					this.OnPresenceUpdate(this, message as PresenceMessage);
				}
				break;
			case MessageType.Ready:
				if (message is ReadyMessage readyMessage)
				{
					lock (_sync)
					{
						Configuration = readyMessage.Configuration;
						CurrentUser = readyMessage.User;
					}
					SynchronizeState();
				}
				if (this.OnReady != null)
				{
					this.OnReady(this, message as ReadyMessage);
				}
				break;
			case MessageType.Close:
				if (this.OnClose != null)
				{
					this.OnClose(this, message as CloseMessage);
				}
				break;
			case MessageType.Error:
				if (this.OnError != null)
				{
					this.OnError(this, message as ErrorMessage);
				}
				break;
			case MessageType.JoinRequest:
				if (Configuration != null && message is JoinRequestMessage joinRequestMessage)
				{
					joinRequestMessage.User.SetConfiguration(Configuration);
				}
				if (this.OnJoinRequested != null)
				{
					this.OnJoinRequested(this, message as JoinRequestMessage);
				}
				break;
			case MessageType.Subscribe:
				lock (_sync)
				{
					SubscribeMessage subscribeMessage = message as SubscribeMessage;
					Subscription |= subscribeMessage.Event;
				}
				if (this.OnSubscribe != null)
				{
					this.OnSubscribe(this, message as SubscribeMessage);
				}
				break;
			case MessageType.Unsubscribe:
				lock (_sync)
				{
					UnsubscribeMessage unsubscribeMessage = message as UnsubscribeMessage;
					Subscription &= ~unsubscribeMessage.Event;
				}
				if (this.OnUnsubscribe != null)
				{
					this.OnUnsubscribe(this, message as UnsubscribeMessage);
				}
				break;
			case MessageType.Join:
				if (this.OnJoin != null)
				{
					this.OnJoin(this, message as JoinMessage);
				}
				break;
			case MessageType.Spectate:
				if (this.OnSpectate != null)
				{
					this.OnSpectate(this, message as SpectateMessage);
				}
				break;
			case MessageType.ConnectionEstablished:
				if (this.OnConnectionEstablished != null)
				{
					this.OnConnectionEstablished(this, message as ConnectionEstablishedMessage);
				}
				break;
			case MessageType.ConnectionFailed:
				if (this.OnConnectionFailed != null)
				{
					this.OnConnectionFailed(this, message as ConnectionFailedMessage);
				}
				break;
			default:
				Logger.Error("Message was queued with no appropriate handle! {0}", message.Type);
				break;
			}
		}

		public void Respond(JoinRequestMessage request, bool acceptRequest)
		{
			if (IsDisposed)
			{
				throw new ObjectDisposedException("Discord IPC Client");
			}
			if (connection == null)
			{
				throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized");
			}
			if (!IsInitialized)
			{
				throw new UninitializedException();
			}
			connection.EnqueueCommand(new RespondCommand
			{
				Accept = acceptRequest,
				UserID = request.User.ID.ToString()
			});
		}

		public void SetPresence(RichPresence presence)
		{
			if (IsDisposed)
			{
				throw new ObjectDisposedException("Discord IPC Client");
			}
			if (connection == null)
			{
				throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized");
			}
			if (!IsInitialized)
			{
				Logger.Warning("The client is not yet initialized, storing the presence as a state instead.");
			}
			if (presence == null)
			{
				if (!SkipIdenticalPresence || CurrentPresence != null)
				{
					connection.EnqueueCommand(new PresenceCommand
					{
						PID = ProcessID,
						Presence = null
					});
				}
			}
			else
			{
				if (presence.HasSecrets() && !HasRegisteredUriScheme)
				{
					throw new BadPresenceException("Cannot send a presence with secrets as this object has not registered a URI scheme. Please enable the uri scheme registration in the DiscordRpcClient constructor.");
				}
				if (presence.HasParty() && presence.Party.Max < presence.Party.Size)
				{
					throw new BadPresenceException("Presence maximum party size cannot be smaller than the current size.");
				}
				if (presence.HasSecrets() && !presence.HasParty())
				{
					Logger.Warning("The presence has set the secrets but no buttons will show as there is no party available.");
				}
				if (!SkipIdenticalPresence || !presence.Matches(CurrentPresence))
				{
					connection.EnqueueCommand(new PresenceCommand
					{
						PID = ProcessID,
						Presence = presence.Clone()
					});
				}
			}
			lock (_sync)
			{
				CurrentPresence = presence?.Clone();
			}
		}

		public RichPresence Update(Action<RichPresence> func)
		{
			if (!IsInitialized)
			{
				throw new UninitializedException();
			}
			RichPresence richPresence;
			lock (_sync)
			{
				richPresence = ((CurrentPresence == null) ? new RichPresence() : CurrentPresence.Clone());
			}
			func(richPresence);
			SetPresence(richPresence);
			return richPresence;
		}

		public RichPresence UpdateType(ActivityType type)
		{
			return Update(delegate(RichPresence p)
			{
				p.Type = type;
			});
		}

		public RichPresence UpdateButtons(Button[] buttons = null)
		{
			return Update(delegate(RichPresence p)
			{
				p.Buttons = buttons;
			});
		}

		public RichPresence SetButton(Button button, int index = 0)
		{
			return Update(delegate(RichPresence p)
			{
				p.Buttons[index] = button;
			});
		}

		public RichPresence UpdateDetails(string details)
		{
			return Update(delegate(RichPresence p)
			{
				p.Details = details;
			});
		}

		public RichPresence UpdateState(string state)
		{
			return Update(delegate(RichPresence p)
			{
				p.State = state;
			});
		}

		public RichPresence UpdateParty(Party party)
		{
			return Update(delegate(RichPresence p)
			{
				p.Party = party;
			});
		}

		public RichPresence UpdatePartySize(int size)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Party == null)
				{
					throw new BadPresenceException("Cannot set the size of the party if the party does not exist");
				}
				p.Party.Size = size;
			});
		}

		public RichPresence UpdatePartySize(int size, int max)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Party == null)
				{
					throw new BadPresenceException("Cannot set the size of the party if the party does not exist");
				}
				p.Party.Size = size;
				p.Party.Max = max;
			});
		}

		public RichPresence UpdateLargeAsset(string key = null, string tooltip = null)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Assets == null)
				{
					p.Assets = new Assets();
				}
				p.Assets.LargeImageKey = key ?? p.Assets.LargeImageKey;
				p.Assets.LargeImageText = tooltip ?? p.Assets.LargeImageText;
			});
		}

		public RichPresence UpdateSmallAsset(string key = null, string tooltip = null)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Assets == null)
				{
					p.Assets = new Assets();
				}
				p.Assets.SmallImageKey = key ?? p.Assets.SmallImageKey;
				p.Assets.SmallImageText = tooltip ?? p.Assets.SmallImageText;
			});
		}

		public RichPresence UpdateSecrets(Secrets secrets)
		{
			return Update(delegate(RichPresence p)
			{
				p.Secrets = secrets;
			});
		}

		public RichPresence UpdateStartTime()
		{
			return UpdateStartTime(DateTime.UtcNow);
		}

		public RichPresence UpdateStartTime(DateTime time)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Timestamps == null)
				{
					p.Timestamps = new Timestamps();
				}
				p.Timestamps.Start = time;
			});
		}

		public RichPresence UpdateEndTime()
		{
			return UpdateEndTime(DateTime.UtcNow);
		}

		public RichPresence UpdateEndTime(DateTime time)
		{
			return Update(delegate(RichPresence p)
			{
				if (p.Timestamps == null)
				{
					p.Timestamps = new Timestamps();
				}
				p.Timestamps.End = time;
			});
		}

		public RichPresence UpdateClearTime()
		{
			return Update(delegate(RichPresence p)
			{
				p.Timestamps = null;
			});
		}

		public void ClearPresence()
		{
			if (IsDisposed)
			{
				throw new ObjectDisposedException("Discord IPC Client");
			}
			if (!IsInitialized)
			{
				throw new UninitializedException();
			}
			if (connection == null)
			{
				throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized");
			}
			SetPresence(null);
		}

		public bool RegisterUriScheme(string steamAppID = null, string executable = null)
		{
			UriSchemeRegister uriSchemeRegister = new UriSchemeRegister(_logger, ApplicationID, steamAppID, executable);
			return HasRegisteredUriScheme = uriSchemeRegister.RegisterUriScheme();
		}

		public void Subscribe(EventType type)
		{
			SetSubscription(Subscription | type);
		}

		[Obsolete("Replaced with Unsubscribe", true)]
		public void Unubscribe(EventType type)
		{
			SetSubscription(Subscription & ~type);
		}

		public void Unsubscribe(EventType type)
		{
			SetSubscription(Subscription & ~type);
		}

		public void SetSubscription(EventType type)
		{
			if (IsInitialized)
			{
				SubscribeToTypes(Subscription & ~type, isUnsubscribe: true);
				SubscribeToTypes(~Subscription & type, isUnsubscribe: false);
			}
			else
			{
				Logger.Warning("Client has not yet initialized, but events are being subscribed too. Storing them as state instead.");
			}
			lock (_sync)
			{
				Subscription = type;
			}
		}

		private void SubscribeToTypes(EventType type, bool isUnsubscribe)
		{
			if (type != 0)
			{
				if (IsDisposed)
				{
					throw new ObjectDisposedException("Discord IPC Client");
				}
				if (!IsInitialized)
				{
					throw new UninitializedException();
				}
				if (connection == null)
				{
					throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized");
				}
				if (!HasRegisteredUriScheme)
				{
					throw new InvalidConfigurationException("Cannot subscribe/unsubscribe to an event as this application has not registered a URI Scheme. Call RegisterUriScheme().");
				}
				if ((type & EventType.Spectate) == EventType.Spectate)
				{
					connection.EnqueueCommand(new SubscribeCommand
					{
						Event = ServerEvent.ActivitySpectate,
						IsUnsubscribe = isUnsubscribe
					});
				}
				if ((type & EventType.Join) == EventType.Join)
				{
					connection.EnqueueCommand(new SubscribeCommand
					{
						Event = ServerEvent.ActivityJoin,
						IsUnsubscribe = isUnsubscribe
					});
				}
				if ((type & EventType.JoinRequest) == EventType.JoinRequest)
				{
					connection.EnqueueCommand(new SubscribeCommand
					{
						Event = ServerEvent.ActivityJoinRequest,
						IsUnsubscribe = isUnsubscribe
					});
				}
			}
		}

		public void SynchronizeState()
		{
			if (!IsInitialized)
			{
				throw new UninitializedException();
			}
			SetPresence(CurrentPresence);
			if (HasRegisteredUriScheme)
			{
				SubscribeToTypes(Subscription, isUnsubscribe: false);
			}
		}

		public bool Initialize()
		{
			if (IsDisposed)
			{
				throw new ObjectDisposedException("Discord IPC Client");
			}
			if (IsInitialized)
			{
				throw new UninitializedException("Cannot initialize a client that is already initialized");
			}
			if (connection == null)
			{
				throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized");
			}
			return IsInitialized = connection.AttemptConnection();
		}

		public void Deinitialize()
		{
			if (!IsInitialized)
			{
				throw new UninitializedException("Cannot deinitialize a client that has not been initalized.");
			}
			connection.Close();
			IsInitialized = false;
		}

		public void Dispose()
		{
			if (!IsDisposed)
			{
				if (IsInitialized)
				{
					Deinitialize();
				}
				IsDisposed = true;
			}
		}
	}
	[Flags]
	public enum EventType
	{
		None = 0,
		Spectate = 1,
		Join = 2,
		JoinRequest = 4
	}
	[Serializable]
	[JsonObject(/*Could not decode attribute arguments.*/)]
	public class BaseRichPresence
	{
		protected internal string _state;

		protected internal string _details;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string State
		{
			get
			{
				return _state;
			}
			set
			{
				if (!ValidateString(value, out _state, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException("State", 0, 128);
				}
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string Details
		{
			get
			{
				return _details;
			}
			set
			{
				if (!ValidateString(value, out _details, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Timestamps Timestamps { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Assets Assets { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Party Party { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Secrets Secrets { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ActivityType Type { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		[Obsolete("This was going to be used, but was replaced by JoinSecret instead")]
		private bool Instance { get; set; }

		public bool HasTimestamps()
		{
			if (Timestamps != null)
			{
				if (!Timestamps.Start.HasValue)
				{
					return Timestamps.End.HasValue;
				}
				return true;
			}
			return false;
		}

		public bool HasAssets()
		{
			return Assets != null;
		}

		public bool HasParty()
		{
			if (Party != null)
			{
				return Party.ID != null;
			}
			return false;
		}

		public bool HasSecrets()
		{
			if (Secrets != null)
			{
				if (Secrets.JoinSecret == null)
				{
					return Secrets.SpectateSecret != null;
				}
				return true;
			}
			return false;
		}

		internal static bool ValidateString(string str, out string result, int bytes, Encoding encoding)
		{
			result = str;
			if (str == null)
			{
				return true;
			}
			string str2 = str.Trim();
			if (!str2.WithinLength(bytes, encoding))
			{
				return false;
			}
			result = str2.GetNullOrString();
			return true;
		}

		public static implicit operator bool(BaseRichPresence presesnce)
		{
			return presesnce != null;
		}

		internal virtual bool Matches(RichPresence other)
		{
			if (other == null)
			{
				return false;
			}
			if (State != other.State || Details != other.Details || Type != other.Type)
			{
				return false;
			}
			if (Timestamps != null)
			{
				if (other.Timestamps == null || other.Timestamps.StartUnixMilliseconds != Timestamps.StartUnixMilliseconds || other.Timestamps.EndUnixMilliseconds != Timestamps.EndUnixMilliseconds)
				{
					return false;
				}
			}
			else if (other.Timestamps != null)
			{
				return false;
			}
			if (Secrets != null)
			{
				if (other.Secrets == null || other.Secrets.JoinSecret != Secrets.JoinSecret || other.Secrets.MatchSecret != Secrets.MatchSecret || other.Secrets.SpectateSecret != Secrets.SpectateSecret)
				{
					return false;
				}
			}
			else if (other.Secrets != null)
			{
				return false;
			}
			if (Party != null)
			{
				if (other.Party == null || other.Party.ID != Party.ID || other.Party.Max != Party.Max || other.Party.Size != Party.Size || other.Party.Privacy != Party.Privacy)
				{
					return false;
				}
			}
			else if (other.Party != null)
			{
				return false;
			}
			if (Assets != null)
			{
				if (other.Assets == null || other.Assets.LargeImageKey != Assets.LargeImageKey || other.Assets.LargeImageText != Assets.LargeImageText || other.Assets.SmallImageKey != Assets.SmallImageKey || other.Assets.SmallImageText != Assets.SmallImageText)
				{
					return false;
				}
			}
			else if (other.Assets != null)
			{
				return false;
			}
			return Instance == other.Instance;
		}

		public RichPresence ToRichPresence()
		{
			RichPresence richPresence = new RichPresence();
			richPresence.State = State;
			richPresence.Details = Details;
			richPresence.Type = Type;
			richPresence.Party = ((!HasParty()) ? Party : null);
			richPresence.Secrets = ((!HasSecrets()) ? Secrets : null);
			if (HasAssets())
			{
				richPresence.Assets = new Assets
				{
					SmallImageKey = Assets.SmallImageKey,
					SmallImageText = Assets.SmallImageText,
					LargeImageKey = Assets.LargeImageKey,
					LargeImageText = Assets.LargeImageText
				};
			}
			if (HasTimestamps())
			{
				richPresence.Timestamps = new Timestamps();
				if (Timestamps.Start.HasValue)
				{
					richPresence.Timestamps.Start = Timestamps.Start;
				}
				if (Timestamps.End.HasValue)
				{
					richPresence.Timestamps.End = Timestamps.End;
				}
			}
			return richPresence;
		}
	}
	[Serializable]
	public class Secrets
	{
		private string _matchSecret;

		private string _joinSecret;

		private string _spectateSecret;

		[Obsolete("This feature has been deprecated my Mason in issue #152 on the offical library. Was originally used as a Notify Me feature, it has been replaced with Join / Spectate.")]
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string MatchSecret
		{
			get
			{
				return _matchSecret;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _matchSecret, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string JoinSecret
		{
			get
			{
				return _joinSecret;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _joinSecret, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string SpectateSecret
		{
			get
			{
				return _spectateSecret;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _spectateSecret, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		public static Encoding Encoding => Encoding.UTF8;

		public static int SecretLength => 128;

		public static string CreateSecret(Random random)
		{
			byte[] array = new byte[SecretLength];
			random.NextBytes(array);
			return Encoding.GetString(array);
		}

		public static string CreateFriendlySecret(Random random)
		{
			string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < SecretLength; i++)
			{
				stringBuilder.Append(text[random.Next(text.Length)]);
			}
			return stringBuilder.ToString();
		}
	}
	[Serializable]
	public class Assets
	{
		private string _largeimagekey;

		private bool _islargeimagekeyexternal;

		private string _largeimagetext;

		private string _smallimagekey;

		private bool _issmallimagekeyexternal;

		private string _smallimagetext;

		private ulong? _largeimageID;

		private ulong? _smallimageID;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string LargeImageKey
		{
			get
			{
				return _largeimagekey;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _largeimagekey, 256, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(256);
				}
				_islargeimagekeyexternal = _largeimagekey?.StartsWith("mp:external/") ?? false;
				_largeimageID = null;
			}
		}

		[JsonIgnore]
		public bool IsLargeImageKeyExternal => _islargeimagekeyexternal;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string LargeImageText
		{
			get
			{
				return _largeimagetext;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _largeimagetext, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string SmallImageKey
		{
			get
			{
				return _smallimagekey;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _smallimagekey, 256, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(256);
				}
				_issmallimagekeyexternal = _smallimagekey?.StartsWith("mp:external/") ?? false;
				_smallimageID = null;
			}
		}

		[JsonIgnore]
		public bool IsSmallImageKeyExternal => _issmallimagekeyexternal;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string SmallImageText
		{
			get
			{
				return _smallimagetext;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _smallimagetext, 128, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(128);
				}
			}
		}

		[JsonIgnore]
		public ulong? LargeImageID => _largeimageID;

		[JsonIgnore]
		public ulong? SmallImageID => _smallimageID;

		internal void Merge(Assets other)
		{
			_smallimagetext = other._smallimagetext;
			_largeimagetext = other._largeimagetext;
			if (ulong.TryParse(other._largeimagekey, out var result))
			{
				_largeimageID = result;
			}
			else
			{
				_largeimagekey = other._largeimagekey;
				_largeimageID = null;
			}
			if (ulong.TryParse(other._smallimagekey, out var result2))
			{
				_smallimageID = result2;
				return;
			}
			_smallimagekey = other._smallimagekey;
			_smallimageID = null;
		}
	}
	[Serializable]
	public class Timestamps
	{
		public static Timestamps Now => new Timestamps(DateTime.UtcNow);

		[JsonIgnore]
		public DateTime? Start { get; set; }

		[JsonIgnore]
		public DateTime? End { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ulong? StartUnixMilliseconds
		{
			get
			{
				if (!Start.HasValue)
				{
					return null;
				}
				return ToUnixMilliseconds(Start.Value);
			}
			set
			{
				Start = (value.HasValue ? new DateTime?(FromUnixMilliseconds(value.Value)) : null);
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ulong? EndUnixMilliseconds
		{
			get
			{
				if (!End.HasValue)
				{
					return null;
				}
				return ToUnixMilliseconds(End.Value);
			}
			set
			{
				End = (value.HasValue ? new DateTime?(FromUnixMilliseconds(value.Value)) : null);
			}
		}

		public static Timestamps FromTimeSpan(double seconds)
		{
			return FromTimeSpan(TimeSpan.FromSeconds(seconds));
		}

		public static Timestamps FromTimeSpan(TimeSpan timespan)
		{
			return new Timestamps
			{
				Start = DateTime.UtcNow,
				End = DateTime.UtcNow + timespan
			};
		}

		public Timestamps()
		{
			Start = null;
			End = null;
		}

		public Timestamps(DateTime start)
		{
			Start = start;
			End = null;
		}

		public Timestamps(DateTime start, DateTime end)
		{
			Start = start;
			End = end;
		}

		public static DateTime FromUnixMilliseconds(ulong unixTime)
		{
			return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Convert.ToDouble(unixTime));
		}

		public static ulong ToUnixMilliseconds(DateTime date)
		{
			DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
			return Convert.ToUInt64((date - dateTime).TotalMilliseconds);
		}
	}
	[Serializable]
	public class Party
	{
		public enum PrivacySetting
		{
			Private,
			Public
		}

		private string _partyid;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string ID
		{
			get
			{
				return _partyid;
			}
			set
			{
				_partyid = value.GetNullOrString();
			}
		}

		[JsonIgnore]
		public int Size { get; set; }

		[JsonIgnore]
		public int Max { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public PrivacySetting Privacy { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		private int[] _size
		{
			get
			{
				int num = Math.Max(1, Size);
				return new int[2]
				{
					num,
					Math.Max(num, Max)
				};
			}
			set
			{
				if (value.Length != 2)
				{
					Size = 0;
					Max = 0;
				}
				else
				{
					Size = value[0];
					Max = value[1];
				}
			}
		}
	}
	public class Button
	{
		private string _label;

		private string _url;

		[JsonProperty("label")]
		public string Label
		{
			get
			{
				return _label;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _label, 32, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(32);
				}
			}
		}

		[JsonProperty("url")]
		public string Url
		{
			get
			{
				return _url;
			}
			set
			{
				if (!BaseRichPresence.ValidateString(value, out _url, 512, Encoding.UTF8))
				{
					throw new StringOutOfRangeException(512);
				}
				if (!Uri.TryCreate(_url, UriKind.Absolute, out Uri _))
				{
					throw new ArgumentException("Url must be a valid URI");
				}
			}
		}
	}
	public enum ActivityType
	{
		Playing = 0,
		Listening = 2,
		Watching = 3,
		Competing = 5
	}
	public sealed class RichPresence : BaseRichPresence
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Button[] Buttons { get; set; }

		public bool HasButtons()
		{
			if (Buttons != null)
			{
				return Buttons.Length != 0;
			}
			return false;
		}

		public RichPresence WithState(string state)
		{
			base.State = state;
			return this;
		}

		public RichPresence WithDetails(string details)
		{
			base.Details = details;
			return this;
		}

		public RichPresence WithType(ActivityType type)
		{
			base.Type = type;
			return this;
		}

		public RichPresence WithTimestamps(Timestamps timestamps)
		{
			base.Timestamps = timestamps;
			return this;
		}

		public RichPresence WithAssets(Assets assets)
		{
			base.Assets = assets;
			return this;
		}

		public RichPresence WithParty(Party party)
		{
			base.Party = party;
			return this;
		}

		public RichPresence WithSecrets(Secrets secrets)
		{
			base.Secrets = secrets;
			return this;
		}

		public RichPresence Clone()
		{
			return new RichPresence
			{
				State = ((_state != null) ? (_state.Clone() as string) : null),
				Details = ((_details != null) ? (_details.Clone() as string) : null),
				Type = base.Type,
				Buttons = ((!HasButtons()) ? null : (Buttons.Clone() as Button[])),
				Secrets = ((!HasSecrets()) ? null : new Secrets
				{
					JoinSecret = ((base.Secrets.JoinSecret != null) ? (base.Secrets.JoinSecret.Clone() as string) : null),
					SpectateSecret = ((base.Secrets.SpectateSecret != null) ? (base.Secrets.SpectateSecret.Clone() as string) : null)
				}),
				Timestamps = ((!HasTimestamps()) ? null : new Timestamps
				{
					Start = base.Timestamps.Start,
					End = base.Timestamps.End
				}),
				Assets = ((!HasAssets()) ? null : new Assets
				{
					LargeImageKey = ((base.Assets.LargeImageKey != null) ? (base.Assets.LargeImageKey.Clone() as string) : null),
					LargeImageText = ((base.Assets.LargeImageText != null) ? (base.Assets.LargeImageText.Clone() as string) : null),
					SmallImageKey = ((base.Assets.SmallImageKey != null) ? (base.Assets.SmallImageKey.Clone() as string) : null),
					SmallImageText = ((base.Assets.SmallImageText != null) ? (base.Assets.SmallImageText.Clone() as string) : null)
				}),
				Party = ((!HasParty()) ? null : new Party
				{
					ID = base.Party.ID,
					Size = base.Party.Size,
					Max = base.Party.Max,
					Privacy = base.Party.Privacy
				})
			};
		}

		internal RichPresence Merge(BaseRichPresence presence)
		{
			_state = presence.State;
			_details = presence.Details;
			base.Type = presence.Type;
			base.Party = presence.Party;
			base.Timestamps = presence.Timestamps;
			base.Secrets = presence.Secrets;
			if (presence.HasAssets())
			{
				if (!HasAssets())
				{
					base.Assets = presence.Assets;
				}
				else
				{
					base.Assets.Merge(presence.Assets);
				}
			}
			else
			{
				base.Assets = null;
			}
			return this;
		}

		internal override bool Matches(RichPresence other)
		{
			if (!base.Matches(other))
			{
				return false;
			}
			if ((Buttons == null) ^ (other.Buttons == null))
			{
				return false;
			}
			if (Buttons != null)
			{
				if (Buttons.Length != other.Buttons.Length)
				{
					return false;
				}
				for (int i = 0; i < Buttons.Length; i++)
				{
					Button button = Buttons[i];
					Button button2 = other.Buttons[i];
					if (button.Label != button2.Label || button.Url != button2.Url)
					{
						return false;
					}
				}
			}
			return true;
		}

		public static implicit operator bool(RichPresence presesnce)
		{
			return presesnce != null;
		}
	}
	internal sealed class RichPresenceResponse : BaseRichPresence
	{
		[JsonProperty("application_id")]
		public string ClientID { get; private set; }

		[JsonProperty("name")]
		public string Name { get; private set; }
	}
	public class User
	{
		public enum AvatarFormat
		{
			PNG,
			JPEG,
			WebP,
			GIF
		}

		public enum AvatarSize
		{
			x16 = 0x10,
			x32 = 0x20,
			x64 = 0x40,
			x128 = 0x80,
			x256 = 0x100,
			x512 = 0x200,
			x1024 = 0x400,
			x2048 = 0x800
		}

		[Flags]
		public enum Flag
		{
			None = 0,
			Employee = 1,
			Partner = 2,
			HypeSquad = 4,
			BugHunter = 8,
			HouseBravery = 0x40,
			HouseBrilliance = 0x80,
			HouseBalance = 0x100,
			EarlySupporter = 0x200,
			TeamUser = 0x400
		}

		public enum PremiumType
		{
			None,
			NitroClassic,
			Nitro
		}

		[JsonProperty("id")]
		public ulong ID { get; private set; }

		[JsonProperty("username")]
		public string Username { get; private set; }

		[JsonProperty("discriminator")]
		[Obsolete("Discord no longer uses discriminators.")]
		public int Discriminator { get; private set; }

		[JsonProperty("global_name")]
		public string DisplayName { get; private set; }

		[JsonProperty("avatar")]
		public string Avatar { get; private set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public Flag Flags { get; private set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public PremiumType Premium { get; private set; }

		public string CdnEndpoint { get; private set; }

		internal User()
		{
			CdnEndpoint = "cdn.discordapp.com";
		}

		internal void SetConfiguration(Configuration configuration)
		{
			CdnEndpoint = configuration.CdnHost;
		}

		public string GetAvatarURL(AvatarFormat format)
		{
			return GetAvatarURL(format, AvatarSize.x128);
		}

		public string GetAvatarURL(AvatarFormat format, AvatarSize size)
		{
			string text = $"/avatars/{ID}/{Avatar}";
			if (string.IsNullOrEmpty(Avatar))
			{
				if (format != 0)
				{
					throw new BadImageFormatException("The user has no avatar and the requested format " + format.ToString() + " is not supported. (Only supports PNG).");
				}
				int num = (int)((ID >> 22) % 6);
				if (Discriminator > 0)
				{
					num = Discriminator % 5;
				}
				text = $"/embed/avatars/{num}";
			}
			return $"https://{CdnEndpoint}{text}{GetAvatarExtension(format)}?size={(int)size}";
		}

		public string GetAvatarExtension(AvatarFormat format)
		{
			return "." + format.ToString().ToLowerInvariant();
		}

		public override string ToString()
		{
			if (!string.IsNullOrEmpty(DisplayName))
			{
				return DisplayName;
			}
			if (Discriminator != 0)
			{
				return Username + "#" + Discriminator.ToString("D4");
			}
			return Username;
		}
	}
}
namespace DiscordRPC.RPC
{
	internal class RpcConnection : IDisposable
	{
		public static readonly int VERSION = 1;

		public static readonly int POLL_RATE = 1000;

		private static readonly bool CLEAR_ON_SHUTDOWN = true;

		private static readonly bool LOCK_STEP = false;

		private ILogger _logger;

		private RpcState _state;

		private readonly object l_states = new object();

		private Configuration _configuration;

		private readonly object l_config = new object();

		private volatile bool aborting;

		private volatile bool shutdown;

		private string applicationID;

		private int processID;

		private long nonce;

		private Thread thread;

		private INamedPipeClient namedPipe;

		private int targetPipe;

		private readonly object l_rtqueue = new object();

		private readonly uint _maxRtQueueSize;

		private Queue<ICommand> _rtqueue;

		private readonly object l_rxqueue = new object();

		private readonly uint _maxRxQueueSize;

		private Queue<IMessage> _rxqueue;

		private AutoResetEvent queueUpdatedEvent = new AutoResetEvent(initialState: false);

		private BackoffDelay delay;

		public ILogger Logger
		{
			get
			{
				return _logger;
			}
			set
			{
				_logger = value;
				if (namedPipe != null)
				{
					namedPipe.Logger = value;
				}
			}
		}

		public RpcState State
		{
			get
			{
				lock (l_states)
				{
					return _state;
				}
			}
		}

		public Configuration Configuration
		{
			get
			{
				Configuration configuration = null;
				lock (l_config)
				{
					return _configuration;
				}
			}
		}

		public bool IsRunning => thread != null;

		public bool ShutdownOnly { get; set; }

		public event OnRpcMessageEvent OnRpcMessage;

		public RpcConnection(string applicationID, int processID, int targetPipe, INamedPipeClient client, uint maxRxQueueSize = 128u, uint maxRtQueueSize = 512u)
		{
			this.applicationID = applicationID;
			this.processID = processID;
			this.targetPipe = targetPipe;
			namedPipe = client;
			ShutdownOnly = true;
			Logger = new ConsoleLogger();
			delay = new BackoffDelay(500, 60000);
			_maxRtQueueSize = maxRtQueueSize;
			_rtqueue = new Queue<ICommand>((int)(_maxRtQueueSize + 1));
			_maxRxQueueSize = maxRxQueueSize;
			_rxqueue = new Queue<IMessage>((int)(_maxRxQueueSize + 1));
			nonce = 0L;
		}

		private long GetNextNonce()
		{
			nonce++;
			return nonce;
		}

		internal void EnqueueCommand(ICommand command)
		{
			Logger.Trace("Enqueue Command: {0}", command.GetType().FullName);
			if (aborting || shutdown)
			{
				return;
			}
			lock (l_rtqueue)
			{
				if (_rtqueue.Count == _maxRtQueueSize)
				{
					Logger.Error("Too many enqueued commands, dropping oldest one. Maybe you are pushing new presences to fast?");
					_rtqueue.Dequeue();
				}
				_rtqueue.Enqueue(command);
			}
		}

		private void EnqueueMessage(IMessage message)
		{
			try
			{
				if (this.OnRpcMessage != null)
				{
					this.OnRpcMessage(this, message);
				}
			}
			catch (Exception ex)
			{
				Logger.Error("Unhandled Exception while processing event: {0}", ex.GetType().FullName);
				Logger.Error(ex.Message);
				Logger.Error(ex.StackTrace);
			}
			if (_maxRxQueueSize == 0)
			{
				Logger.Trace("Enqueued Message, but queue size is 0.");
				return;
			}
			Logger.Trace("Enqueue Message: {0}", message.Type);
			lock (l_rxqueue)
			{
				if (_rxqueue.Count == _maxRxQueueSize)
				{
					Logger.Warning("Too many enqueued messages, dropping oldest one.");
					_rxqueue.Dequeue();
				}
				_rxqueue.Enqueue(message);
			}
		}

		internal IMessage DequeueMessage()
		{
			lock (l_rxqueue)
			{
				if (_rxqueue.Count == 0)
				{
					return null;
				}
				return _rxqueue.Dequeue();
			}
		}

		internal IMessage[] DequeueMessages()
		{
			lock (l_rxqueue)
			{
				IMessage[] result = _rxqueue.ToArray();
				_rxqueue.Clear();
				return result;
			}
		}

		private void MainLoop()
		{
			Logger.Info("RPC Connection Started");
			if (Logger.Level <= LogLevel.Trace)
			{
				Logger.Trace("============================");
				Logger.Trace("Assembly:             " + Assembly.GetAssembly(typeof(RichPresence)).FullName);
				Logger.Trace("Pipe:                 " + namedPipe.GetType().FullName);
				Logger.Trace("Platform:             " + Environment.OSVersion.ToString());
				Logger.Trace("applicationID:        " + applicationID);
				Logger.Trace("targetPipe:           " + targetPipe);
				ILogger logger = Logger;
				int pOLL_RATE = POLL_RATE;
				logger.Trace("POLL_RATE:            " + pOLL_RATE);
				ILogger logger2 = Logger;
				uint maxRtQueueSize = _maxRtQueueSize;
				logger2.Trace("_maxRtQueueSize:      " + maxRtQueueSize);
				ILogger logger3 = Logger;
				maxRtQueueSize = _maxRxQueueSize;
				logger3.Trace("_maxRxQueueSize:      " + maxRtQueueSize);
				Logger.Trace("============================");
			}
			while (!aborting && !shutdown)
			{
				try
				{
					if (namedPipe == null)
					{
						Logger.Error("Something bad has happened with our pipe client!");
						aborting = true;
						return;
					}
					Logger.Trace("Connecting to the pipe through the {0}", namedPipe.GetType().FullName);
					if (namedPipe.Connect(targetPipe))
					{
						Logger.Trace("Connected to the pipe. Attempting to establish handshake...");
						EnqueueMessage(new ConnectionEstablishedMessage
						{
							ConnectedPipe = namedPipe.ConnectedPipe
						});
						EstablishHandshake();
						Logger.Trace("Connection Established. Starting reading loop...");
						bool flag = true;
						while (flag && !aborting && !shutdown && namedPipe.IsConnected)
						{
							if (namedPipe.ReadFrame(out var frame))
							{
								Logger.Trace("Read Payload: {0}", frame.Opcode);
								switch (frame.Opcode)
								{
								case Opcode.Close:
								{
									ClosePayload @object = frame.GetObject<ClosePayload>();
									Logger.Warning("We have been told to terminate by discord: ({0}) {1}", @object.Code, @object.Reason);
									EnqueueMessage(new CloseMessage
									{
										Code = @object.Code,
										Reason = @object.Reason
									});
									flag = false;
									break;
								}
								case Opcode.Ping:
									Logger.Trace("PING");
									frame.Opcode = Opcode.Pong;
									namedPipe.WriteFrame(frame);
									break;
								case Opcode.Pong:
									Logger.Trace("PONG");
									break;
								case Opcode.Frame:
								{
									if (shutdown)
									{
										Logger.Warning("Skipping frame because we are shutting down.");
										break;
									}
									if (frame.Data == null)
									{
										Logger.Error("We received no data from the frame so we cannot get the event payload!");
										break;
									}
									EventPayload eventPayload = null;
									try
									{
										eventPayload = frame.GetObject<EventPayload>();
									}
									catch (Exception ex)
									{
										Logger.Error("Failed to parse event! {0}", ex.Message);
										Logger.Error("Data: {0}", frame.Message);
									}
									try
									{
										if (eventPayload != null)
										{
											ProcessFrame(eventPayload);
										}
									}
									catch (Exception ex2)
									{
										Logger.Error("Failed to process event! {0}", ex2.Message);
										Logger.Error("Data: {0}", frame.Message);
									}
									break;
								}
								default:
									Logger.Error("Invalid opcode: {0}", frame.Opcode);
									flag = false;
									break;
								}
							}
							if (!aborting && namedPipe.IsConnected)
							{
								ProcessCommandQueue();
								queueUpdatedEvent.WaitOne(POLL_RATE);
							}
						}
						Logger.Trace("Left main read loop for some reason. Aborting: {0}, Shutting Down: {1}", aborting, shutdown);
					}
					else
					{
						Logger.Error("Failed to connect for some reason.");
						EnqueueMessage(new ConnectionFailedMessage
						{
							FailedPipe = targetPipe
						});
					}
					if (!aborting && !shutdown)
					{
						long num = delay.NextDelay();
						Logger.Trace("Waiting {0}ms before attempting to connect again", num);
						Thread.Sleep(delay.NextDelay());
					}
				}
				catch (Exception ex3)
				{
					Logger.Error("Unhandled Exception: {0}", ex3.GetType().FullName);
					Logger.Error(ex3.Message);
					Logger.Error(ex3.StackTrace);
				}
				finally
				{
					if (namedPipe.IsConnected)
					{
						Logger.Trace("Closing the named pipe.");
						namedPipe.Close();
					}
					SetConnectionState(RpcState.Disconnected);
				}
			}
			Logger.Trace("Left Main Loop");
			if (namedPipe != null)
			{
				namedPipe.Dispose();
			}
			Logger.Info("Thread Terminated, no longer performing RPC connection.");
		}

		private void ProcessFrame(EventPayload response)
		{
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			Logger.Info("Handling Response. Cmd: {0}, Event: {1}", response.Command, response.Event);
			if (response.Event.HasValue && response.Event.Value == ServerEvent.Error)
			{
				Logger.Error("Error received from the RPC");
				ErrorMessage @object = response.GetObject<ErrorMessage>();
				Logger.Error("Server responded with an error message: ({0}) {1}", @object.Code.ToString(), @object.Message);
				EnqueueMessage(@object);
			}
			else if (State == RpcState.Connecting && response.Command == Command.Dispatch && response.Event.HasValue && response.Event.Value == ServerEvent.Ready)
			{
				Logger.Info("Connection established with the RPC");
				SetConnectionState(RpcState.Connected);
				delay.Reset();
				ReadyMessage object2 = response.GetObject<ReadyMessage>();
				lock (l_config)
				{
					_configuration = object2.Configuration;
					object2.User.SetConfiguration(_configuration);
				}
				EnqueueMessage(object2);
			}
			else if (State == RpcState.Connected)
			{
				switch (response.Command)
				{
				case Command.Dispatch:
					ProcessDispatch(response);
					break;
				case Command.SetActivity:
				{
					if (response.Data == null)
					{
						EnqueueMessage(new PresenceMessage());
						break;
					}
					RichPresenceResponse object3 = response.GetObject<RichPresenceResponse>();
					EnqueueMessage(new PresenceMessage(object3));
					break;
				}
				case Command.Subscribe:
				case Command.Unsubscribe:
				{
					((Collection<JsonConverter>)(object)new JsonSerializer().Converters).Add((JsonConverter)(object)new EnumSnakeCaseConverter());
					ServerEvent value = response.GetObject<EventPayload>().Event.Value;
					if (response.Command == Command.Subscribe)
					{
						EnqueueMessage(new SubscribeMessage(value));
					}
					else
					{
						EnqueueMessage(new UnsubscribeMessage(value));
					}
					break;
				}
				case Command.SendActivityJoinInvite:
					Logger.Trace("Got invite response ack.");
					break;
				case Command.CloseActivityJoinRequest:
					Logger.Trace("Got invite response reject ack.");
					break;
				default:
					Logger.Error("Unkown frame was received! {0}", response.Command);
					break;
				}
			}
			else
			{
				Logger.Trace("Received a frame while we are disconnected. Ignoring. Cmd: {0}, Event: {1}", response.Command, response.Event);
			}
		}

		private void ProcessDispatch(EventPayload response)
		{
			if (response.Command == Command.Dispatch && response.Event.HasValue)
			{
				switch (response.Event.Value)
				{
				case ServerEvent.ActivitySpectate:
				{
					SpectateMessage object3 = response.GetObject<SpectateMessage>();
					EnqueueMessage(object3);
					break;
				}
				case ServerEvent.ActivityJoin:
				{
					JoinMessage object2 = response.GetObject<JoinMessage>();
					EnqueueMessage(object2);
					break;
				}
				case ServerEvent.ActivityJoinRequest:
				{
					JoinRequestMessage @object = response.GetObject<JoinRequestMessage>();
					EnqueueMessage(@object);
					break;
				}
				default:
					Logger.Warning("Ignoring {0}", response.Event.Value);
					break;
				}
			}
		}

		private void ProcessCommandQueue()
		{
			if (State != RpcState.Connected)
			{
				return;
			}
			if (aborting)
			{
				Logger.Warning("We have been told to write a queue but we have also been aborted.");
			}
			bool flag = true;
			ICommand command = null;
			while (flag && namedPipe.IsConnected)
			{
				lock (l_rtqueue)
				{
					flag = _rtqueue.Count > 0;
					if (!flag)
					{
						break;
					}
					command = _rtqueue.Peek();
				}
				if (shutdown || (!aborting && LOCK_STEP))
				{
					flag = false;
				}
				IPayload payload = command.PreparePayload(GetNextNonce());
				Logger.Trace("Attempting to send payload: {0}", payload.Command);
				PipeFrame frame = default(PipeFrame);
				if (command is CloseCommand)
				{
					SendHandwave();
					Logger.Trace("Handwave sent, ending queue processing.");
					lock (l_rtqueue)
					{
						_rtqueue.Dequeue();
						break;
					}
				}
				if (aborting)
				{
					Logger.Warning("- skipping frame because of abort.");
					lock (l_rtqueue)
					{
						_rtqueue.Dequeue();
					}
					continue;
				}
				frame.SetObject(Opcode.Frame, payload);
				Logger.Trace("Sending payload: {0}", payload.Command);
				if (namedPipe.WriteFrame(frame))
				{
					Logger.Trace("Sent Successfully.");
					lock (l_rtqueue)
					{
						_rtqueue.Dequeue();
					}
					continue;
				}
				Logger.Warning("Something went wrong during writing!");
				break;
			}
		}

		private void EstablishHandshake()
		{
			Logger.Trace("Attempting to establish a handshake...");
			if (State != 0)
			{
				Logger.Error("State must be disconnected in order to start a handshake!");
				return;
			}
			Logger.Trace("Sending Handshake...");
			if (!namedPipe.WriteFrame(new PipeFrame(Opcode.Handshake, new Handshake
			{
				Version = VERSION,
				ClientID = applicationID
			})))
			{
				Logger.Error("Failed to write a handshake.");
			}
			else
			{
				SetConnectionState(RpcState.Connecting);
			}
		}

		private void SendHandwave()
		{
			Logger.Info("Attempting to wave goodbye...");
			if (State == RpcState.Disconnected)
			{
				Logger.Error("State must NOT be disconnected in order to send a handwave!");
			}
			else if (!namedPipe.WriteFrame(new PipeFrame(Opcode.Close, new Handshake
			{
				Version = VERSION,
				ClientID = applicationID
			})))
			{
				Logger.Error("failed to write a handwave.");
			}
		}

		public bool AttemptConnection()
		{
			Logger.Info("Attempting a new connection");
			if (thread != null)
			{
				Logger.Error("Cannot attempt a new connection as the previous connection thread is not null!");
				return false;
			}
			if (State != 0)
			{
				Logger.Warning("Cannot attempt a new connection as the previous connection hasn't changed state yet.");
				return false;
			}
			if (aborting)
			{
				Logger.Error("Cannot attempt a new connection while aborting!");
				return false;
			}
			thread = new Thread(MainLoop);
			thread.Name = "Discord IPC Thread";
			thread.IsBackground = true;
			thread.Start();
			return true;
		}

		private void SetConnectionState(RpcState state)
		{
			Logger.Trace("Setting the connection state to {0}", state.ToString().ToSnakeCase().ToUpperInvariant());
			lock (l_states)
			{
				_state = state;
			}
		}

		public void Shutdown()
		{
			Logger.Trace("Initiated shutdown procedure");
			shutdown = true;
			lock (l_rtqueue)
			{
				_rtqueue.Clear();
				if (CLEAR_ON_SHUTDOWN)
				{
					_rtqueue.Enqueue(new PresenceCommand
					{
						PID = processID,
						Presence = null
					});
				}
				_rtqueue.Enqueue(new CloseCommand());
			}
			queueUpdatedEvent.Set();
		}

		public void Close()
		{
			if (thread == null)
			{
				Logger.Error("Cannot close as it is not available!");
				return;
			}
			if (aborting)
			{
				Logger.Error("Cannot abort as it has already been aborted");
				return;
			}
			if (ShutdownOnly)
			{
				Shutdown();
				return;
			}
			Logger.Trace("Updating Abort State...");
			aborting = true;
			queueUpdatedEvent.Set();
		}

		public void Dispose()
		{
			ShutdownOnly = false;
			Close();
		}
	}
	internal enum RpcState
	{
		Disconnected,
		Connecting,
		Connected
	}
}
namespace DiscordRPC.RPC.Payload
{
	internal class ClosePayload : IPayload
	{
		[JsonProperty("code")]
		public int Code { get; set; }

		[JsonProperty("message")]
		public string Reason { get; set; }

		[JsonConstructor]
		public ClosePayload()
		{
			Code = -1;
			Reason = "";
		}
	}
	internal enum Command
	{
		[EnumValue("DISPATCH")]
		Dispatch,
		[EnumValue("SET_ACTIVITY")]
		SetActivity,
		[EnumValue("SUBSCRIBE")]
		Subscribe,
		[EnumValue("UNSUBSCRIBE")]
		Unsubscribe,
		[EnumValue("SEND_ACTIVITY_JOIN_INVITE")]
		SendActivityJoinInvite,
		[EnumValue("CLOSE_ACTIVITY_JOIN_REQUEST")]
		CloseActivityJoinRequest,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		Authorize,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		Authenticate,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetGuild,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetGuilds,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetChannel,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetChannels,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		SetUserVoiceSettings,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		SelectVoiceChannel,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetSelectedVoiceChannel,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		SelectTextChannel,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		GetVoiceSettings,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		SetVoiceSettings,
		[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
		CaptureShortcut
	}
	internal abstract class IPayload
	{
		[JsonProperty("cmd")]
		[JsonConverter(typeof(EnumSnakeCaseConverter))]
		public Command Command { get; set; }

		[JsonProperty("nonce")]
		public string Nonce { get; set; }

		protected IPayload()
		{
		}

		protected IPayload(long nonce)
		{
			Nonce = nonce.ToString();
		}

		public override string ToString()
		{
			return $"Payload || Command: {Command}, Nonce: {Nonce}";
		}
	}
	internal class ArgumentPayload : IPayload
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public JObject Arguments { get; set; }

		public ArgumentPayload()
		{
			Arguments = null;
		}

		public ArgumentPayload(long nonce)
			: base(nonce)
		{
			Arguments = null;
		}

		public ArgumentPayload(object args, long nonce)
			: base(nonce)
		{
			SetObject(args);
		}

		public void SetObject(object obj)
		{
			Arguments = JObject.FromObject(obj);
		}

		public T GetObject<T>()
		{
			return ((JToken)Arguments).ToObject<T>();
		}

		public override string ToString()
		{
			return "Argument " + base.ToString();
		}
	}
	internal class EventPayload : IPayload
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public JObject Data { get; set; }

		[JsonProperty("evt")]
		[JsonConverter(typeof(EnumSnakeCaseConverter))]
		public ServerEvent? Event { get; set; }

		public EventPayload()
		{
			Data = null;
		}

		public EventPayload(long nonce)
			: base(nonce)
		{
			Data = null;
		}

		public T GetObject<T>()
		{
			if (Data == null)
			{
				return default(T);
			}
			return ((JToken)Data).ToObject<T>();
		}

		public override string ToString()
		{
			return "Event " + base.ToString() + ", Event: " + (Event.HasValue ? Event.ToString() : "N/A");
		}
	}
	internal enum ServerEvent
	{
		[EnumValue("READY")]
		Ready,
		[EnumValue("ERROR")]
		Error,
		[EnumValue("ACTIVITY_JOIN")]
		ActivityJoin,
		[EnumValue("ACTIVITY_SPECTATE")]
		ActivitySpectate,
		[EnumValue("ACTIVITY_JOIN_REQUEST")]
		ActivityJoinRequest
	}
}
namespace DiscordRPC.RPC.Commands
{
	internal class CloseCommand : ICommand
	{
		[JsonProperty("close_reason")]
		public string value = "Unity 5.5 doesn't handle thread aborts. Can you please close me discord?";

		[JsonProperty("pid")]
		public int PID { get; set; }

		public IPayload PreparePayload(long nonce)
		{
			return new ArgumentPayload
			{
				Command = Command.Dispatch,
				Nonce = null,
				Arguments = null
			};
		}
	}
	internal interface ICommand
	{
		IPayload PreparePayload(long nonce);
	}
	internal class PresenceCommand : ICommand
	{
		[JsonProperty("pid")]
		public int PID { get; set; }

		[JsonProperty("activity")]
		public RichPresence Presence { get; set; }

		public IPayload PreparePayload(long nonce)
		{
			return new ArgumentPayload(this, nonce)
			{
				Command = Command.SetActivity
			};
		}
	}
	internal class RespondCommand : ICommand
	{
		[JsonProperty("user_id")]
		public string UserID { get; set; }

		[JsonIgnore]
		public bool Accept { get; set; }

		public IPayload PreparePayload(long nonce)
		{
			return new ArgumentPayload(this, nonce)
			{
				Command = (Accept ? Command.SendActivityJoinInvite : Command.CloseActivityJoinRequest)
			};
		}
	}
	internal class SubscribeCommand : ICommand
	{
		public ServerEvent Event { get; set; }

		public bool IsUnsubscribe { get; set; }

		public IPayload PreparePayload(long nonce)
		{
			return new EventPayload(nonce)
			{
				Command = (IsUnsubscribe ? Command.Unsubscribe : Command.Subscribe),
				Event = Event
			};
		}
	}
}
namespace DiscordRPC.Registry
{
	internal interface IUriSchemeCreator
	{
		bool RegisterUriScheme(UriSchemeRegister register);
	}
	internal class MacUriSchemeCreator : IUriSchemeCreator
	{
		private ILogger logger;

		public MacUriSchemeCreator(ILogger logger)
		{
			this.logger = logger;
		}

		public bool RegisterUriScheme(UriSchemeRegister register)
		{
			string executablePath = register.ExecutablePath;
			if (string.IsNullOrEmpty(executablePath))
			{
				logger.Error("Failed to register because the application could not be located.");
				return false;
			}
			logger.Trace("Registering Steam Command");
			string text = executablePath;
			if (register.UsingSteamApp)
			{
				text = "steam://rungameid/" + register.SteamAppID;
			}
			else
			{
				logger.Warning("This library does not fully support MacOS URI Scheme Registration.");
			}
			string text2 = "~/Library/Application Support/discord/games";
			if (!Directory.CreateDirectory(text2).Exists)
			{
				logger.Error("Failed to register because {0} does not exist", text2);
				return false;
			}
			string text3 = text2 + "/" + register.ApplicationID + ".json";
			File.WriteAllText(text3, "{ \"command\": \"" + text + "\" }");
			logger.Trace("Registered {0}, {1}", text3, text);
			return true;
		}
	}
	internal class UnixUriSchemeCreator : IUriSchemeCreator
	{
		private ILogger logger;

		public UnixUriSchemeCreator(ILogger logger)
		{
			this.logger = logger;
		}

		public bool RegisterUriScheme(UriSchemeRegister register)
		{
			string environmentVariable = Environment.GetEnvironmentVariable("HOME");
			if (string.IsNullOrEmpty(environmentVariable))
			{
				logger.Error("Failed to register because the HOME variable was not set.");
				return false;
			}
			string executablePath = register.ExecutablePath;
			if (string.IsNullOrEmpty(executablePath))
			{
				logger.Error("Failed to register because the application was not located.");
				return false;
			}
			string text = null;
			text = ((!register.UsingSteamApp) ? executablePath : ("xdg-open steam://rungameid/" + register.SteamAppID));
			string text2 = $"[Desktop Entry]\nName=Game {register.ApplicationID}\nExec={text} %u\nType=Application\nNoDisplay=true\nCategories=Discord;Games;\nMimeType=x-scheme-handler/discord-{register.ApplicationID}";
			string text3 = "/discord-" + register.ApplicationID + ".desktop";
			string text4 = environmentVariable + "/.local/share/applications";
			if (!Directory.CreateDirectory(text4).Exists)
			{
				logger.Error("Failed to register because {0} does not exist", text4);
				return false;
			}
			File.WriteAllText(text4 + text3, text2);
			if (!RegisterMime(register.ApplicationID))
			{
				logger.Error("Failed to register because the Mime failed.");
				return false;
			}
			logger.Trace("Registered {0}, {1}, {2}", text4 + text3, text2, text);
			return true;
		}

		private bool RegisterMime(string appid)
		{
			string arguments = string.Format("default discord-{0}.desktop x-scheme-handler/discord-{0}", appid);
			Process process = Process.Start("xdg-mime", arguments);
			process.WaitForExit();
			return process.ExitCode >= 0;
		}
	}
	internal class UriSchemeRegister
	{
		private ILogger _logger;

		public string ApplicationID { get; set; }

		public string SteamAppID { get; set; }

		public bool UsingSteamApp
		{
			get
			{
				if (!string.IsNullOrEmpty(SteamAppID))
				{
					return SteamAppID != "";
				}
				return false;
			}
		}

		public string ExecutablePath { get; set; }

		public UriSchemeRegister(ILogger logger, string applicationID, string steamAppID = null, string executable = null)
		{
			_logger = logger;
			ApplicationID = applicationID.Trim();
			SteamAppID = steamAppID?.Trim();
			ExecutablePath = executable ?? GetApplicationLocation();
		}

		public bool RegisterUriScheme()
		{
			IUriSchemeCreator uriSchemeCreator = null;
			switch (Environment.OSVersion.Platform)
			{
			case PlatformID.Win32S:
			case PlatformID.Win32Windows:
			case PlatformID.Win32NT:
			case PlatformID.WinCE:
				_logger.Trace("Creating Windows Scheme Creator");
				uriSchemeCreator = new WindowsUriSchemeCreator(_logger);
				break;
			case PlatformID.Unix:
				if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
				{
					_logger.Trace("Creating MacOSX Scheme Creator");
					uriSchemeCreator = new MacUriSchemeCreator(_logger);
				}
				else
				{
					_logger.Trace("Creating Unix Scheme Creator");
					uriSchemeCreator = new UnixUriSchemeCreator(_logger);
				}
				break;
			default:
				_logger.Error("Unkown Platform: {0}", Environment.OSVersion.Platform);
				throw new PlatformNotSupportedException("Platform does not support registration.");
			}
			if (uriSchemeCreator.RegisterUriScheme(this))
			{
				_logger.Info("URI scheme registered.");
				return true;
			}
			return false;
		}

		public static string GetApplicationLocation()
		{
			return Process.GetCurrentProcess().MainModule.FileName;
		}
	}
	internal class WindowsUriSchemeCreator : IUriSchemeCreator
	{
		private ILogger logger;

		public WindowsUriSchemeCreator(ILogger logger)
		{
			this.logger = logger;
		}

		public bool RegisterUriScheme(UriSchemeRegister register)
		{
			if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
			{
				throw new PlatformNotSupportedException("URI schemes can only be registered on Windows");
			}
			string executablePath = register.ExecutablePath;
			if (executablePath == null)
			{
				logger.Error("Failed to register application because the location was null.");
				return false;
			}
			string scheme = "discord-" + register.ApplicationID;
			string friendlyName = "Run game " + register.ApplicationID + " protocol";
			string defaultIcon = executablePath;
			string command = executablePath;
			if (register.UsingSteamApp)
			{
				string steamLocation = GetSteamLocation();
				if (steamLocation != null)
				{
					command = $"\"{steamLocation}\" steam://rungameid/{register.SteamAppID}";
				}
			}
			CreateUriScheme(scheme, friendlyName, defaultIcon, command);
			return true;
		}

		private void CreateUriScheme(string scheme, string friendlyName, string defaultIcon, string command)
		{
			using (RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\" + scheme))
			{
				registryKey.SetValue("", "URL:" + friendlyName);
				registryKey.SetValue("URL Protocol", "");
				using (RegistryKey registryKey2 = registryKey.CreateSubKey("DefaultIcon"))
				{
					registryKey2.SetValue("", defaultIcon);
				}
				using RegistryKey registryKey3 = registryKey.CreateSubKey("shell\\open\\command");
				registryKey3.SetValue("", command);
			}
			logger.Trace("Registered {0}, {1}, {2}", scheme, friendlyName, command);
		}

		public string GetSteamLocation()
		{
			using RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam");
			if (registryKey == null)
			{
				return null;
			}
			return registryKey.GetValue("SteamExe") as string;
		}
	}
}
namespace DiscordRPC.Message
{
	public class CloseMessage : IMessage
	{
		public override MessageType Type => MessageType.Close;

		public string Reason { get; internal set; }

		public int Code { get; internal set; }

		internal CloseMessage()
		{
		}

		internal CloseMessage(string reason)
		{
			Reason = reason;
		}
	}
	public class ConnectionEstablishedMessage : IMessage
	{
		public override MessageType Type => MessageType.ConnectionEstablished;

		public int ConnectedPipe { get; internal set; }
	}
	public class ConnectionFailedMessage : IMessage
	{
		public override MessageType Type => MessageType.ConnectionFailed;

		public int FailedPipe { get; internal set; }
	}
	public class ErrorMessage : IMessage
	{
		public override MessageType Type => MessageType.Error;

		[JsonProperty("code")]
		public ErrorCode Code { get; internal set; }

		[JsonProperty("message")]
		public string Message { get; internal set; }
	}
	public enum ErrorCode
	{
		Success = 0,
		PipeException = 1,
		ReadCorrupt = 2,
		NotImplemented = 10,
		UnkownError = 1000,
		InvalidPayload = 4000,
		InvalidCommand = 4002,
		InvalidEvent = 4004
	}
	public abstract class IMessage
	{
		private DateTime _timecreated;

		public abstract MessageType Type { get; }

		public DateTime TimeCreated => _timecreated;

		public IMessage()
		{
			_timecreated = DateTime.Now;
		}
	}
	public class JoinMessage : IMessage
	{
		public override MessageType Type => MessageType.Join;

		[JsonProperty("secret")]
		public string Secret { get; internal set; }
	}
	public class JoinRequestMessage : IMessage
	{
		public override MessageType Type => MessageType.JoinRequest;

		[JsonProperty("user")]
		public User User { get; internal set; }
	}
	public enum MessageType
	{
		Ready,
		Close,
		Error,
		PresenceUpdate,
		Subscribe,
		Unsubscribe,
		Join,
		Spectate,
		JoinRequest,
		ConnectionEstablished,
		ConnectionFailed
	}
	public class PresenceMessage : IMessage
	{
		public override MessageType Type => MessageType.PresenceUpdate;

		public BaseRichPresence Presence { get; internal set; }

		public string Name { get; internal set; }

		public string ApplicationID { get; internal set; }

		internal PresenceMessage()
			: this(null)
		{
		}

		internal PresenceMessage(RichPresenceResponse rpr)
		{
			if (rpr == null)
			{
				Presence = null;
				Name = "No Rich Presence";
				ApplicationID = "";
			}
			else
			{
				Presence = rpr;
				Name = rpr.Name;
				ApplicationID = rpr.ClientID;
			}
		}
	}
	public class ReadyMessage : IMessage
	{
		public override MessageType Type => MessageType.Ready;

		[JsonProperty("config")]
		public Configuration Configuration { get; set; }

		[JsonProperty("user")]
		public User User { get; set; }

		[JsonProperty("v")]
		public int Version { get; set; }
	}
	public class SpectateMessage : JoinMessage
	{
		public override MessageType Type => MessageType.Spectate;
	}
	public class SubscribeMessage : IMessage
	{
		public override MessageType Type => MessageType.Subscribe;

		public EventType Event { get; internal set; }

		internal SubscribeMessage(ServerEvent evt)
		{
			switch (evt)
			{
			default:
				Event = EventType.Join;
				break;
			case ServerEvent.ActivityJoinRequest:
				Event = EventType.JoinRequest;
				break;
			case ServerEvent.ActivitySpectate:
				Event = EventType.Spectate;
				break;
			}
		}
	}
	public class UnsubscribeMessage : IMessage
	{
		public override MessageType Type => MessageType.Unsubscribe;

		public EventType Event { get; internal set; }

		internal UnsubscribeMessage(ServerEvent evt)
		{
			switch (evt)
			{
			default:
				Event = EventType.Join;
				break;
			case ServerEvent.ActivityJoinRequest:
				Event = EventType.JoinRequest;
				break;
			case ServerEvent.ActivitySpectate:
				Event = EventType.Spectate;
				break;
			}
		}
	}
}
namespace DiscordRPC.Logging
{
	public class ConsoleLogger : ILogger
	{
		public LogLevel Level { get; set; }

		public bool Coloured { get; set; }

		[Obsolete("Use Coloured")]
		public bool Colored
		{
			get
			{
				return Coloured;
			}
			set
			{
				Coloured = value;
			}
		}

		public ConsoleLogger()
		{
			Level = LogLevel.Info;
			Coloured = false;
		}

		public ConsoleLogger(LogLevel level)
			: this()
		{
			Level = level;
		}

		public ConsoleLogger(LogLevel level, bool coloured)
		{
			Level = level;
			Coloured = coloured;
		}

		public void Trace(string message, params object[] args)
		{
			if (Level <= LogLevel.Trace)
			{
				if (Coloured)
				{
					Console.ForegroundColor = ConsoleColor.Gray;
				}
				string text = "TRACE: " + message;
				if (args.Length != 0)
				{
					Console.WriteLine(text, args);
				}
				else
				{
					Console.WriteLine(text);
				}
			}
		}

		public void Info(string message, params object[] args)
		{
			if (Level <= LogLevel.Info)
			{
				if (Coloured)
				{
					Console.ForegroundColor = ConsoleColor.White;
				}
				string text = "INFO: " + message;
				if (args.Length != 0)
				{
					Console.WriteLine(text, args);
				}
				else
				{
					Console.WriteLine(text);
				}
			}
		}

		public void Warning(string message, params object[] args)
		{
			if (Level <= LogLevel.Warning)
			{
				if (Coloured)
				{
					Console.ForegroundColor = ConsoleColor.Yellow;
				}
				string text = "WARN: " + message;
				if (args.Length != 0)
				{
					Console.WriteLine(text, args);
				}
				else
				{
					Console.WriteLine(text);
				}
			}
		}

		public void Error(string message, params object[] args)
		{
			if (Level <= LogLevel.Error)
			{
				if (Coloured)
				{
					Console.ForegroundColor = ConsoleColor.Red;
				}
				string text = "ERR : " + message;
				if (args.Length != 0)
				{
					Console.WriteLine(text, args);
				}
				else
				{
					Console.WriteLine(text);
				}
			}
		}
	}
	public class FileLogger : ILogger
	{
		private object filelock;

		public LogLevel Level { get; set; }

		public string File { get; set; }

		public FileLogger(string path)
			: this(path, LogLevel.Info)
		{
		}

		public FileLogger(string path, LogLevel level)
		{
			Level = level;
			File = path;
			filelock = new object();
		}

		public void Trace(string message, params object[] args)
		{
			if (Level > LogLevel.Trace)
			{
				return;
			}
			lock (filelock)
			{
				System.IO.File.AppendAllText(File, "\r\nTRCE: " + ((args.Length != 0) ? string.Format(message, args) : message));
			}
		}

		public void Info(string message, params object[] args)
		{
			if (Level > LogLevel.Info)
			{
				return;
			}
			lock (filelock)
			{
				System.IO.File.AppendAllText(File, "\r\nINFO: " + ((args.Length != 0) ? string.Format(message, args) : message));
			}
		}

		public void Warning(string message, params object[] args)
		{
			if (Level > LogLevel.Warning)
			{
				return;
			}
			lock (filelock)
			{
				System.IO.File.AppendAllText(File, "\r\nWARN: " + ((args.Length != 0) ? string.Format(message, args) : message));
			}
		}

		public void Error(string message, params object[] args)
		{
			if (Level > LogLevel.Error)
			{
				return;
			}
			lock (filelock)
			{
				System.IO.File.AppendAllText(File, "\r\nERR : " + ((args.Length != 0) ? string.Format(message, args) : message));
			}
		}
	}
	public interface ILogger
	{
		LogLevel Level { get; set; }

		void Trace(string message, params object[] args);

		void Info(string message, params object[] args);

		void Warning(string message, params object[] args);

		void Error(string message, params object[] args);
	}
	public enum LogLevel
	{
		Trace = 1,
		Info = 2,
		Warning = 3,
		Error = 4,
		None = 256
	}
	public class NullLogger : ILogger
	{
		public LogLevel Level { get; set; }

		public void Trace(string message, params object[] args)
		{
		}

		public void Info(string message, params object[] args)
		{
		}

		public void Warning(string message, params object[] args)
		{
		}

		public void Error(string message, params object[] args)
		{
		}
	}
}
namespace DiscordRPC.IO
{
	internal class Handshake
	{
		[JsonProperty("v")]
		public int Version { get; set; }

		[JsonProperty("client_id")]
		public string ClientID { get; set; }
	}
	public interface INamedPipeClient : IDisposable
	{
		ILogger Logger { get; set; }

		bool IsConnected { get; }

		int ConnectedPipe { get; }

		bool Connect(int pipe);

		bool ReadFrame(out PipeFrame frame);

		bool WriteFrame(PipeFrame frame);

		void Close();
	}
	public sealed class ManagedNamedPipeClient : INamedPipeClient, IDisposable
	{
		private const string PIPE_NAME = "discord-ipc-{0}";

		private int _connectedPipe;

		private NamedPipeClientStream _stream;

		private byte[] _buffer = new byte[PipeFrame.MAX_SIZE];

		private Queue<PipeFrame> _framequeue = new Queue<PipeFrame>();

		private object _framequeuelock = new object();

		private volatile bool _isDisposed;

		private volatile bool _isClosed = true;

		private object l_stream = new object();

		public ILogger Logger { get; set; }

		public bool IsConnected
		{
			get
			{
				if (_isClosed)
				{
					return false;
				}
				lock (l_stream)
				{
					return _stream != null && _stream.IsConnected;
				}
			}
		}

		public int ConnectedPipe => _connectedPipe;

		public ManagedNamedPipeClient()
		{
			_buffer = new byte[PipeFrame.MAX_SIZE];
			Logger = new NullLogger();
			_stream = null;
		}

		public bool Connect(int pipe)
		{
			Logger.Trace("ManagedNamedPipeClient.Connection({0})", pipe);
			if (_isDisposed)
			{
				throw new ObjectDisposedException("NamedPipe");
			}
			if (pipe > 9)
			{
				throw new ArgumentOutOfRangeException("pipe", "Argument cannot be greater than 9");
			}
			if (pipe < 0)
			{
				for (int i = 0; i < 10; i++)
				{
					if (AttemptConnection(i) || AttemptConnection(i, isSandbox: true))
					{
						BeginReadStream();
						return true;
					}
				}
			}
			else if (AttemptConnection(pipe) || AttemptConnection(pipe, isSandbox: true))
			{
				BeginReadStream();
				return true;
			}
			return false;
		}

		private bool AttemptConnection(int pipe, bool isSandbox = false)
		{
			if (_isDisposed)
			{
				throw new ObjectDisposedException("_stream");
			}
			string text = (isSandbox ? GetPipeSandbox() : "");
			if (isSandbox && text == null)
			{
				Logger.Trace("Skipping sandbox connection.");
				return false;
			}
			Logger.Trace("Connection Attempt {0} ({1})", pipe, text);
			string pipeName = GetPipeName(pipe, text);
			try
			{
				lock (l_stream)
				{
					Logger.Info("Attempting to connect to '{0}'", pipeName);
					_stream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
					_stream.Connect(0);
					Logger.Trace("Waiting for connection...");
					do
					{
						Thread.Sleep(10);
					}
					while (!_stream.IsConnected);
				}
				Logger.Info("Connected to '{0}'", pipeName);
				_connectedPipe = pipe;
				_isClosed = false;
			}
			catch (Exception ex)
			{
				Logger.Error("Failed connection to {0}. {1}", pipeName, ex.Message);
				Close();
			}
			Logger.Trace("Done. Result: {0}", _isClosed);
			return !_isClosed;
		}

		private void BeginReadStream()
		{
			if (_isClosed)
			{
				return;
			}
			try
			{
				lock (l_stream)
				{
					if (_stream != null && _stream.IsConnected)
					{
						Logger.Trace("Begining Read of {0} bytes", _buffer.Length);
						_stream.BeginRead(_buffer, 0, _buffer.Length, EndReadStream, _stream.IsConnected);
					}
				}
			}
			catch (ObjectDisposedException)
			{
				Logger.Warning("Attempted to start reading from a disposed pipe");
			}
			catch (InvalidOperationException)
			{
				Logger.Warning("Attempted to start reading from a closed pipe");
			}
			catch (Exception ex3)
			{
				Logger.Error("An exception occured while starting to read a stream: {0}", ex3.Message);
				Logger.Error(ex3.StackTrace);
			}
		}

		private void EndReadStream(IAsyncResult callback)
		{
			Logger.Trace("Ending Read");
			int num = 0;
			try
			{
				lock (l_stream)
				{
					if (_stream == null || !_stream.IsConnected)
					{
						return;
					}
					num = _stream.EndRead(callback);
				}
			}
			catch (IOException)
			{
				Logger.Warning("Attempted to end reading from a closed pipe");
				return;
			}
			catch (NullReferenceException)
			{
				Logger.Warning("Attempted to read from a null pipe");
				return;
			}
			catch (ObjectDisposedException)
			{
				Logger.Warning("Attemped to end reading from a disposed pipe");
				return;
			}
			catch (Exception ex4)
			{
				Logger.Error("An exception occured while ending a read of a stream: {0}", ex4.Message);
				Logger.Error(ex4.StackTrace);
				return;
			}
			Logger.Trace("Read {0} bytes", num);
			if (num > 0)
			{
				using MemoryStream stream = new MemoryStream(_buffer, 0, num);
				try
				{
					PipeFrame item = default(PipeFrame);
					if (item.ReadStream(stream))
					{
						Logger.Trace("Read a frame: {0}", item.Opcode);
						lock (_framequeuelock)
						{
							_framequeue.Enqueue(item);
						}
					}
					else
					{
						Logger.Error("Pipe failed to read from the data received by the stream.");
						Close();
					}
				}
				catch (Exception ex5)
				{
					Logger.Error("A exception has occured while trying to parse the pipe data: {0}", ex5.Message);
					Close();
				}
			}
			else if (IsUnix())
			{
				Logger.Error("Empty frame was read on {0}, aborting.", Environment.OSVersion);
				Close();
			}
			else
			{
				Logger.Warning("Empty frame was read. Please send report to Lachee.");
			}
			if (!_isClosed && IsConnected)
			{
				Logger.Trace("Starting another read");
				BeginReadStream();
			}
		}

		public bool ReadFrame(out PipeFrame frame)
		{
			if (_isDisposed)
			{
				throw new ObjectDisposedException("_stream");
			}
			lock (_framequeuelock)
			{
				if (_framequeue.Count == 0)
				{
					frame = default(PipeFrame);
					return false;
				}
				frame = _framequeue.Dequeue();
				return true;
			}
		}

		public bool WriteFrame(PipeFrame frame)
		{
			if (_isDisposed)
			{
				throw new ObjectDisposedException("_stream");
			}
			if (_isClosed || !IsConnected)
			{
				Logger.Error("Failed to write frame because the stream is closed");
				return false;
			}
			try
			{
				frame.WriteStream(_stream);
				return true;
			}
			catch (IOException ex)
			{
				Logger.Error("Failed to write frame because of a IO Exception: {0}", ex.Message);
			}
			catch (ObjectDisposedException)
			{
				Logger.Warning("Failed to write frame as the stream was already disposed");
			}
			catch (InvalidOperationException)
			{
				Logger.Warning("Failed to write frame because of a invalid operation");
			}
			return false;
		}

		public void Close()
		{
			if (_isClosed)
			{
				Logger.Warning("Tried to close a already closed pipe.");
				return;
			}
			try
			{
				lock (l_stream)
				{
					if (_stream != null)
					{
						try
						{
							_stream.Flush();
							_stream.Dispose();
						}
						catch (Exception)
						{
						}
						_stream = null;
						_isClosed = true;
					}
					else
					{
						Logger.Warning("Stream was closed, but no stream was available to begin with!");
					}
				}
			}
			catch (ObjectDisposedException)
			{
				Logger.Warning("Tried to dispose already disposed stream");
			}
			finally
			{
				_isClosed = true;
				_connectedPipe = -1;
			}
		}

		public void Dispose()
		{
			if (_isDisposed)
			{
				return;
			}
			if (!_isClosed)
			{
				Close();
			}
			lock (l_stream)
			{
				if (_stream != null)
				{
					_stream.Dispose();
					_stream = null;
				}
			}
			_isDisposed = true;
		}

		public static string GetPipeName(int pipe, string sandbox)
		{
			if (!IsUnix())
			{
				return sandbox + $"discord-ipc-{pipe}";
			}
			return Path.Combine(GetTemporaryDirectory(), sandbox + $"discord-ipc-{pipe}");
		}

		public static string GetPipeName(int pipe)
		{
			return GetPipeName(pipe, "");
		}

		public static string GetPipeSandbox()
		{
			if (Environment.OSVersion.Platform != PlatformID.Unix)
			{
				return null;
			}
			return "snap.discord/";
		}

		private static string GetTemporaryDirectory()
		{
			object obj = null ?? Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR");
			if (obj == null)
			{
				obj = Environment.GetEnvironmentVariable("TMPDIR");
			}
			if (obj == null)
			{
				obj = Environment.GetEnvironmentVariable("TMP");
			}
			if (obj == null)
			{
				obj = Environment.GetEnvironmentVariable("TEMP");
			}
			if (obj == null)
			{
				obj = "/tmp";
			}
			return (string)obj;
		}

		public static bool IsUnix()
		{
			PlatformID platform = Environment.OSVersion.Platform;
			if (platform != PlatformID.Unix && platform != PlatformID.MacOSX)
			{
				return false;
			}
			return true;
		}
	}
	public enum Opcode : uint
	{
		Handshake,
		Frame,
		Close,
		Ping,
		Pong
	}
	public struct PipeFrame : IEquatable<PipeFrame>
	{
		public static readonly int MAX_SIZE = 16384;

		public Opcode Opcode { get; set; }

		public uint Length => (uint)Data.Length;

		public byte[] Data { get; set; }

		public string Message
		{
			get
			{
				return GetMessage();
			}
			set
			{
				SetMessage(value);
			}
		}

		public Encoding MessageEncoding => Encoding.UTF8;

		public PipeFrame(Opcode opcode, object data)
		{
			Opcode = opcode;
			Data = null;
			SetObject(data);
		}

		private void SetMessage(string str)
		{
			Data = MessageEncoding.GetBytes(str);
		}

		private string GetMessage()
		{
			return MessageEncoding.GetString(Data);
		}

		public void SetObject(object obj)
		{
			string message = JsonConvert.SerializeObject(obj);
			SetMessage(message);
		}

		public void SetObject(Opcode opcode, object obj)
		{
			Opcode = opcode;
			SetObject(obj);
		}

		public T GetObject<T>()
		{
			return JsonConvert.DeserializeObject<T>(GetMessage());
		}

		public bool ReadStream(Stream stream)
		{
			if (!TryReadUInt32(stream, out var value))
			{
				return false;
			}
			if (!TryReadUInt32(stream, out var value2))
			{
				return false;
			}
			uint num = value2;
			using MemoryStream memoryStream = new MemoryStream();
			uint num2 = (uint)Min(2048, value2);
			byte[] array = new byte[num2];
			int count;
			while ((count = stream.Read(array, 0, Min(array.Length, num))) > 0)
			{
				num -= num2;
				memoryStream.Write(array, 0, count);
			}
			byte[] array2 = memoryStream.ToArray();
			if (array2.LongLength != value2)
			{
				return false;
			}
			Opcode = (Opcode)value;
			Data = array2;
			return true;
		}

		private int Min(int a, uint b)
		{
			if (b >= a)
			{
				return a;
			}
			return (int)b;
		}

		private bool TryReadUInt32(Stream stream, out uint value)
		{
			byte[] array = new byte[4];
			if (stream.Read(array, 0, array.Length) != 4)
			{
				value = 0u;
				return false;
			}
			value = BitConverter.ToUInt32(array, 0);
			return true;
		}

		public void WriteStream(Stream stream)
		{
			byte[] bytes = BitConverter.GetBytes((uint)Opcode);
			byte[] bytes2 = BitConverter.GetBytes(Length);
			byte[] array = new byte[bytes.Length + bytes2.Length + Data.Length];
			bytes.CopyTo(array, 0);
			bytes2.CopyTo(array, bytes.Length);
			Data.CopyTo(array, bytes.Length + bytes2.Length);
			stream.Write(array, 0, array.Length);
		}

		public bool Equals(PipeFrame other)
		{
			if (Opcode == other.Opcode && Length == other.Length)
			{
				return Data == other.Data;
			}
			return false;
		}
	}
}
namespace DiscordRPC.Helper
{
	internal class BackoffDelay
	{
		private int _current;

		private int _fails;

		public int Maximum { get; private set; }

		public int Minimum { get; private set; }

		public int Current => _current;

		public int Fails => _fails;

		public Random Random { get; set; }

		private BackoffDelay()
		{
		}

		public BackoffDelay(int min, int max)
			: this(min, max, new Random())
		{
		}

		public BackoffDelay(int min, int max, Random random)
		{
			Minimum = min;
			Maximum = max;
			_current = min;
			_fails = 0;
			Random = random;
		}

		public void Reset()
		{
			_fails = 0;
			_current = Minimum;
		}

		public int NextDelay()
		{
			_fails++;
			double num = (float)(Maximum - Minimum) / 100f;
			_current = (int)Math.Floor(num * (double)_fails) + Minimum;
			return Math.Min(Math.Max(_current, Minimum), Maximum);
		}
	}
	public static class StringTools
	{
		public static string GetNullOrString(this string str)
		{
			if (str.Length != 0 && !string.IsNullOrEmpty(str.Trim()))
			{
				return str;
			}
			return null;
		}

		public static bool WithinLength(this string str, int bytes)
		{
			return str.WithinLength(bytes, Encoding.UTF8);
		}

		public static bool WithinLength(this string str, int bytes, Encoding encoding)
		{
			return encoding.GetByteCount(str) <= bytes;
		}

		public static string ToCamelCase(this string str)
		{
			return (from s in str?.ToLowerInvariant().Split(new string[2] { "_", " " }, StringSplitOptions.RemoveEmptyEntries)
				select char.ToUpper(s[0]) + s.Substring(1, s.Length - 1)).Aggregate(string.Empty, (string s1, string s2) => s1 + s2);
		}

		public static string ToSnakeCase(this string str)
		{
			if (str == null)
			{
				return null;
			}
			return string.Concat(str.Select((char x, int i) => (i <= 0 || !char.IsUpper(x)) ? x.ToString() : ("_" + x)).ToArray()).ToUpperInvariant();
		}
	}
}
namespace DiscordRPC.Exceptions
{
	public class BadPresenceException : Exception
	{
		internal BadPresenceException(string message)
			: base(message)
		{
		}
	}
	public class InvalidConfigurationException : Exception
	{
		internal InvalidConfigurationException(string message)
			: base(message)
		{
		}
	}
	[Obsolete("Not actually used anywhere")]
	public class InvalidPipeException : Exception
	{
		internal InvalidPipeException(string message)
			: base(message)
		{
		}
	}
	public class StringOutOfRangeException : Exception
	{
		public int MaximumLength { get; private set; }

		public int MinimumLength { get; private set; }

		internal StringOutOfRangeException(string message, int min, int max)
			: base(message)
		{
			MinimumLength = min;
			MaximumLength = max;
		}

		internal StringOutOfRangeException(int minumum, int max)
			: this($"Length of string is out of range. Expected a value between {minumum} and {max}", minumum, max)
		{
		}

		internal StringOutOfRangeException(int max)
			: this($"Length of string is out of range. Expected a value with a maximum length of {max}", 0, max)
		{
		}
	}
	public class UninitializedException : Exception
	{
		internal UninitializedException(string message)
			: base(message)
		{
		}

		internal UninitializedException()
			: this("Cannot perform action because the client has not been initialized yet or has been deinitialized.")
		{
		}
	}
}
namespace DiscordRPC.Events
{
	public delegate void OnReadyEvent(object sender, ReadyMessage args);
	public delegate void OnCloseEvent(object sender, CloseMessage args);
	public delegate void OnErrorEvent(object sender, ErrorMessage args);
	public delegate void OnPresenceUpdateEvent(object sender, PresenceMessage args);
	public delegate void OnSubscribeEvent(object sender, SubscribeMessage args);
	public delegate void OnUnsubscribeEvent(object sender, UnsubscribeMessage args);
	public delegate void OnJoinEvent(object sender, JoinMessage args);
	public delegate void OnSpectateEvent(object sender, SpectateMessage args);
	public delegate void OnJoinRequestedEvent(object sender, JoinRequestMessage args);
	public delegate void OnConnectionEstablishedEvent(object sender, ConnectionEstablishedMessage args);
	public delegate void OnConnectionFailedEvent(object sender, ConnectionFailedMessage args);
	public delegate void OnRpcMessageEvent(object sender, IMessage msg);
}
namespace DiscordRPC.Converters
{
	internal class EnumSnakeCaseConverter : JsonConverter
	{
		public override bool CanConvert(Type objectType)
		{
			return objectType.IsEnum;
		}

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			if (reader.Value == null)
			{
				return null;
			}
			object obj = null;
			if (TryParseEnum(objectType, (string)reader.Value, out obj))
			{
				return obj;
			}
			return existingValue;
		}

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			Type type = value.GetType();
			string text = Enum.GetName(type, value);
			MemberInfo[] members = type.GetMembers(BindingFlags.Static | BindingFlags.Public);
			foreach (MemberInfo memberInfo in members)
			{
				if (memberInfo.Name.Equals(text))
				{
					object[] customAttributes = memberInfo.GetCustomAttributes(typeof(EnumValueAttribute), inherit: true);
					if (customAttributes.Length != 0)
					{
						text = ((EnumValueAttribute)customAttributes[0]).Value;
					}
				}
			}
			writer.WriteValue(text);
		}

		public bool TryParseEnum(Type enumType, string str, out object obj)
		{
			if (str == null)
			{
				obj = null;
				return false;
			}
			Type type = enumType;
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
			{
				type = type.GetGenericArguments().First();
			}
			if (!type.IsEnum)
			{
				obj = null;
				return false;
			}
			MemberInfo[] members = type.GetMembers(BindingFlags.Static | BindingFlags.Public);
			foreach (MemberInfo memberInfo in members)
			{
				object[] customAttributes = memberInfo.GetCustomAttributes(typeof(EnumValueAttribute), inherit: true);
				for (int j = 0; j < customAttributes.Length; j++)
				{
					EnumValueAttribute enumValueAttribute = (EnumValueAttribute)customAttributes[j];
					if (str.Equals(enumValueAttribute.Value))
					{
						obj = Enum.Parse(type, memberInfo.Name, ignoreCase: true);
						return true;
					}
				}
			}
			obj = null;
			return false;
		}
	}
	internal class EnumValueAttribute : Attribute
	{
		public string Value { get; set; }

		public EnumValueAttribute(string value)
		{
			Value = value;
		}
	}
}