Decompiled source of EyeTracking v1.0.1

Mods/EyeTracking.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
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 System.Text.RegularExpressions;
using System.Threading;
using BlobHandles;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using EyeTracking;
using EyeTracking.Data;
using EyeTracking.EyeGaze;
using EyeTracking.MarrowSDK;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.InteropTypes.Fields;
using Il2CppRealisticEyeMovements;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.VRMK;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using MiniNtp;
using OscCore;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.IL2CPP.CompilerServices.BlobHandles;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Profiling;
using UnityEngine.XR;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "EyeTracking", "1.0.1", "Checkerboard", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: InternalsVisibleTo("OscCore.Tests.Editor")]
[assembly: InternalsVisibleTo("OscCore.Tests.Runtime")]
[assembly: InternalsVisibleTo("OscCore.Editor")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MiniNtp
{
	public static class ExtensionMethods
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint ReverseBytes(this uint value)
		{
			return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000u) >> 24);
		}
	}
	public struct NtpTimestamp : IEquatable<NtpTimestamp>, IComparable<NtpTimestamp>
	{
		public readonly uint Seconds;

		public readonly uint Fractions;

		public NtpTimestamp(uint seconds, uint fractions)
		{
			Seconds = seconds;
			Fractions = fractions;
		}

		public NtpTimestamp(DateTime dt)
		{
			DateTime dateTime = ((dt < TimeConstants.Epoch2036) ? TimeConstants.Epoch1900 : TimeConstants.Epoch2036);
			Seconds = (uint)(dt - dateTime).TotalSeconds;
			Fractions = (uint)(dt.Millisecond * 5000000);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static NtpTimestamp FromBigEndianBytes(byte[] buffer, int offset)
		{
			fixed (byte* tsPtr = &buffer[offset])
			{
				return FromBigEndianBytes((uint*)tsPtr);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static NtpTimestamp FromBigEndianBytes(byte* tsPtr)
		{
			return FromBigEndianBytes((uint*)tsPtr);
		}

		public unsafe static NtpTimestamp FromBigEndianBytes(uint* tsPtr)
		{
			uint num = *tsPtr;
			uint seconds = ((num & 0xFF) << 24) | ((num & 0xFF00) << 8) | ((num & 0xFF0000) >> 8) | ((num & 0xFF000000u) >> 24);
			uint num2 = tsPtr[1];
			uint fractions = ((num2 & 0xFF) << 24) | ((num2 & 0xFF00) << 8) | ((num2 & 0xFF0000) >> 8) | ((num2 & 0xFF000000u) >> 24);
			return new NtpTimestamp(seconds, fractions);
		}

		public DateTime ToDateTime()
		{
			if (Fractions == 1 && Seconds == 0)
			{
				return DateTime.Now;
			}
			DateTime dateTime = ((DateTime.Now < TimeConstants.Epoch2036) ? TimeConstants.Epoch1900 : TimeConstants.Epoch2036);
			double num = (double)Fractions * 2E-07;
			double value = (double)Seconds * 1000.0 + num;
			return dateTime.AddMilliseconds(value);
		}

		public unsafe void ToBigEndianBytes(byte[] bytes, int offset)
		{
			fixed (byte* ptr = &bytes[offset])
			{
				uint* ptr2 = (uint*)ptr;
				*ptr2 = Seconds.ReverseBytes();
				ptr2[1] = Fractions.ReverseBytes();
			}
		}

		public unsafe void ToBigEndianBytes(uint* writePtr)
		{
			*writePtr = Seconds.ReverseBytes();
			writePtr[1] = Fractions.ReverseBytes();
		}

		public override string ToString()
		{
			return $"Seconds: {Seconds} , Fractions {Fractions}";
		}

		public bool Equals(NtpTimestamp other)
		{
			if (Seconds == other.Seconds)
			{
				return Fractions == other.Fractions;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is NtpTimestamp other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (int)((Seconds * 397) ^ Fractions);
		}

		public static bool operator ==(NtpTimestamp left, NtpTimestamp right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(NtpTimestamp left, NtpTimestamp right)
		{
			return !left.Equals(right);
		}

		public int CompareTo(NtpTimestamp other)
		{
			int num = Seconds.CompareTo(other.Seconds);
			if (num == 0)
			{
				return Fractions.CompareTo(other.Fractions);
			}
			return num;
		}

		public static bool operator <(NtpTimestamp left, NtpTimestamp right)
		{
			return left.CompareTo(right) < 0;
		}

		public static bool operator >(NtpTimestamp left, NtpTimestamp right)
		{
			return left.CompareTo(right) > 0;
		}

		public static bool operator <=(NtpTimestamp left, NtpTimestamp right)
		{
			return left.CompareTo(right) <= 0;
		}

		public static bool operator >=(NtpTimestamp left, NtpTimestamp right)
		{
			return left.CompareTo(right) >= 0;
		}

		public static NtpTimestamp operator -(NtpTimestamp left, NtpTimestamp right)
		{
			return new NtpTimestamp(left.Seconds - right.Seconds, left.Fractions - right.Fractions);
		}
	}
	public static class TimeConstants
	{
		public static readonly DateTime Epoch1900 = DateTime.Parse("1900-01-01 00:00:00.000");

		public static readonly DateTime Epoch2036 = DateTime.Parse("2036-02-07 06:28:15");

		public const int TicksPerSecond = 10000000;

		public const uint TimestampFractionsPerMs = 5000000u;

		public const double FractionMillisecondMultiplier = 2E-07;
	}
}
namespace Unity.IL2CPP.CompilerServices.BlobHandles
{
	public enum Option
	{
		NullChecks = 1,
		ArrayBoundsChecks,
		DivideByZeroChecks
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	public class Il2CppSetOptionAttribute : Attribute
	{
		public Option Option { get; private set; }

		public object Value { get; private set; }

		public Il2CppSetOptionAttribute(Option option, object value)
		{
			Option = option;
			Value = value;
		}
	}
}
namespace BlobHandles
{
	public static class BlobHandleDictionaryMethods
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static bool TryGetValueFromBytes<T>(this Dictionary<BlobHandle, T> self, byte* ptr, int length, out T value)
		{
			return self.TryGetValue(new BlobHandle(ptr, length), out value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool TryGetValueFromBytes<T>(this Dictionary<BlobHandle, T> self, byte[] bytes, out T value)
		{
			return self.TryGetValue(new BlobHandle(bytes), out value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool TryGetValueFromBytes<T>(this Dictionary<BlobHandle, T> self, byte[] bytes, int length, out T value)
		{
			return self.TryGetValue(new BlobHandle(bytes, length), out value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool TryGetValueFromBytes<T>(this Dictionary<BlobHandle, T> self, byte[] bytes, int length, int offset, out T value)
		{
			return self.TryGetValue(new BlobHandle(bytes, length, offset), out value);
		}
	}
	public static class BlobHandleHashSetMethods
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static bool ContainsBlob<T>(this HashSet<BlobHandle> self, byte* ptr, int length)
		{
			return self.Contains(new BlobHandle(ptr, length));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ContainsBlob<T>(this HashSet<BlobHandle> self, byte[] bytes)
		{
			return self.Contains(new BlobHandle(bytes));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ContainsBlob<T>(this HashSet<BlobHandle> self, byte[] bytes, int length)
		{
			return self.Contains(new BlobHandle(bytes, length));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ContainsBlob(this HashSet<BlobHandle> self, byte[] bytes, int length, int offset)
		{
			return self.Contains(new BlobHandle(bytes, length, offset));
		}
	}
	public sealed class BlobStringDictionary<T> : IDisposable
	{
		private const int defaultSize = 16;

		public readonly Dictionary<BlobHandle, T> HandleToValue;

		private readonly Dictionary<string, BlobString> SourceToBlob;

		public BlobStringDictionary(int initialCapacity = 16)
		{
			HandleToValue = new Dictionary<BlobHandle, T>(initialCapacity);
			SourceToBlob = new Dictionary<string, BlobString>(initialCapacity);
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public void Add(string str, T value)
		{
			if (str != null && !SourceToBlob.ContainsKey(str))
			{
				BlobString value2 = new BlobString(str, (Allocator)4);
				HandleToValue.Add(value2.Handle, value);
				SourceToBlob.Add(str, value2);
			}
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public void Add(BlobString blobStr, T value)
		{
			HandleToValue.Add(blobStr.Handle, value);
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public bool Remove(string str)
		{
			if (!SourceToBlob.TryGetValue(str, out var value))
			{
				return false;
			}
			SourceToBlob.Remove(str);
			bool result = HandleToValue.Remove(value.Handle);
			value.Dispose();
			return result;
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public bool Remove(BlobString blobStr)
		{
			return HandleToValue.Remove(blobStr.Handle);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[Il2CppSetOption(Option.NullChecks, false)]
		public unsafe bool TryGetValueFromBytes(byte* ptr, int byteCount, out T value)
		{
			return HandleToValue.TryGetValue(new BlobHandle(ptr, byteCount), out value);
		}

		public void Clear()
		{
			HandleToValue.Clear();
			SourceToBlob.Clear();
		}

		public void Dispose()
		{
			foreach (KeyValuePair<string, BlobString> item in SourceToBlob)
			{
				item.Value.Dispose();
			}
		}
	}
	public struct BlobHandle : IEquatable<BlobHandle>
	{
		public unsafe readonly byte* Pointer;

		public readonly int Length;

		public unsafe BlobHandle(byte* pointer, int length)
		{
			Pointer = pointer;
			Length = length;
		}

		public unsafe BlobHandle(IntPtr pointer, int length)
		{
			Pointer = (byte*)(void*)pointer;
			Length = length;
		}

		public unsafe BlobHandle(byte[] bytes)
		{
			fixed (byte* pointer = bytes)
			{
				Pointer = pointer;
				Length = bytes.Length;
			}
		}

		public unsafe BlobHandle(byte[] bytes, int length)
		{
			fixed (byte* pointer = bytes)
			{
				Pointer = pointer;
				Length = length;
			}
		}

		public unsafe BlobHandle(byte[] bytes, int length, int offset)
		{
			fixed (byte* pointer = &bytes[offset])
			{
				Pointer = pointer;
				Length = length;
			}
		}

		public unsafe override string ToString()
		{
			return Length + " bytes @ " + new IntPtr(Pointer);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe override int GetHashCode()
		{
			return (Length * 397) ^ Pointer[Length - 1];
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe bool Equals(BlobHandle other)
		{
			if (Length == other.Length)
			{
				return MemoryCompare(Pointer, other.Pointer, (UIntPtr)(ulong)Length) == 0;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is BlobHandle other)
			{
				return Equals(other);
			}
			return false;
		}

		public unsafe static bool operator ==(BlobHandle left, BlobHandle right)
		{
			if (left.Length == right.Length)
			{
				return MemoryCompare(left.Pointer, right.Pointer, (UIntPtr)(ulong)left.Length) == 0;
			}
			return false;
		}

		public unsafe static bool operator !=(BlobHandle left, BlobHandle right)
		{
			if (left.Length == right.Length)
			{
				return MemoryCompare(left.Pointer, right.Pointer, (UIntPtr)(ulong)left.Length) != 0;
			}
			return true;
		}

		private unsafe static int MemoryCompare(void* ptr1, void* ptr2, UIntPtr count)
		{
			Span<byte> span = new Span<byte>(ptr1, (int)(uint)count);
			Span<byte> span2 = new Span<byte>(ptr2, (int)(uint)count);
			for (int i = 0; i < span.Length; i++)
			{
				if (span[i] != span2[i])
				{
					return 1;
				}
			}
			return 0;
		}
	}
	public struct BlobString : IDisposable, IEquatable<BlobString>
	{
		private readonly NativeArray<byte> Bytes;

		public readonly BlobHandle Handle;

		public static Encoding Encoding { get; set; } = System.Text.Encoding.ASCII;


		public int Length => Bytes.Length;

		public unsafe BlobString(string source, Allocator allocator = 4)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			int byteCount = Encoding.GetByteCount(source);
			Bytes = new NativeArray<byte>(byteCount, allocator, (NativeArrayOptions)1);
			byte* unsafePtr = (byte*)NativeArrayUnsafeUtility.GetUnsafePtr<byte>(Bytes);
			fixed (char* chars = source)
			{
				Encoding.GetBytes(chars, source.Length, unsafePtr, byteCount);
				Handle = new BlobHandle(unsafePtr, byteCount);
			}
		}

		public unsafe BlobString(byte* sourcePtr, int length)
		{
			Handle = new BlobHandle(sourcePtr, length);
			Bytes = null;
		}

		public unsafe override string ToString()
		{
			return Encoding.GetString(Handle.Pointer, Handle.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override int GetHashCode()
		{
			return Handle.GetHashCode();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool Equals(BlobString other)
		{
			return Handle.Equals(other.Handle);
		}

		public override bool Equals(object obj)
		{
			if (obj is BlobString blobString)
			{
				return Handle.Equals(blobString.Handle);
			}
			return false;
		}

		public static bool operator ==(BlobString l, BlobString r)
		{
			return l.Handle == r.Handle;
		}

		public static bool operator !=(BlobString l, BlobString r)
		{
			return l.Handle != r.Handle;
		}

		public void Dispose()
		{
			if (Bytes.IsCreated)
			{
				Bytes.Dispose();
			}
		}
	}
}
namespace OscCore
{
	public class OscBlobMessageHandler : MessageHandlerBase
	{
		protected byte[] m_Buffer = new byte[128];

		public byte[] Buffer => m_Buffer;

		public int LastReceivedBlobLength { get; private set; }

		public event Action<byte[], int> OnMessageReceived;

		public OscBlobMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			LastReceivedBlobLength = values.ReadBlobElement(0, ref m_Buffer);
		}

		protected override void InvokeEvent()
		{
			this.OnMessageReceived?.Invoke(m_Buffer, LastReceivedBlobLength);
		}
	}
	public class OscBooleanMessageHandler : OscMessageHandler<bool>
	{
		public OscBooleanMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadBooleanElement(0);
		}
	}
	public class OscColorMessageHandler : OscMessageHandler<Color>
	{
		public OscColorMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			m_Value = Color32.op_Implicit(values.ReadColor32Element(0));
		}
	}
	public class OscFloat64MessageHandler : OscMessageHandler<double>
	{
		public OscFloat64MessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadFloat64Element(0);
		}
	}
	public class OscFloatMessageHandler : OscMessageHandler<float>
	{
		public OscFloatMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadFloatElement(0);
		}
	}
	public class OscInt64MessageHandler : OscMessageHandler<long>
	{
		public OscInt64MessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadInt64Element(0);
		}
	}
	public class OscIntMessageHandler : OscMessageHandler<int>
	{
		public OscIntMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadIntElement(0);
		}
	}
	public class OscStringMessageHandler : OscMessageHandler<string>
	{
		public OscStringMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			m_Value = values.ReadStringElement(0);
		}
	}
	public class OscVector3MessageHandler : OscMessageHandler<Vector3>
	{
		public OscVector3MessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void ValueRead(OscMessageValues values)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			float num = values.ReadFloatElement(0);
			float num2 = values.ReadFloatElement(1);
			float num3 = values.ReadFloatElement(2);
			m_Value = new Vector3(num, num2, num3);
		}
	}
	public abstract class MessageHandlerBase : IDisposable
	{
		protected OscReceiver m_Receiver;

		protected string m_Address = "/";

		protected OscActionPair m_ActionPair;

		protected bool m_Registered;

		protected bool m_Disposed;

		public OscReceiver Receiver => m_Receiver;

		public string Address => m_Address;

		public MessageHandlerBase(OscReceiver receiver, string address)
		{
			m_Receiver = receiver;
			m_Address = address;
			Initialize();
		}

		protected virtual void Initialize()
		{
			if (!m_Registered && !string.IsNullOrEmpty(Address) && m_Receiver?.Server != null)
			{
				m_ActionPair = new OscActionPair(ValueRead, InvokeEvent);
				Receiver.Server.TryAddMethodPair(Address, m_ActionPair);
				m_Registered = true;
			}
		}

		public virtual void Dispose()
		{
			if (!m_Disposed)
			{
				m_Registered = false;
				m_Receiver?.Server?.RemoveMethodPair(Address, m_ActionPair);
				m_Disposed = true;
			}
		}

		protected abstract void InvokeEvent();

		protected abstract void ValueRead(OscMessageValues values);
	}
	public abstract class OscMessageHandler<T> : MessageHandlerBase
	{
		protected T m_Value;

		public event Action<T> OnMessageReceived;

		public OscMessageHandler(OscReceiver receiver, string address)
			: base(receiver, address)
		{
		}

		protected override void InvokeEvent()
		{
			this.OnMessageReceived?.Invoke(m_Value);
		}
	}
	public class OscReceiver : IDisposable
	{
		private int m_Port = 9000;

		private bool m_Disposed;

		public int Port
		{
			get
			{
				return m_Port;
			}
			set
			{
				SetPort(value);
			}
		}

		public bool Running { get; private set; }

		public OscServer Server { get; private set; }

		public OscReceiver(int port = 9000)
		{
			m_Port = port.ClampPort();
			Initialize();
		}

		private void Initialize()
		{
			Server = OscServer.GetOrCreate(m_Port);
			Running = true;
		}

		public void Update()
		{
			Server?.Update();
		}

		public void Dispose()
		{
			if (!m_Disposed)
			{
				Server?.Dispose();
				Server = null;
				Running = false;
				m_Disposed = true;
			}
		}

		private void SetPort(int newPort)
		{
			if (newPort.ClampPort() != newPort)
			{
				return;
			}
			int port = m_Port;
			OscServer server = Server;
			try
			{
				Server = OscServer.GetOrCreate(newPort);
				m_Port = newPort;
				server?.Dispose();
			}
			catch (Exception)
			{
				m_Port = port;
				Server = server;
			}
		}
	}
	public class OscSender : IDisposable
	{
		private string m_IpAddress = "127.0.0.1";

		private int m_Port = 7000;

		private bool m_Disposed;

		public string IpAddress
		{
			get
			{
				return m_IpAddress;
			}
			set
			{
				if (IPAddress.TryParse(value, out IPAddress _))
				{
					m_IpAddress = value;
					ReInitialize();
				}
			}
		}

		public int Port
		{
			get
			{
				return m_Port;
			}
			set
			{
				m_Port = value.ClampPort();
				ReInitialize();
			}
		}

		public OscClient Client { get; private set; }

		public OscSender(int port = 7000, string ipAddress = "127.0.0.1")
		{
			m_IpAddress = ipAddress;
			m_Port = port.ClampPort();
			Setup();
		}

		private void Setup()
		{
			if (Client == null)
			{
				Client = new OscClient(m_IpAddress, m_Port);
			}
		}

		private void ReInitialize()
		{
			if (!m_Disposed)
			{
				Client = null;
				Setup();
			}
		}

		public void Dispose()
		{
			if (!m_Disposed)
			{
				Client = null;
				m_Disposed = true;
			}
		}
	}
	public class PropertyOutput : MonoBehaviour
	{
		private OscSender m_Sender;

		private string m_Address = "";

		private GameObject m_Object;

		private Component m_SourceComponent;

		private bool m_MemberIsProperty;

		private string m_PropertyName;

		private string m_PropertyTypeName;

		private Vector2ElementFilter m_SendVector2Elements;

		private Vector3ElementFilter m_SendVector3Elements;

		private bool m_PreviousBooleanValue;

		private int m_PreviousIntValue;

		private long m_PreviousLongValue;

		private double m_PreviousDoubleValue;

		private float m_PreviousSingleValue;

		private string m_PreviousStringValue;

		private Color m_PreviousColorValue;

		private Vector2 m_PreviousVec2Value;

		private Vector3 m_PreviousVec3Value;

		private bool m_HasSender;

		private MemberInfo m_MemberInfo;

		private PropertyInfo m_Property;

		private FieldInfo m_Field;

		public OscSender Sender
		{
			get
			{
				return m_Sender;
			}
			set
			{
				m_Sender = ((value == null) ? m_Sender : value);
			}
		}

		public Component SourceComponent
		{
			get
			{
				return m_SourceComponent;
			}
			set
			{
				m_SourceComponent = (((Object)(object)value == (Object)null) ? m_SourceComponent : value);
			}
		}

		public PropertyInfo Property
		{
			get
			{
				return m_Property;
			}
			set
			{
				m_MemberInfo = value;
				m_Property = value;
				m_Field = null;
				m_MemberIsProperty = true;
			}
		}

		public FieldInfo Field
		{
			get
			{
				return m_Field;
			}
			set
			{
				m_MemberInfo = value;
				m_Field = value;
				m_Property = null;
				m_MemberIsProperty = false;
			}
		}

		private void OnEnable()
		{
			if ((Object)(object)m_Object == (Object)null)
			{
				m_Object = ((Component)this).gameObject;
			}
			m_HasSender = m_Sender != null;
			SetPropertyFromSerialized();
		}

		private void OnValidate()
		{
			Utils.ValidateAddress(ref m_Address);
			if (m_Sender == null)
			{
				m_Sender = ((Component)this).gameObject.GetComponentInParent<OscSender>();
			}
			m_HasSender = m_Sender != null;
		}

		private void Update()
		{
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			if (m_MemberInfo == null || !m_HasSender || m_Sender.Client == null)
			{
				return;
			}
			object obj = (m_MemberIsProperty ? m_Property.GetValue(m_SourceComponent) : m_Field.GetValue(m_SourceComponent));
			if (obj == null)
			{
				return;
			}
			string propertyTypeName = m_PropertyTypeName;
			if (propertyTypeName == null)
			{
				return;
			}
			int castValue5;
			switch (propertyTypeName.Length)
			{
			case 5:
			{
				char c = propertyTypeName[3];
				if ((uint)c <= 51u)
				{
					switch (c)
					{
					default:
						return;
					case '1':
						if (!(propertyTypeName == "Int16"))
						{
							return;
						}
						break;
					case '3':
						if (!(propertyTypeName == "Int32"))
						{
							return;
						}
						break;
					}
				}
				else
				{
					if (c == '6')
					{
						if (propertyTypeName == "Int64" && ValueChanged(ref m_PreviousLongValue, obj, out var castValue6))
						{
							m_Sender.Client.Send(m_Address, castValue6);
						}
						break;
					}
					if (c == 'o')
					{
						if (!(propertyTypeName == "Color"))
						{
							break;
						}
						goto IL_02f0;
					}
					if (c != 't' || !(propertyTypeName == "SByte"))
					{
						break;
					}
				}
				goto IL_0217;
			}
			case 6:
				switch (propertyTypeName[1])
				{
				default:
					return;
				case 'I':
					break;
				case 'i':
				{
					if (propertyTypeName == "Single" && ValueChanged(ref m_PreviousSingleValue, obj, out var castValue4))
					{
						m_Sender.Client.Send(m_Address, castValue4);
					}
					return;
				}
				case 'o':
				{
					if (propertyTypeName == "Double" && ValueChanged(ref m_PreviousDoubleValue, obj, out var castValue3))
					{
						m_Sender.Client.Send(m_Address, castValue3);
					}
					return;
				}
				case 't':
				{
					if (propertyTypeName == "String" && ValueChanged(ref m_PreviousStringValue, obj, out var castValue2))
					{
						m_Sender.Client.Send(m_Address, castValue2);
					}
					return;
				}
				}
				if (!(propertyTypeName == "UInt16"))
				{
					break;
				}
				goto IL_0217;
			case 7:
				switch (propertyTypeName[0])
				{
				default:
					return;
				case 'C':
					break;
				case 'V':
					if (!(propertyTypeName == "Vector2"))
					{
						if (propertyTypeName == "Vector3")
						{
							SendVector3(obj);
						}
					}
					else
					{
						SendVector2(obj);
					}
					return;
				case 'B':
				{
					if (propertyTypeName == "Boolean" && ValueChanged(ref m_PreviousBooleanValue, obj, out var castValue))
					{
						m_Sender.Client.Send(m_Address, castValue);
					}
					return;
				}
				}
				if (!(propertyTypeName == "Color32"))
				{
					break;
				}
				goto IL_02f0;
			case 4:
				{
					if (!(propertyTypeName == "Byte"))
					{
						break;
					}
					goto IL_0217;
				}
				IL_02f0:
				if (!((Color)(ref m_PreviousColorValue)).Equals((Color)obj))
				{
					m_PreviousColorValue = (Color)obj;
					m_Sender.Client.Send(m_Address, Color32.op_Implicit(m_PreviousColorValue));
				}
				break;
				IL_0217:
				if (ValueChanged(ref m_PreviousIntValue, obj, out castValue5))
				{
					m_Sender.Client.Send(m_Address, castValue5);
				}
				break;
			}
		}

		private void SendVector2(object obj)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = (Vector2)obj;
			switch (m_SendVector2Elements)
			{
			case Vector2ElementFilter.XY:
				if (!((Vector2)(ref m_PreviousVec2Value)).Equals(val))
				{
					m_PreviousVec2Value = val;
					m_Sender.Client.Send(m_Address, val);
				}
				break;
			case Vector2ElementFilter.X:
				if (!m_PreviousSingleValue.Equals(val.x))
				{
					m_PreviousSingleValue = val.x;
					m_Sender.Client.Send(m_Address, val.x);
				}
				break;
			case Vector2ElementFilter.Y:
				if (!m_PreviousSingleValue.Equals(val.y))
				{
					m_PreviousSingleValue = val.y;
					m_Sender.Client.Send(m_Address, val.y);
				}
				break;
			}
		}

		private void SendVector3(object value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (Vector3)value;
			switch (m_SendVector3Elements)
			{
			case Vector3ElementFilter.XYZ:
				if (!((Vector3)(ref m_PreviousVec3Value)).Equals(val))
				{
					m_PreviousVec3Value = val;
					m_Sender.Client.Send(m_Address, val);
				}
				break;
			case Vector3ElementFilter.X:
				if (!m_PreviousSingleValue.Equals(val.x))
				{
					m_PreviousSingleValue = val.x;
					m_Sender.Client.Send(m_Address, val.x);
				}
				break;
			case Vector3ElementFilter.Y:
				if (!m_PreviousSingleValue.Equals(val.y))
				{
					m_PreviousSingleValue = val.y;
					m_Sender.Client.Send(m_Address, val.y);
				}
				break;
			case Vector3ElementFilter.Z:
				if (!m_PreviousSingleValue.Equals(val.z))
				{
					m_PreviousSingleValue = val.z;
					m_Sender.Client.Send(m_Address, val.z);
				}
				break;
			case Vector3ElementFilter.XY:
			{
				Vector2 val4 = default(Vector2);
				((Vector2)(ref val4))..ctor(val.x, val.y);
				if (!((Vector2)(ref m_PreviousVec2Value)).Equals(val4))
				{
					m_PreviousVec2Value = val4;
					m_Sender.Client.Send(m_Address, val4);
				}
				break;
			}
			case Vector3ElementFilter.XZ:
			{
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(val.x, val.z);
				if (!((Vector2)(ref m_PreviousVec2Value)).Equals(val3))
				{
					m_PreviousVec2Value = val3;
					m_Sender.Client.Send(m_Address, val3);
				}
				break;
			}
			case Vector3ElementFilter.YZ:
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(val.y, val.z);
				if (!((Vector2)(ref m_PreviousVec2Value)).Equals(val2))
				{
					m_PreviousVec2Value = val2;
					m_Sender.Client.Send(m_Address, val2);
				}
				break;
			}
			}
		}

		private static bool ValueChanged<T>(ref T previousValue, object value, out T castValue) where T : IEquatable<T>
		{
			castValue = (T)value;
			if (!castValue.Equals(previousValue))
			{
				previousValue = castValue;
				return true;
			}
			return false;
		}

		internal Component[] GetObjectComponents()
		{
			return Il2CppArrayBase<Component>.op_Implicit(((Object)(object)m_Object == (Object)null) ? null : m_Object.GetComponents<Component>());
		}

		internal void SetPropertyFromSerialized()
		{
			if (!((Object)(object)m_SourceComponent == (Object)null))
			{
				Type type = ((object)m_SourceComponent).GetType();
				if (m_MemberIsProperty)
				{
					Property = type.GetProperty(m_PropertyName);
				}
				else
				{
					Field = type.GetField(m_PropertyName);
				}
			}
		}
	}
	[Serializable]
	public class BoolUnityEvent : UnityEvent<bool>
	{
	}
	[Serializable]
	public class IntUnityEvent : UnityEvent<int>
	{
	}
	[Serializable]
	public class LongUnityEvent : UnityEvent<long>
	{
	}
	[Serializable]
	public class FloatUnityEvent : UnityEvent<float>
	{
	}
	[Serializable]
	public class DoubleUnityEvent : UnityEvent<double>
	{
	}
	[Serializable]
	public class StringUnityEvent : UnityEvent<string>
	{
	}
	[Serializable]
	public class ColorUnityEvent : UnityEvent<Color>
	{
	}
	[Serializable]
	public class Vector3UnityEvent : UnityEvent<Vector3>
	{
	}
	[Serializable]
	public class BlobUnityEvent : UnityEvent<byte[], int>
	{
	}
	internal static class Constant
	{
		public const byte Comma = 44;

		public const byte ForwardSlash = 47;

		public static readonly byte[] BundlePrefixBytes;

		public static readonly long BundlePrefixLong;

		static Constant()
		{
			byte[] bytes = Encoding.ASCII.GetBytes("#bundle ");
			bytes[7] = 0;
			BundlePrefixBytes = bytes;
			BundlePrefixLong = BitConverter.ToInt64(bytes, 0);
		}
	}
	public delegate void MonitorCallback(BlobString address, OscMessageValues values);
	internal enum AddressType
	{
		Invalid,
		Pattern,
		Address
	}
	public enum TypeTag : byte
	{
		False = 70,
		Infinitum = 73,
		Nil = 78,
		AltTypeString = 83,
		True = 84,
		ArrayStart = 91,
		ArrayEnd = 93,
		Blob = 98,
		AsciiChar32 = 99,
		Float64 = 100,
		Float32 = 102,
		Int64 = 104,
		Int32 = 105,
		MIDI = 109,
		Color32 = 114,
		String = 115,
		TimeTag = 116
	}
	public static class TypeTagMethods
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsSupported(this TypeTag tag)
		{
			switch (tag)
			{
			case TypeTag.False:
			case TypeTag.Infinitum:
			case TypeTag.Nil:
			case TypeTag.AltTypeString:
			case TypeTag.True:
			case TypeTag.ArrayStart:
			case TypeTag.ArrayEnd:
			case TypeTag.Blob:
			case TypeTag.AsciiChar32:
			case TypeTag.Float64:
			case TypeTag.Float32:
			case TypeTag.Int64:
			case TypeTag.Int32:
			case TypeTag.MIDI:
			case TypeTag.Color32:
			case TypeTag.String:
			case TypeTag.TimeTag:
				return true;
			default:
				return false;
			}
		}
	}
	internal enum Vector3ElementFilter : byte
	{
		XYZ,
		X,
		Y,
		Z,
		XY,
		XZ,
		YZ
	}
	internal enum Vector2ElementFilter : byte
	{
		XY,
		X,
		Y
	}
	public sealed class OscMessageValues
	{
		private const int k_ResizeByteHeadroom = 1024;

		private readonly byte[] m_SharedBuffer;

		private unsafe readonly byte* SharedBufferPtr;

		private readonly byte[] m_SwapBuffer32 = new byte[4];

		private unsafe readonly float* SwapBuffer32Ptr;

		private unsafe readonly uint* SwapBuffer32UintPtr;

		private unsafe readonly Color32* SwapBufferColor32Ptr;

		private readonly GCHandle m_Swap32Handle;

		private readonly byte[] m_SwapBuffer64 = new byte[8];

		private unsafe readonly double* SwapBuffer64Ptr;

		private readonly GCHandle m_Swap64Handle;

		internal readonly TypeTag[] Tags;

		internal readonly int[] Offsets;

		public int ElementCount { get; internal set; }

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public char ReadAsciiCharElement(int index)
		{
			if (Tags[index] == TypeTag.AsciiChar32)
			{
				return (char)m_SharedBuffer[Offsets[index] + 3];
			}
			return '\0';
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int ReadBlobElement(int index, ref byte[] copyTo, int copyOffset = 0)
		{
			if (Tags[index] == TypeTag.Blob)
			{
				int num = Offsets[index];
				int num2 = ReadIntIndex(num);
				int srcOffset = num + 4;
				if (copyTo.Length - copyOffset <= num2)
				{
					Array.Resize(ref copyTo, num2 + copyOffset + 1024);
				}
				Buffer.BlockCopy(m_SharedBuffer, srcOffset, copyTo, copyOffset, num2);
				return num2;
			}
			return 0;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool ReadBooleanElement(int index)
		{
			return Tags[index] switch
			{
				TypeTag.True => true, 
				TypeTag.False => false, 
				TypeTag.Int32 => ReadIntElementUnchecked(index) > 0, 
				_ => false, 
			};
		}

		public unsafe Color32 ReadColor32Element(int index)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			int num = Offsets[index];
			if (Tags[index] == TypeTag.Color32)
			{
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				return *SwapBufferColor32Ptr;
			}
			return default(Color32);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe Color32 ReadColor32ElementUnchecked(int index)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			int num = Offsets[index];
			m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
			m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
			m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
			m_SwapBuffer32[3] = m_SharedBuffer[num];
			return *SwapBufferColor32Ptr;
		}

		internal unsafe OscMessageValues(byte[] buffer, int elementCapacity = 8)
		{
			ElementCount = 0;
			Tags = new TypeTag[elementCapacity];
			Offsets = new int[elementCapacity];
			m_SharedBuffer = buffer;
			fixed (byte* sharedBufferPtr = buffer)
			{
				SharedBufferPtr = sharedBufferPtr;
			}
			m_Swap32Handle = GCHandle.Alloc(m_SwapBuffer32, GCHandleType.Pinned);
			IntPtr intPtr = m_Swap32Handle.AddrOfPinnedObject();
			SwapBuffer32Ptr = (float*)(void*)intPtr;
			SwapBuffer32UintPtr = (uint*)(void*)intPtr;
			SwapBufferColor32Ptr = (Color32*)(void*)intPtr;
			SwapBuffer64Ptr = Utils.PinPtr<byte, double>(m_SwapBuffer64, out m_Swap64Handle);
		}

		~OscMessageValues()
		{
			m_Swap32Handle.Free();
			m_Swap64Handle.Free();
		}

		public void ForEachElement(Action<int, TypeTag> elementAction)
		{
			for (int i = 0; i < ElementCount; i++)
			{
				elementAction(i, Tags[i]);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private bool OutOfBounds(int index)
		{
			if (index >= ElementCount)
			{
				((MelonBase)Core.Instance).LoggerInstance.Error($"Tried to read message element index {index}, but there are only {ElementCount} elements");
				return true;
			}
			return false;
		}

		public unsafe float ReadFloatElement(int index)
		{
			int num = Offsets[index];
			switch (Tags[index])
			{
			case TypeTag.Float32:
				m_SwapBuffer32[0] = SharedBufferPtr[num + 3];
				m_SwapBuffer32[1] = SharedBufferPtr[num + 2];
				m_SwapBuffer32[2] = SharedBufferPtr[num + 1];
				m_SwapBuffer32[3] = SharedBufferPtr[num];
				return *SwapBuffer32Ptr;
			case TypeTag.Int32:
				return (SharedBufferPtr[index] << 24) | (SharedBufferPtr[index + 1] << 16) | (SharedBufferPtr[index + 2] << 8) | SharedBufferPtr[index + 3];
			default:
				return 0f;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe float ReadFloatElementUnchecked(int index)
		{
			int num = Offsets[index];
			m_SwapBuffer32[0] = SharedBufferPtr[num + 3];
			m_SwapBuffer32[1] = SharedBufferPtr[num + 2];
			m_SwapBuffer32[2] = SharedBufferPtr[num + 1];
			m_SwapBuffer32[3] = SharedBufferPtr[num];
			return *SwapBuffer32Ptr;
		}

		public unsafe double ReadFloat64Element(int index)
		{
			int num = Offsets[index];
			switch (Tags[index])
			{
			case TypeTag.Float64:
				m_SwapBuffer64[7] = m_SharedBuffer[num];
				m_SwapBuffer64[6] = m_SharedBuffer[num + 1];
				m_SwapBuffer64[5] = m_SharedBuffer[num + 2];
				m_SwapBuffer64[4] = m_SharedBuffer[num + 3];
				m_SwapBuffer64[3] = m_SharedBuffer[num + 4];
				m_SwapBuffer64[2] = m_SharedBuffer[num + 5];
				m_SwapBuffer64[1] = m_SharedBuffer[num + 6];
				m_SwapBuffer64[0] = m_SharedBuffer[num + 7];
				return *SwapBuffer64Ptr;
			case TypeTag.Float32:
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				return *SwapBuffer32Ptr;
			case TypeTag.Int64:
				return IPAddress.NetworkToHostOrder((long)SharedBufferPtr[num]);
			case TypeTag.Int32:
				return (m_SharedBuffer[index] << 24) | (m_SharedBuffer[index + 1] << 16) | (m_SharedBuffer[index + 2] << 8) | m_SharedBuffer[index + 3];
			default:
				return 0.0;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe double ReadFloat64ElementUnchecked(int index)
		{
			int num = Offsets[index];
			m_SwapBuffer64[7] = m_SharedBuffer[num];
			m_SwapBuffer64[6] = m_SharedBuffer[num + 1];
			m_SwapBuffer64[5] = m_SharedBuffer[num + 2];
			m_SwapBuffer64[4] = m_SharedBuffer[num + 3];
			m_SwapBuffer64[3] = m_SharedBuffer[num + 4];
			m_SwapBuffer64[2] = m_SharedBuffer[num + 5];
			m_SwapBuffer64[1] = m_SharedBuffer[num + 6];
			m_SwapBuffer64[0] = m_SharedBuffer[num + 7];
			return *SwapBuffer64Ptr;
		}

		public unsafe int ReadIntElement(int index)
		{
			int num = Offsets[index];
			switch (Tags[index])
			{
			case TypeTag.Int32:
				return (m_SharedBuffer[num] << 24) | (m_SharedBuffer[num + 1] << 16) | (m_SharedBuffer[num + 2] << 8) | m_SharedBuffer[num + 3];
			case TypeTag.Float32:
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				return (int)(*SwapBuffer32Ptr);
			default:
				return 0;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int ReadIntElementUnchecked(int index)
		{
			int num = Offsets[index];
			return (m_SharedBuffer[num] << 24) | (m_SharedBuffer[num + 1] << 16) | (m_SharedBuffer[num + 2] << 8) | m_SharedBuffer[num + 3];
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal unsafe uint ReadUIntIndex(int index)
		{
			m_SwapBuffer32[0] = m_SharedBuffer[index + 3];
			m_SwapBuffer32[1] = m_SharedBuffer[index + 2];
			m_SwapBuffer32[2] = m_SharedBuffer[index + 1];
			m_SwapBuffer32[3] = m_SharedBuffer[index];
			return *SwapBuffer32UintPtr;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal int ReadIntIndex(int index)
		{
			return (m_SharedBuffer[index] << 24) | (m_SharedBuffer[index + 1] << 16) | (m_SharedBuffer[index + 2] << 8) | m_SharedBuffer[index + 3];
		}

		public unsafe long ReadInt64Element(int index)
		{
			int num = Offsets[index];
			switch (Tags[index])
			{
			case TypeTag.Int64:
				return IPAddress.NetworkToHostOrder((long)SharedBufferPtr[num]);
			case TypeTag.Int32:
				return (m_SharedBuffer[num] << 24) | (m_SharedBuffer[num + 1] << 16) | (m_SharedBuffer[num + 2] << 8) | m_SharedBuffer[num + 3];
			case TypeTag.Float64:
				m_SwapBuffer64[7] = m_SharedBuffer[num];
				m_SwapBuffer64[6] = m_SharedBuffer[num + 1];
				m_SwapBuffer64[5] = m_SharedBuffer[num + 2];
				m_SwapBuffer64[4] = m_SharedBuffer[num + 3];
				m_SwapBuffer64[3] = m_SharedBuffer[num + 4];
				m_SwapBuffer64[2] = m_SharedBuffer[num + 5];
				m_SwapBuffer64[1] = m_SharedBuffer[num + 6];
				m_SwapBuffer64[0] = m_SharedBuffer[num + 7];
				return (long)(*SwapBuffer64Ptr);
			case TypeTag.Float32:
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				return (long)(*SwapBuffer32Ptr);
			default:
				return 0L;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe long ReadInt64ElementUnchecked(int index)
		{
			return IPAddress.NetworkToHostOrder((long)SharedBufferPtr[Offsets[index]]);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe MidiMessage ReadMidiElement(int index)
		{
			if (Tags[index] == TypeTag.MIDI)
			{
				return *(MidiMessage*)(SharedBufferPtr + Offsets[index]);
			}
			return default(MidiMessage);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe MidiMessage ReadMidiElementUnchecked(int index)
		{
			return *(MidiMessage*)(SharedBufferPtr + Offsets[index]);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool ReadNilOrInfinitumElement(int index)
		{
			TypeTag typeTag = Tags[index];
			if (typeTag == TypeTag.Infinitum || typeTag == TypeTag.Nil)
			{
				return true;
			}
			return false;
		}

		public unsafe string ReadStringElement(int index)
		{
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			int num = Offsets[index];
			switch (Tags[index])
			{
			case TypeTag.AltTypeString:
			case TypeTag.String:
			{
				int i;
				for (i = 0; m_SharedBuffer[num + i] != 0; i++)
				{
				}
				return Encoding.UTF8.GetString(m_SharedBuffer, num, i);
			}
			case TypeTag.Float64:
			{
				m_SwapBuffer64[7] = m_SharedBuffer[num];
				m_SwapBuffer64[6] = m_SharedBuffer[num + 1];
				m_SwapBuffer64[5] = m_SharedBuffer[num + 2];
				m_SwapBuffer64[4] = m_SharedBuffer[num + 3];
				m_SwapBuffer64[3] = m_SharedBuffer[num + 4];
				m_SwapBuffer64[2] = m_SharedBuffer[num + 5];
				m_SwapBuffer64[1] = m_SharedBuffer[num + 6];
				m_SwapBuffer64[0] = m_SharedBuffer[num + 7];
				double swapBuffer64Ptr = *SwapBuffer64Ptr;
				return swapBuffer64Ptr.ToString(CultureInfo.CurrentCulture);
			}
			case TypeTag.Float32:
			{
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				float swapBuffer32Ptr = *SwapBuffer32Ptr;
				return swapBuffer32Ptr.ToString(CultureInfo.CurrentCulture);
			}
			case TypeTag.Int64:
				return IPAddress.NetworkToHostOrder(m_SharedBuffer[num]).ToString(CultureInfo.CurrentCulture);
			case TypeTag.Int32:
				return ((m_SharedBuffer[num] << 24) | (m_SharedBuffer[num + 1] << 16) | (m_SharedBuffer[num + 2] << 8) | m_SharedBuffer[num + 3]).ToString(CultureInfo.CurrentCulture);
			case TypeTag.False:
				return "False";
			case TypeTag.True:
				return "True";
			case TypeTag.Nil:
				return "Nil";
			case TypeTag.Infinitum:
				return "Infinitum";
			case TypeTag.Color32:
			{
				m_SwapBuffer32[0] = m_SharedBuffer[num + 3];
				m_SwapBuffer32[1] = m_SharedBuffer[num + 2];
				m_SwapBuffer32[2] = m_SharedBuffer[num + 1];
				m_SwapBuffer32[3] = m_SharedBuffer[num];
				Color32 swapBufferColor32Ptr = *SwapBufferColor32Ptr;
				return ((object)(Color32)(ref swapBufferColor32Ptr)).ToString();
			}
			case TypeTag.MIDI:
			{
				MidiMessage midiMessage = *(MidiMessage*)(SharedBufferPtr + num);
				return midiMessage.ToString();
			}
			case TypeTag.AsciiChar32:
			{
				char c = (char)m_SharedBuffer[num + 3];
				return c.ToString();
			}
			default:
				return string.Empty;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int ReadStringElementBytes(int index, byte[] copyTo)
		{
			TypeTag typeTag = Tags[index];
			if (typeTag == TypeTag.AltTypeString || typeTag == TypeTag.String)
			{
				int num = Offsets[index];
				int i;
				for (i = num; i < m_SharedBuffer.Length; i++)
				{
					byte b = m_SharedBuffer[i];
					if (b == 0)
					{
						break;
					}
					copyTo[i - num] = b;
				}
				return i - num;
			}
			return 0;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int ReadStringElementBytes(int index, byte[] copyTo, int copyOffset)
		{
			TypeTag typeTag = Tags[index];
			if (typeTag == TypeTag.AltTypeString || typeTag == TypeTag.String)
			{
				int num = Offsets[index];
				int num2 = num - copyOffset;
				int i;
				for (i = num; i < m_SharedBuffer.Length; i++)
				{
					byte b = m_SharedBuffer[i];
					if (b == 0)
					{
						break;
					}
					copyTo[i - num2] = b;
				}
				return i - num;
			}
			return 0;
		}

		public unsafe NtpTimestamp ReadTimestampElement(int index)
		{
			if (Tags[index] == TypeTag.TimeTag)
			{
				return NtpTimestamp.FromBigEndianBytes(SharedBufferPtr + Offsets[index]);
			}
			return default(NtpTimestamp);
		}

		public unsafe NtpTimestamp ReadTimestampElementUnchecked(int index)
		{
			return NtpTimestamp.FromBigEndianBytes(SharedBufferPtr + Offsets[index]);
		}

		internal unsafe NtpTimestamp ReadTimestampIndex(int index)
		{
			byte* num = SharedBufferPtr + index;
			uint num2 = *(uint*)num;
			uint seconds = ((num2 & 0xFF) << 24) | ((num2 & 0xFF00) << 8) | ((num2 & 0xFF0000) >> 8) | ((num2 & 0xFF000000u) >> 24);
			uint num3 = *(uint*)(num + 4);
			uint fractions = ((num3 & 0xFF) << 24) | ((num3 & 0xFF00) << 8) | ((num3 & 0xFF0000) >> 8) | ((num3 & 0xFF000000u) >> 24);
			return new NtpTimestamp(seconds, fractions);
		}
	}
	public class OscActionPair
	{
		public readonly Action<OscMessageValues> ValueRead;

		public readonly Action MainThreadQueued;

		public OscActionPair(Action<OscMessageValues> valueRead, Action mainThreadQueued = null)
		{
			ValueRead = valueRead ?? throw new ArgumentNullException("valueRead", "Value read callbacks required!");
			MainThreadQueued = mainThreadQueued;
		}

		public static OscActionPair operator +(OscActionPair l, OscActionPair r)
		{
			Action mainThreadQueued = ((l.MainThreadQueued == null) ? r.MainThreadQueued : ((Action)Delegate.Combine(l.MainThreadQueued, r.MainThreadQueued)));
			return new OscActionPair((Action<OscMessageValues>)Delegate.Combine(l.ValueRead, r.ValueRead), mainThreadQueued);
		}

		public static OscActionPair operator -(OscActionPair l, OscActionPair r)
		{
			Action mainThreadQueued = ((l.MainThreadQueued == null) ? r.MainThreadQueued : ((Action)Delegate.Remove(l.MainThreadQueued, r.MainThreadQueued)));
			return new OscActionPair((Action<OscMessageValues>)Delegate.Remove(l.ValueRead, r.ValueRead), mainThreadQueued);
		}
	}
	public sealed class OscAddressSpace
	{
		private const int k_DefaultPatternCapacity = 8;

		private const int k_DefaultCapacity = 16;

		private StringBuilder escapedStringBuilder = new StringBuilder();

		private HashSet<char> specialRegexCharacters = new HashSet<char>(new char[14]
		{
			'.', '^', '$', '*', '+', '?', '{', '}', '[', ']',
			'\\', '|', '(', ')'
		});

		internal readonly OscAddressMethods AddressToMethod;

		internal int PatternCount;

		internal Regex[] Patterns = new Regex[8];

		internal OscActionPair[] PatternMethods = new OscActionPair[8];

		private readonly Queue<int> FreedPatternIndices = new Queue<int>();

		private readonly Dictionary<string, int> PatternStringToIndex = new Dictionary<string, int>();

		public int HandlerCount => AddressToMethod.HandleToValue.Count;

		public IEnumerable<string> Addresses => AddressToMethod.SourceToBlob.Keys;

		public OscAddressSpace(int startingCapacity = 16)
		{
			AddressToMethod = new OscAddressMethods(startingCapacity);
		}

		public bool TryAddMethod(string address, OscActionPair onReceived)
		{
			if (string.IsNullOrEmpty(address) || onReceived == null)
			{
				return false;
			}
			switch (OscParser.GetAddressType(address))
			{
			case AddressType.Address:
				AddressToMethod.Add(address, onReceived);
				return true;
			case AddressType.Pattern:
			{
				if (PatternStringToIndex.TryGetValue(address, out var value))
				{
					OscActionPair[] patternMethods = PatternMethods;
					int num = value;
					patternMethods[num] += onReceived;
					return true;
				}
				if (FreedPatternIndices.Count > 0)
				{
					value = FreedPatternIndices.Dequeue();
				}
				else
				{
					value = PatternCount;
					if (value >= Patterns.Length)
					{
						int newSize = Patterns.Length * 2;
						Array.Resize(ref Patterns, newSize);
						Array.Resize(ref PatternMethods, newSize);
					}
				}
				Regex regex = null;
				try
				{
					regex = new Regex(address);
				}
				catch (ArgumentException ex)
				{
					try
					{
						regex = new Regex(EscapeRegexSpecialCharacters(address));
					}
					catch (Exception)
					{
						throw ex;
					}
				}
				Patterns[value] = regex;
				PatternMethods[value] = onReceived;
				PatternStringToIndex[address] = value;
				PatternCount++;
				return true;
			}
			default:
				return false;
			}
		}

		public bool RemoveAddressMethod(string address)
		{
			if (string.IsNullOrEmpty(address))
			{
				return false;
			}
			if (OscParser.GetAddressType(address) == AddressType.Address)
			{
				return AddressToMethod.RemoveAddress(address);
			}
			return false;
		}

		public bool RemoveMethod(string address, OscActionPair onReceived)
		{
			if (string.IsNullOrEmpty(address) || onReceived == null)
			{
				return false;
			}
			switch (OscParser.GetAddressType(address))
			{
			case AddressType.Address:
				return AddressToMethod.Remove(address, onReceived);
			case AddressType.Pattern:
			{
				if (!PatternStringToIndex.TryGetValue(address, out var value))
				{
					return false;
				}
				if (PatternMethods[value].ValueRead.GetInvocationList().Length == 1)
				{
					Patterns[value] = null;
					PatternMethods[value] = null;
				}
				else
				{
					OscActionPair[] patternMethods = PatternMethods;
					int num = value;
					patternMethods[num] -= onReceived;
				}
				PatternCount--;
				FreedPatternIndices.Enqueue(value);
				return PatternStringToIndex.Remove(address);
			}
			default:
				return false;
			}
		}

		public bool TryMatchPatternHandler(string address, List<OscActionPair> allMatchedMethods)
		{
			if (!OscParser.AddressIsValid(address))
			{
				return false;
			}
			allMatchedMethods.Clear();
			bool result = false;
			for (int i = 0; i < PatternCount; i++)
			{
				if (Patterns[i].IsMatch(address))
				{
					OscActionPair callbacks = PatternMethods[i];
					AddressToMethod.Add(address, callbacks);
					result = true;
				}
			}
			return result;
		}

		private string EscapeRegexSpecialCharacters(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			escapedStringBuilder.Clear();
			foreach (char c in input)
			{
				if (specialRegexCharacters.Contains(c))
				{
					escapedStringBuilder.Append('\\');
				}
				escapedStringBuilder.Append(c);
			}
			return escapedStringBuilder.ToString();
		}
	}
	public class OscClient
	{
		protected readonly Socket m_Socket;

		protected readonly OscWriter m_Writer;

		private const uint k_Int32TypeTagBytes = 26924u;

		private const uint k_Float32TypeTagBytes = 26156u;

		private const uint k_StringTypeTagBytes = 29484u;

		private const uint k_BlobTypeTagBytes = 25132u;

		private const uint k_Int64TypeTagBytes = 25644u;

		private const uint k_Float64TypeTagBytes = 26668u;

		private const uint k_Color32TypeTagBytes = 29228u;

		private const uint k_MidiTypeTagBytes = 27948u;

		private const uint k_CharTypeTagBytes = 25388u;

		private const uint k_TrueTypeTagBytes = 21548u;

		private const uint k_FalseTypeTagBytes = 17964u;

		private const uint k_NilTypeTagBytes = 20012u;

		private const uint k_InfinitumTypeTagBytes = 18732u;

		public OscWriter Writer => m_Writer;

		public IPEndPoint Destination { get; }

		public OscClient(string ipAddress, int port)
		{
			m_Writer = new OscWriter();
			m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
			if (ipAddress == "255.255.255.255")
			{
				m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, optionValue: true);
			}
			Destination = new IPEndPoint(IPAddress.Parse(ipAddress), port);
			m_Socket.Connect(Destination);
		}

		public void Send(string address)
		{
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",");
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, int element)
		{
			m_Writer.WriteAddressAndTags(address, 26924u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, float element)
		{
			m_Writer.WriteAddressAndTags(address, 26156u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, string element)
		{
			m_Writer.WriteAddressAndTags(address, 29484u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, byte[] bytes, int length, int start = 0)
		{
			m_Writer.WriteAddressAndTags(address, 25132u);
			m_Writer.Write(bytes, length, start);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, Vector2 element)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",ff");
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, float element1, float element2)
		{
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",ff");
			m_Writer.Write(element1);
			m_Writer.Write(element2);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, Vector3 element)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",fff");
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, float element1, float element2, float element3)
		{
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",fff");
			m_Writer.Write(element1);
			m_Writer.Write(element2);
			m_Writer.Write(element3);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, float element1, float element2, float element3, float element4)
		{
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",ffff");
			m_Writer.Write(element1);
			m_Writer.Write(element2);
			m_Writer.Write(element3);
			m_Writer.Write(element4);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, Vector3 element1, Vector3 element2)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			m_Writer.Reset();
			m_Writer.Write(address);
			m_Writer.Write(",ffffff");
			m_Writer.Write(element1);
			m_Writer.Write(element2);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, double element)
		{
			m_Writer.WriteAddressAndTags(address, 25644u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, long element)
		{
			m_Writer.WriteAddressAndTags(address, 26668u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, Color32 element)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			m_Writer.WriteAddressAndTags(address, 29228u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, MidiMessage element)
		{
			m_Writer.WriteAddressAndTags(address, 27948u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, char element)
		{
			m_Writer.WriteAddressAndTags(address, 25388u);
			m_Writer.Write(element);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void Send(string address, bool element)
		{
			m_Writer.WriteAddressAndTags(address, element ? 21548u : 17964u);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void SendNil(string address)
		{
			m_Writer.WriteAddressAndTags(address, 20012u);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void SendInfinitum(string address)
		{
			m_Writer.WriteAddressAndTags(address, 18732u);
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		public void ForceSendBuffer()
		{
			m_Socket.Send(m_Writer.Buffer, m_Writer.Length, SocketFlags.None);
		}

		private unsafe static uint[] GetAlignedAsciiBytes(string input)
		{
			int byteCount = Encoding.ASCII.GetByteCount(input);
			uint[] array = new uint[((byteCount + 3) & -4) / 4];
			fixed (uint* bytes = array)
			{
				fixed (char* chars = input)
				{
					Encoding.ASCII.GetBytes(chars, input.Length, (byte*)bytes, byteCount);
				}
			}
			return array;
		}
	}
	public class OscParser
	{
		public const int MaxElementsPerMessage = 32;

		public const int MaxBlobSize = 262144;

		internal readonly byte[] Buffer;

		internal unsafe readonly byte* BufferPtr;

		internal unsafe readonly long* BufferLongPtr;

		public readonly OscMessageValues MessageValues;

		public unsafe OscParser(byte[] fixedBuffer)
		{
			Buffer = fixedBuffer;
			fixed (byte* ptr = fixedBuffer)
			{
				BufferPtr = ptr;
				BufferLongPtr = (long*)ptr;
			}
			MessageValues = new OscMessageValues(Buffer, 32);
		}

		public int Parse()
		{
			int num = FindUnalignedAddressLength();
			if (num < 0)
			{
				return num;
			}
			int num2 = (num + 3) & -4;
			if (num2 == num)
			{
				num2 += 4;
			}
			int num3 = ParseTags(Buffer, num2);
			int offset = (num2 + (num3 + 4)) & -4;
			FindOffsets(offset);
			return num;
		}

		public int Parse(int startingByteOffset)
		{
			int num = FindUnalignedAddressLength(startingByteOffset);
			if (num < 0)
			{
				return num;
			}
			int num2 = (num + 3) & -4;
			if (num2 == num)
			{
				num2 += 4;
			}
			int num3 = startingByteOffset + num2;
			int num4 = ParseTags(Buffer, num3);
			int offset = (num3 + (num4 + 4)) & -4;
			FindOffsets(offset);
			return num;
		}

		internal static bool AddressIsValid(string address)
		{
			if (address[0] != '/')
			{
				return false;
			}
			for (int i = 0; i < address.Length; i++)
			{
				switch (address[i])
				{
				case ' ':
				case '#':
				case '*':
				case ',':
				case '?':
				case '[':
				case ']':
				case '{':
				case '}':
					return false;
				}
			}
			return true;
		}

		internal static bool CharacterIsValidInAddress(char c)
		{
			switch (c)
			{
			case ' ':
			case '#':
			case '*':
			case ',':
			case '?':
			case '[':
			case ']':
			case '{':
			case '}':
				return false;
			default:
				return true;
			}
		}

		internal static AddressType GetAddressType(string address)
		{
			if (address[0] != '/')
			{
				return AddressType.Invalid;
			}
			bool flag = true;
			string text = address;
			for (int i = 0; i < text.Length; i++)
			{
				switch (text[i])
				{
				case ' ':
				case '#':
				case '*':
				case ',':
				case '?':
				case '[':
				case ']':
				case '{':
				case '}':
					flag = false;
					break;
				}
			}
			if (flag)
			{
				return AddressType.Address;
			}
			text = address;
			foreach (char c in text)
			{
				if (c == ' ' || c == '#' || c == ',')
				{
					return AddressType.Invalid;
				}
			}
			return AddressType.Pattern;
		}

		internal int ParseTags(byte[] bytes, int start = 0)
		{
			if (bytes[start] != 44)
			{
				return 0;
			}
			int num = start + 1;
			int num2 = 0;
			TypeTag[] tags = MessageValues.Tags;
			while (true)
			{
				TypeTag typeTag = (TypeTag)bytes[num];
				if (!typeTag.IsSupported())
				{
					break;
				}
				tags[num2] = typeTag;
				num++;
				num2++;
			}
			MessageValues.ElementCount = num2;
			return num2 + 1;
		}

		public unsafe int FindUnalignedAddressLength()
		{
			if (*BufferPtr != 47)
			{
				return -1;
			}
			int num = 1;
			do
			{
				num++;
			}
			while (BufferPtr[num] != 0);
			return num;
		}

		public unsafe int FindUnalignedAddressLength(int offset)
		{
			if (BufferPtr[offset] != 47)
			{
				return -1;
			}
			int num = offset + 1;
			do
			{
				num++;
			}
			while (BufferPtr[num] != 0);
			return num - offset;
		}

		public int GetStringLength(int offset)
		{
			int num = Buffer.Length - offset;
			int i;
			for (i = offset; i < num && Buffer[i] == 0; i++)
			{
			}
			return (i - offset + 3) & -4;
		}

		public unsafe void FindOffsets(int offset)
		{
			TypeTag[] tags = MessageValues.Tags;
			int[] offsets = MessageValues.Offsets;
			for (int i = 0; i < MessageValues.ElementCount; i++)
			{
				offsets[i] = offset;
				switch (tags[i])
				{
				case TypeTag.AsciiChar32:
				case TypeTag.Float32:
				case TypeTag.Int32:
				case TypeTag.MIDI:
				case TypeTag.Color32:
					offset += 4;
					break;
				case TypeTag.Float64:
				case TypeTag.Int64:
				case TypeTag.TimeTag:
					offset += 8;
					break;
				case TypeTag.AltTypeString:
				case TypeTag.String:
					offset += GetStringLength(offset);
					break;
				case TypeTag.Blob:
					offset += 4 + *(int*)(BufferPtr + offset);
					break;
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe bool IsBundleTagAtIndex(int index)
		{
			return *(long*)(BufferPtr + (nint)index * (nint)8) == Constant.BundlePrefixLong;
		}

		public static int FindArrayLength(byte[] bytes, int offset = 0)
		{
			if (bytes[offset] != 91)
			{
				return -1;
			}
			int i;
			for (i = offset + 1; bytes[i] != 93; i++)
			{
			}
			return i - offset;
		}
	}
	public sealed class OscServer : IDisposable
	{
		private static readonly Dictionary<Action<OscMessageValues>, OscActionPair> k_SingleCallbackToPair = new Dictionary<Action<OscMessageValues>, OscActionPair>();

		private readonly OscSocket m_Socket;

		private bool m_Disposed;

		private bool m_Started;

		private readonly byte[] m_ReadBuffer;

		private GCHandle m_BufferHandle;

		private unsafe byte* m_BufferPtr;

		private Action[] m_MainThreadQueue = new Action[16];

		private int m_MainThreadCount;

		private readonly Dictionary<int, string> m_ByteLengthToStringBuffer = new Dictionary<int, string>();

		private readonly HashSet<MonitorCallback> m_MonitorCallbacks = new HashSet<MonitorCallback>();

		private readonly List<OscActionPair> m_PatternMatchedMethods = new List<OscActionPair>();

		public static readonly Dictionary<int, OscServer> PortToServer = new Dictionary<int, OscServer>();

		internal bool Running { get; set; }

		public int Port { get; }

		public OscAddressSpace AddressSpace { get; private set; }

		public OscParser Parser { get; }

		public NtpTimestamp LastBundleTimestamp { get; private set; }

		public unsafe OscServer(int port, int bufferSize = 4096)
		{
			if (PortToServer.ContainsKey(port))
			{
				((MelonBase)Core.Instance).LoggerInstance.Error($"port {port} is already in use, cannot start a new OSC Server on it");
				return;
			}
			k_SingleCallbackToPair.Clear();
			AddressSpace = new OscAddressSpace();
			m_ReadBuffer = new byte[bufferSize];
			m_BufferHandle = GCHandle.Alloc(m_ReadBuffer, GCHandleType.Pinned);
			m_BufferPtr = (byte*)(void*)m_BufferHandle.AddrOfPinnedObject();
			Parser = new OscParser(m_ReadBuffer);
			Port = port;
			m_Socket = new OscSocket(port)
			{
				Server = this
			};
			Start();
		}

		public void Start()
		{
			if (m_Started)
			{
				Running = true;
				return;
			}
			m_Socket.Start();
			m_Disposed = false;
			m_Started = true;
			Running = true;
		}

		public static OscServer GetOrCreate(int port)
		{
			if (!PortToServer.TryGetValue(port, out OscServer value))
			{
				value = new OscServer(port);
				PortToServer[port] = value;
			}
			return value;
		}

		public static bool Remove(int port)
		{
			if (PortToServer.TryGetValue(port, out OscServer value))
			{
				value.Dispose();
				return PortToServer.Remove(port);
			}
			return false;
		}

		public bool TryAddMethod(string address, Action<OscMessageValues> valueReadMethod)
		{
			OscActionPair oscActionPair = new OscActionPair(valueReadMethod);
			k_SingleCallbackToPair.Add(valueReadMethod, oscActionPair);
			return AddressSpace.TryAddMethod(address, oscActionPair);
		}

		public bool RemoveMethod(string address, Action<OscMessageValues> valueReadMethod)
		{
			if (k_SingleCallbackToPair.TryGetValue(valueReadMethod, out OscActionPair value))
			{
				if (AddressSpace.RemoveMethod(address, value))
				{
					return k_SingleCallbackToPair.Remove(valueReadMethod);
				}
				return false;
			}
			return false;
		}

		public bool RemoveAddress(string address)
		{
			return AddressSpace.RemoveAddressMethod(address);
		}

		public bool TryAddMethodPair(string address, OscActionPair actionPair)
		{
			return AddressSpace.TryAddMethod(address, actionPair);
		}

		public bool TryAddMethodPair(string address, Action<OscMessageValues> read, Action mainThread)
		{
			return AddressSpace.TryAddMethod(address, new OscActionPair(read, mainThread));
		}

		public bool RemoveMethodPair(string address, OscActionPair actionPair)
		{
			if (AddressSpace != null)
			{
				return AddressSpace.RemoveMethod(address, actionPair);
			}
			return true;
		}

		public void AddMonitorCallback(MonitorCallback callback)
		{
			m_MonitorCallbacks.Add(callback);
		}

		public bool RemoveMonitorCallback(MonitorCallback callback)
		{
			return m_MonitorCallbacks.Remove(callback);
		}

		public void Update()
		{
			for (int i = 0; i < m_MainThreadCount; i++)
			{
				m_MainThreadQueue[i]();
			}
			m_MainThreadCount = 0;
		}

		public unsafe void ParseBuffer(int byteLength)
		{
			byte* bufferPtr = Parser.BufferPtr;
			long* bufferLongPtr = Parser.BufferLongPtr;
			OscParser parser = Parser;
			OscAddressMethods addressToMethod = AddressSpace.AddressToMethod;
			if (*bufferLongPtr != Constant.BundlePrefixLong)
			{
				int num = parser.Parse();
				if (num >= 0)
				{
					if (addressToMethod.TryGetValueFromBytes(bufferPtr, num, out OscActionPair value))
					{
						HandleCallbacks(value, parser.MessageValues);
					}
					else if (AddressSpace.PatternCount > 0)
					{
						TryMatchPatterns(parser, bufferPtr, num);
					}
					Profiler.EndSample();
					if (m_MonitorCallbacks.Count > 0)
					{
						HandleMonitorCallbacks(bufferPtr, num, parser);
					}
				}
				return;
			}
			int num2 = 0;
			bool flag;
			do
			{
				LastBundleTimestamp = parser.MessageValues.ReadTimestampIndex(num2 + 8);
				num2 += 16;
				flag = false;
				while (num2 < byteLength && !flag)
				{
					int num3 = (int)parser.MessageValues.ReadUIntIndex(num2);
					int num4 = num2 + 4;
					if (parser.IsBundleTagAtIndex(num4))
					{
						num2 = num4;
						flag = true;
						continue;
					}
					int num5 = parser.Parse(num4);
					if (num5 <= 0)
					{
						num2 += num3 + 4;
						continue;
					}
					byte* ptr = bufferPtr + num4;
					if (addressToMethod.TryGetValueFromBytes(ptr, num5, out OscActionPair value2))
					{
						HandleCallbacks(value2, parser.MessageValues);
					}
					else if (AddressSpace.PatternCount > 0)
					{
						TryMatchPatterns(parser, bufferPtr, num5);
					}
					num2 += num3 + 4;
					if (m_MonitorCallbacks.Count > 0)
					{
						HandleMonitorCallbacks(ptr, num5, parser);
					}
				}
			}
			while (flag);
		}

		private void HandleCallbacks(OscActionPair pair, OscMessageValues messageValues)
		{
			pair.ValueRead(messageValues);
			if (pair.MainThreadQueued != null)
			{
				if (m_MainThreadCount >= m_MainThreadQueue.Length)
				{
					Array.Resize(ref m_MainThreadQueue, m_MainThreadCount + 16);
				}
				m_MainThreadQueue[m_MainThreadCount++] = pair.MainThreadQueued;
			}
		}

		private unsafe void HandleMonitorCallbacks(byte* bufferPtr, int addressLength, OscParser parser)
		{
			BlobString address = new BlobString(bufferPtr, addressLength);
			foreach (MonitorCallback monitorCallback in m_MonitorCallbacks)
			{
				monitorCallback(address, parser.MessageValues);
			}
		}

		private unsafe void TryMatchPatterns(OscParser parser, byte* bufferPtr, int addressLength)
		{
			if (!m_ByteLengthToStringBuffer.TryGetValue(addressLength, out string value))
			{
				value = Encoding.ASCII.GetString(bufferPtr, addressLength);
				m_ByteLengthToStringBuffer[addressLength] = value;
			}
			else
			{
				OverwriteAsciiString(value, bufferPtr);
			}
			if (!AddressSpace.TryMatchPatternHandler(value, m_PatternMatchedMethods))
			{
				return;
			}
			string address = string.Copy(value);
			AddressSpace.AddressToMethod.Add(address, m_PatternMatchedMethods);
			foreach (OscActionPair patternMatchedMethod in m_PatternMatchedMethods)
			{
				patternMatchedMethod.ValueRead(parser.MessageValues);
				m_MainThreadQueue[m_MainThreadCount++] = patternMatchedMethod.MainThreadQueued;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe static void OverwriteAsciiString(string str, byte* bufferPtr)
		{
			fixed (char* ptr = str)
			{
				for (int i = 0; i < str.Length; i++)
				{
					ptr[i] = (char)bufferPtr[i];
				}
			}
		}

		public void Dispose()
		{
			PortToServer.Remove(Port);
			if (!m_Disposed)
			{
				m_Disposed = true;
				if (m_BufferHandle.IsAllocated)
				{
					m_BufferHandle.Free();
				}
				AddressSpace.AddressToMethod.Dispose();
				AddressSpace = null;
				m_Socket.Dispose();
			}
		}

		~OscServer()
		{
			Dispose();
		}

		public int CountHandlers()
		{
			return AddressSpace?.AddressToMethod.SourceToBlob.Count ?? 0;
		}
	}
	internal sealed class OscSocket : IDisposable
	{
		private readonly Socket m_Socket;

		private readonly Thread m_Thread;

		private bool m_Disposed;

		private bool m_Started;

		private AutoResetEvent m_ThreadWakeup;

		private bool m_CloseRequested;

		public int Port { get; }

		public OscServer Server { get; set; }

		public OscSocket(int port)
		{
			Port = port;
			m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
			{
				ReceiveTimeout = int.MaxValue
			};
			m_Thread = new Thread(Serve);
		}

		public void Start()
		{
			if (!m_Started)
			{
				m_Disposed = false;
				if (!m_Socket.IsBound)
				{
					m_Socket.Bind(new IPEndPoint(IPAddress.Any, Port));
				}
				m_ThreadWakeup = new AutoResetEvent(initialState: false);
				m_Thread.Start();
				m_Started = true;
			}
		}

		private void Serve()
		{
			byte[] buffer = Server.Parser.Buffer;
			Socket socket = m_Socket;
			while (!m_Disposed)
			{
				try
				{
					int receivedByteCount = 0;
					socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, delegate(IAsyncResult result)
					{
						try
						{
							receivedByteCount = socket.EndReceive(result);
						}
						catch (Exception ex4)
						{
							if (!m_Disposed && !m_CloseRequested)
							{
								((MelonBase)Core.Instance).LoggerInstance.Error((object)ex4);
							}
						}
						finally
						{
							m_ThreadWakeup.Set();
						}
					}, null);
					m_ThreadWakeup.WaitOne();
					if (m_CloseRequested)
					{
						m_Socket.Close();
						m_Socket.Dispose();
						break;
					}
					if (receivedByteCount != 0)
					{
						Server.ParseBuffer(receivedByteCount);
						Profiler.EndSample();
					}
					continue;
				}
				catch (SocketException)
				{
					continue;
				}
				catch (ThreadAbortException)
				{
					continue;
				}
				catch (Exception ex3)
				{
					if (!m_Disposed)
					{
						((MelonBase)Core.Instance).LoggerInstance.Error((object)ex3);
					}
				}
				break;
			}
			m_ThreadWakeup.Dispose();
		}

		public void Dispose()
		{
			if (!m_Disposed)
			{
				if (m_ThreadWakeup != null)
				{
					m_CloseRequested = true;
					m_ThreadWakeup.Set();
				}
				else
				{
					m_Socket.Close();
					m_Socket.Dispose();
				}
				m_Disposed = true;
			}
		}
	}
	public sealed class OscWriter : IDisposable
	{
		public readonly byte[] Buffer;

		private unsafe readonly byte* m_BufferPtr;

		private readonly GCHandle m_BufferHandle;

		private unsafe readonly MidiMessage* m_BufferMidiPtr;

		private readonly float[] m_FloatSwap = new float[1];

		private unsafe readonly byte* m_FloatSwapPtr;

		private readonly GCHandle m_FloatSwapHandle;

		private readonly double[] m_DoubleSwap = new double[1];

		private unsafe readonly byte* m_DoubleSwapPtr;

		private readonly GCHandle m_DoubleSwapHandle;

		private readonly Color32[] m_Color32Swap = (Color32[])(object)new Color32[1];

		private unsafe readonly byte* m_Color32SwapPtr;

		private readonly GCHandle m_Color32SwapHandle;

		private int m_Length;

		public int Length => m_Length;

		public unsafe OscWriter(int capacity = 4096)
		{
			Buffer = new byte[capacity];
			m_BufferPtr = Utils.PinPtr<byte, byte>(Buffer, out m_BufferHandle);
			m_BufferMidiPtr = (MidiMessage*)m_BufferPtr;
			m_FloatSwapPtr = Utils.PinPtr<float, byte>(m_FloatSwap, out m_FloatSwapHandle);
			m_DoubleSwapPtr = Utils.PinPtr<double, byte>(m_DoubleSwap, out m_DoubleSwapHandle);
			m_Color32SwapPtr = Utils.PinPtr<Color32, byte>(m_Color32Swap, out m_Color32SwapHandle);
		}

		~OscWriter()
		{
			Dispose();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Reset()
		{
			m_Length = 0;
		}

		public void Write(int data)
		{
			Buffer[m_Length++] = (byte)(data >> 24);
			Buffer[m_Length++] = (byte)(data >> 16);
			Buffer[m_Length++] = (byte)(data >> 8);
			Buffer[m_Length++] = (byte)data;
		}

		public unsafe void Write(float data)
		{
			m_FloatSwap[0] = data;
			Buffer[m_Length++] = m_FloatSwapPtr[3];
			Buffer[m_Length++] = m_FloatSwapPtr[2];
			Buffer[m_Length++] = m_FloatSwapPtr[1];
			Buffer[m_Length++] = *m_FloatSwapPtr;
		}

		public void Write(Vector2 data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Write(data.x);
			Write(data.y);
		}

		public void Write(Vector3 data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Write(data.x);
			Write(data.y);
			Write(data.z);
		}

		public void Write(string data)
		{
			foreach (char c in data)
			{
				Buffer[m_Length++] = (byte)c;
			}
			int num = (data.Length + 3) & -4;
			if (num == data.Length)
			{
				num += 4;
			}
			for (int j = data.Length; j < num; j++)
			{
				Buffer[m_Length++] = 0;
			}
		}

		public unsafe void Write(BlobString data)
		{
			int length = data.Length;
			System.Buffer.MemoryCopy(data.Handle.Pointer, m_BufferPtr + m_Length, length, length);
			m_Length += length;
			int num = (data.Length + 3) & -4;
			if (num == data.Length)
			{
				num += 4;
			}
			for (int i = data.Length; i < num; i++)
			{
				Buffer[m_Length++] = 0;
			}
		}

		public void Write(byte[] bytes, int length, int start = 0)
		{
			if (start + length <= bytes.Length)
			{
				Write(length);
				System.Buffer.BlockCopy(bytes, start, Buffer, m_Length, length);
				m_Length += length;
				int num = ((length + 3) & -4) - length;
				for (int i = 0; i < num; i++)
				{
					Buffer[m_Length++] = 0;
				}
			}
		}

		public void Write(long data)
		{
			byte[] buffer = Buffer;
			buffer[m_Length++] = (byte)(data >> 56);
			buffer[m_Length++] = (byte)(data >> 48);
			buffer[m_Length++] = (byte)(data >> 40);
			buffer[m_Length++] = (byte)(data >> 32);
			buffer[m_Length++] = (byte)(data >> 24);
			buffer[m_Length++] = (byte)(data >> 16);
			buffer[m_Length++] = (byte)(data >> 8);
			buffer[m_Length++] = (byte)data;
		}

		public unsafe void Write(double data)
		{
			byte[] buffer = Buffer;
			m_DoubleSwap[0] = data;
			byte* doubleSwapPtr = m_DoubleSwapPtr;
			buffer[m_Length++] = doubleSwapPtr[7];
			buffer[m_Length++] = doubleSwapPtr[6];
			buffer[m_Length++] = doubleSwapPtr[5];
			buffer[m_Length++] = doubleSwapPtr[4];
			buffer[m_Length++] = doubleSwapPtr[3];
			buffer[m_Length++] = doubleSwapPtr[2];
			buffer[m_Length++] = doubleSwapPtr[1];
			buffer[m_Length++] = *doubleSwapPtr;
		}

		public unsafe void Write(Color32 data)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			m_Color32Swap[0] = data;
			Buffer[m_Length++] = m_Color32SwapPtr[3];
			Buffer[m_Length++] = m_Color32SwapPtr[2];
			Buffer[m_Length++] = m_Color32SwapPtr[1];
			Buffer[m_Length++] = *m_Color32SwapPtr;
		}

		public unsafe void Write(MidiMessage data)
		{
			MidiMessage* ptr = (MidiMessage*)(m_BufferPtr + m_Length);
			*ptr = data;
			m_Length += 4;
		}

		public unsafe void Write(NtpTimestamp time)
		{
			time.ToBigEndianBytes((uint*)(m_BufferPtr + m_Length));
			m_Length += 8;
		}

		public unsafe void WriteCurrentTimestamp()
		{
			new NtpTimestamp(DateTime.Now).ToBigEndianBytes((uint*)(m_BufferPtr + m_Length));
			m_Length += 8;
		}

		public void Write(char data)
		{
			Buffer[m_Length + 3] = (byte)data;
			m_Length += 4;
		}

		public void WriteBundlePrefix()
		{
			System.Buffer.BlockCopy(Constant.BundlePrefixBytes, 0, Buffer, m_Length, 8);
			m_Length += 8;
		}

		public unsafe void WriteAddressAndTags(string address, uint tags)
		{
			m_Length = 0;
			foreach (char c in address)
			{
				Buffer[m_Length++] = (byte)c;
			}
			int num = (address.Length + 3) & -4;
			if (num == address.Length)
			{
				num += 4;
			}
			for (int j = address.Length; j < num; j++)
			{
				Buffer[m_Length++] = 0;
			}
			*(uint*)(m_BufferPtr + m_Length) = tags;
			m_Length += 4;
		}

		public void CopyBuffer(byte[] copyTo, int copyOffset = 0)
		{
			System.Buffer.BlockCopy(Buffer, 0, copyTo, copyOffset, Length);
		}

		public void Dispose()
		{
			m_BufferHandle.SafeFree();
			m_Color32SwapHandle.SafeFree();
			m_FloatSwapHandle.SafeFree();
			m_DoubleSwapHandle.SafeFree();
		}
	}
	[StructLayout(LayoutKind.Explicit)]
	public struct MidiMessage : IEquatable<MidiMessage>
	{
		[FieldOffset(0)]
		private readonly int data;

		[FieldOffset(0)]
		public readonly byte PortId;

		[FieldOffset(1)]
		public readonly byte Status;

		[FieldOffset(2)]
		public readonly byte Data1;

		[FieldOffset(3)]
		public readonly byte Data2;

		public MidiMessage(byte[] bytes, int offset)
		{
			data = 0;
			PortId = bytes[offset];
			Status = bytes[offset + 1];
			Data1 = bytes[offset + 2];
			Data2 = bytes[offset + 3];
		}

		public MidiMessage(byte portId, byte status, byte data1, byte data2)
		{
			data = 0;
			PortId = portId;
			Status = status;
			Data1 = data1;
			Data2 = data2;
		}

		public override string ToString()
		{
			return $"Port ID: {PortId}, Status: {Status}, Data 1: {Data1} , 2: {Data2}";
		}

		public bool Equals(MidiMessage other)
		{
			if (PortId == other.PortId && Status == other.Status && Data1 == other.Data1)
			{
				return Data2 == other.Data2;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is MidiMessage other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (((Status.GetHashCode() * 397) ^ Data1.GetHashCode()) * 397) ^ Data2.GetHashCode();
		}

		public static bool operator ==(MidiMessage left, MidiMessage right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(MidiMessage left, MidiMessage right)
		{
			return !left.Equals(right);
		}
	}
	internal static class ExtensionMethods
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Align4(this int self)
		{
			return (self + 3) & -4;
		}

		internal static void SafeFree(this GCHandle handle)
		{
			if (handle.IsAllocated)
			{
				handle.Free();
			}
		}

		internal static int ClampPort(this int port)
		{
			if (port < 1024)
			{
				port = 1024;
			}
			if (port >= 65535)
			{
				port = 65535;
			}
			return port;
		}
	}
	internal sealed class OscAddressMethods : IDisposable
	{
		private const int defaultSize = 16;

		public readonly Dictionary<BlobHandle, OscActionPair> HandleToValue;

		internal readonly Dictionary<string, BlobString> SourceToBlob;

		public OscAddressMethods(int initialCapacity = 16)
		{
			HandleToValue = new Dictionary<BlobHandle, OscActionPair>(initialCapacity);
			SourceToBlob = new Dictionary<string, BlobString>(initialCapacity);
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public void Add(string address, OscActionPair callbacks)
		{
			if (!SourceToBlob.TryGetValue(address, out var value))
			{
				value = new BlobString(address, (Allocator)4);
				HandleToValue[value.Handle] = callbacks;
				SourceToBlob.Add(address, value);
			}
			else if (HandleToValue.ContainsKey(value.Handle))
			{
				HandleToValue[value.Handle] += callbacks;
			}
			else
			{
				HandleToValue[value.Handle] = callbacks;
			}
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public void Add(string address, Action<OscMessageValues> callback)
		{
			Add(address, new OscActionPair(callback));
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		internal void Add(string address, List<OscActionPair> callbacks)
		{
			if (callbacks.Count == 0)
			{
				return;
			}
			OscActionPair callbacks2 = callbacks[0];
			if (callbacks.Count > 1)
			{
				for (int i = 1; i < callbacks.Count; i++)
				{
					callbacks2 += callbacks[i];
				}
			}
			Add(address, callbacks2);
		}

		[Il2CppSetOption(Option.NullChecks, false)]
		public bool Remove(string address, OscActionPair callbacks)
		{
			if (!SourceToBlob.TryGetValue(address, out var value))
			{
				return false;
			}
			if (!HandleToValue.TryGetValue(value.Handle, out OscActionPair value2))
			{
				return false;
			}
			if (value2.ValueRead.GetInvocationList().Length == 1)
			{
				bool result = HandleToValue.Remove(value.Handle) && SourceToBlob.Remove(address);
				value.Dispose();
				return result;
			}
			HandleToValue[value.Handle] -= callbacks;
			return true;
		}

		public bool RemoveAddress(string address)
		{
			if (!SourceToBlob.TryGetValue(address, out var value))
			{
				return false;
			}
			SourceToBlob.Remove(address);
			HandleToValue.Remove(value.Handle);
			value.Dispose();
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[Il2CppSetOption(Option.NullChecks, false)]
		public unsafe bool TryGetValueFromBytes(byte* ptr, int byteCount, out OscActionPair value)
		{
			return HandleToValue.TryGetValue(new BlobHandle(ptr, byteCount), out value);
		}

		public void Clear()
		{
			HandleToValue.Clear();
			SourceToBlob.Clear();
		}

		public void Dispose()
		{
			foreach (KeyValuePair<string, BlobString> item in SourceToBlob)
			{
				item.Value.Dispose();
			}
		}
	}
	internal static class Utils
	{
		private static readonly List<char> k_TempChars = new List<char>();

		private static readonly StringBuilder k_Builder = new StringBuilder();

		public static bool ValidateAddress(ref string address)
		{
			if (string.IsNullOrEmpty(address))
			{
				address = "/";
			}
			if (address[0] != '/')
			{
				address = address.Insert(0, "/");
			}
			if (address.EndsWith(" "))
			{
				address = address.TrimEnd(' ');
			}
			address = ReplaceInvalidAddressCharacters(address);
			return true;
		}

		internal static string ReplaceInvalidAddressCharacters(string address)
		{
			k_TempChars.Clear();
			k_TempChars.AddRange(address.Where(OscParser.CharacterIsValidInAddress));
			return new string(k_TempChars.ToArray());
		}

		public unsafe static TPtr* PinPtr<TData, TPtr>(TData[] array, out GCHandle handle) where TData : struct where TPtr : struct
		{
			handle = GCHandle.Alloc(array, GCHandleType.Pinned);
			return (TPtr*)(void*)handle.AddrOfPinnedObject();
		}

		internal static string GetLocalIpAddress()
		{
			string result = "unknown";
			IPAddress[] addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
			foreach (IPAddress iPAddress in addressList)
			{
				if (iPAddress.AddressFamily == AddressFamily.InterNetwork)
				{
					result = iPAddress.ToString();
					break;
				}
			}
			return result;
		}

		public static string MonitorMessageToString(BlobString address, OscMessageValues values)
		{
			OscMessageValues values2 = values;
			k_Builder.Clear();
			k_Builder.Append(address.ToString());
			k_Builder.Append("  ,");
			values2.ForEachElement(delegate(int i, TypeTag type)
			{
				k_Builder.Append((char)type);
			});
			k_Builder.Append("  ");
			int lastIndex = values2.ElementCount - 1;
			values2.ForEachElement(delegate(int i, TypeTag type)
			{
				string value = values2.ReadStringElement(i);
				k_Builder.Append(value);
				if (i != lastIndex)
				{
					k_Builder.Append(' ');
				}
			});
			return k_Builder.ToString();
		}
	}
}
namespace OscCore.Demo
{
	public class MonitorToDebugText : MonoBehaviour
	{
		private const int k_LineCount = 9;

		private const int k_LastIndex = 8;

		private static readonly StringBuilder k_StringBuilder = new StringBuilder();

		public OscReceiver Receiver;

		public TextMesh IpAddressText;

		public TextMesh RecentValueText;

		private int m_ReplaceLineIndex;

		private bool m_Dirty;

		private readonly string[] m_ReceivedAsString = new string[9];

		public void Awake()
		{
			IpAddressText.text = $"Local IP: {Utils.GetLocalIpAddress()} , Port {Receiver.Port}";
			Receiver.Server.AddMonitorCallback(Monitor);
		}

		private void Update()
		{
			if (m_Dirty)
			{
				RecentValueText.text = BuildMultiLine();
				m_Dirty = false;
			}
		}

		private void Monitor(BlobString address, OscMessageValues values)
		{
			m_Dirty = true;
			if (m_ReplaceLineIndex == 8)
			{
				for (int i = 0; i < 8; i++)
				{
					m_ReceivedAsString[i] = m_ReceivedAsString[i + 1];
				}
			}
			m_ReceivedAsString[m_ReplaceLineIndex] = Utils.MonitorMessageToString(address, values);
			if (m_ReplaceLineIndex < 8)
			{
				m_ReplaceLineIndex++;
			}
		}

		private string BuildMultiLine()
		{
			k_StringBuilder.Clear();
			for (int i = 0; i <= m_ReplaceLineIndex; i++)
			{
				k_StringBuilder.AppendLine(m_ReceivedAsString[i]);
				k_StringBuilder.AppendLine();
			}
			return k_StringBuilder.ToString();
		}
	}
}
namespace EyeTracking
{
	public class Core : MelonMod
	{
		public static bool HasFusion;

		internal static Core Instance { get; private set; }

		internal static MelonPreferences_Category Category { get; private set; }

		internal static MelonPreferences_Entry<bool> EnableEyeTracking { get; set; }

		internal static MelonPreferences_Entry<string> ActiveEyeGazeImplementation { get; private set; }

		public static Page RootPage { get; private set; }

		private static BoolElement EnableDebug { get; set; }

		public static Page ImplementationsPage { get; private set; }

		public override void OnInitializeMelon()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Category = MelonPreferences.CreateCategory("EyeTracking", "Eye Tracking Settings");
			EnableEyeTracking = Category.CreateEntry<bool>("EnableEyeTracking", true, "Enable Eye Tracking", (string)null, false, false, (ValueValidator)null, (string)null);
			ActiveEyeGazeImplementation = Category.CreateEntry<string>("ActiveEyeGazeImplementation", "OSC", "Active Eye Gaze Implementation", (string)null, false, false, (ValueValidator)null, (string)null);
			Category.SaveToFile(false);
			HasFusion = MelonBase.FindMelon("LabFusion", "Lakatrazz") != null;
			if (HasFusion)
			{
				Utils.LoadAssemblyFromAssembly(((MelonBase)Instance).MelonAssembly.Assembly, "EyeTracking.Resources.EyeTrackingFusion.dll").GetType("EyeTracking.Fusion.ModuleLoader").GetMethod("LoadModule")
					.Invoke(null, null);
			}
			RootPage = Page.Root.CreatePage("Eye Tracking", Color.green, 0, true);
			RootPage.CreateFunction("Current Implementation: " + ActiveEyeGazeImplementation.Value, Color.green, (Action)delegate
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				Notifier.Send(new Notification
				{
					ShowTitleOnPopup = true,
					Title = NotificationText.op_Implicit("hi"),
					Message = NotificationText.op_Implicit("oh, hello there"),
					Type = (NotificationType)0
				});
			});
			ImplementationsPage = RootPage.CreatePage("Available Implementations", Color.cyan, 0, true);
			ImplementationManager.Initialize();
			Hooking.OnSwitchAvatarPostfix += EyeSolver.OnAvatarSwap;
		}

		public override void OnUpdate()
		{
			if (EnableEyeTracking.Value && ImplementationManager.CurrentImplementation != null)
			{
				ImplementationManager.CurrentImplementation.Update();
				EyeSolver.UpdateBlink();
			}
		}

		public override void OnGUI()
		{
			if (EnableDebug != null && EnableDebug.Value && ImplementationManager.CurrentImplementation != null)
			{
				EyeGazeDebugOverlay.Draw();
			}
		}
	}
	public static class EyeSolver
	{
		public static readonly float SmoothingSpeed = 35f;

		private static float _currentLeftBlink = 0f;

		private static float _currentRightBlink = 0f;

		internal static AvatarEyeGazeDescriptor CurrentEyeGazeDescriptor { get; private set; }

		internal static int LeftBlinkIndex { get; private set; } = -1;


		internal static int RightBlinkIndex { get; private set; } = -1;


		public static void OnAvatarSwap(Avatar avatar)
		{
			if (!((Object)(object)avatar == (Object)null) && !((Object)(object)((Component)((Component)avatar).transform.parent).GetComponent<RigManager>() != (Object)(object)Player.RigManager))
			{
				CurrentEyeGazeDescriptor = null;
				LeftBlinkIndex = -1;
				RightBlinkIndex = -1;
				CurrentEyeGazeDescriptor = ((Component)avatar).GetComponent<AvatarEyeGazeDescriptor>();
				if (!((Object)(object)CurrentEyeGazeDescriptor == (Object)null))
				{
					LeftBlinkIndex = CurrentEyeGazeDescriptor.LeftEyeBlinkShapeKey.Get();
					RightBlinkIndex = CurrentEyeGazeDescriptor.RightEyeBlinkShapeKey.Get();
				}
			}
		}

		public static void UpdateBlink()
		{
			if (!Core.EnableEyeTracking.Value || !ImplementationManager.CurrentImplementation.IsLoaded || (Object)(object)CurrentEyeGazeDescriptor == (Object)null || (Object)(object)CurrentEyeGazeDescriptor.SkinnedMeshRenderer.Get() == (Object)null || LeftBlinkIndex == -1 || RightBlinkIndex == -1)
			{
				return;
			}
			float num = 1f - Tracking.Data.Eye.Left.Openness;
			float num2 = 1f - Tracking.Data.Eye.Right.Openness;
			_currentLeftBlink = Mathf.Lerp(_currentLeftBlink, num, SmoothingSpeed * Time.deltaTime);
			_currentRightBlink = Mathf.Lerp(_currentRightBlink, num2, SmoothingSpeed * Time.deltaTime);
			AvatarEyeGazeDescriptor currentEyeGazeDescriptor = CurrentEyeGazeDescriptor;
			if (currentEyeGazeDescriptor != null)
			{
				Il2CppReferenceField<SkinnedMeshRenderer> skinnedMeshRenderer = currentEyeGazeDescriptor.SkinnedMeshRenderer;
				if (skinnedMeshRenderer != null)
				{
					SkinnedMeshRenderer obj = skinnedMeshRenderer.Get();
					if (obj != null)
					{
						obj.SetBlendShapeWeight(LeftBlinkIndex, _currentLeftBlink * 100f);
					}
				}
			}
			AvatarEyeGazeDescriptor currentEyeGazeDescriptor2 = CurrentEyeGazeDescriptor;
			if (currentEyeGazeDescriptor2 == null)
			{
				return;
			}
			Il2CppReferenceField<SkinnedMeshRenderer> skinnedMeshRenderer2 = currentEyeGazeDescriptor2.SkinnedMeshRenderer;
			if (skinnedMeshRenderer2 != null)
			{
				SkinnedMeshRenderer obj2 = skinnedMeshRenderer2.Get();
				if (obj2 != null)
				{
					obj2.SetBlendShapeWeight(RightBlinkIndex, _currentRightBlink * 100f);
				}
			}
		}
	}
	public static class Tracking
	{
		public static readonly TrackingData Data = new TrackingData();
	}
	public static class ImplementationManager
	{
		private static readonly List<EyeGazeImplementation> Implementations = new List<EyeGazeImplementation>();

		public static EyeGazeImplementation? CurrentImplementation { get; private set; }

		internal static void Initialize()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			LoadImplementations();
			if (CurrentImplementation == null)
			{
				Core.ActiveEyeGazeImplementation.Value = Core.ActiveEyeGazeImplementation.DefaultValue;
				Core.Category.SaveToFile(false);
				LoadImplementations();
			}
			foreach (EyeGazeImplementation implementation in Implementations)
			{
				Core.ImplementationsPage.CreateFunction(implementation.Name, Color.white, (Action)delegate
				{
					//IL_0020: Unknown result type (might be due to invalid IL or missing references)
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0032: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Unknown result type (might be due to invalid IL or missing references)
					//IL_003c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0042: Unknown result type (might be due to invalid IL or missing references)
					//IL_0047: Unknown result type (might be due to invalid IL or missing references)
					//IL_004c: Unknown result type (might be due to invalid IL or missing references)
					//IL_004e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0058: Expected O, but got Unknown
					Core.ActiveEyeGazeImplementation.Value = implementation.Name;
					Core.Category.SaveToFile(false);
					Notifier.Send(new Notification
					{
						ShowTitleOnPopup = true,
						Title = NotificationText.op_Implicit("Eye Tracking Implementation Changed"),
						Message = NotificationText.op_Implicit("Please restart the game for this change to take affect."),
						Type = (NotificationType)3
					});
				});
			}
		}

		private static void LoadImplementations()
		{
			Implementations.Clear();
			CurrentImplementation = null;
			foreach (MelonBase registeredMelo