Decompiled source of InterprocessLib v3.0.0

Renderer/BepInEx/plugins/InterprocessLib.BepInEx/InterprocessLib.Unity.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;
using Renderite.Shared;
using Renderite.Unity;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Nytra")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: AssemblyInformationalVersion("3.0.0+cec136eadee793dc3aceee57dbadeb04e56bd3e1")]
[assembly: AssemblyProduct("InterprocessLib.Unity")]
[assembly: AssemblyTitle("InterprocessLib.Unity")]
[assembly: AssemblyVersion("3.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[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 InterprocessLib
{
	internal class Defaults
	{
		private static string? _defaultQueuePrefix;

		public static bool DefaultIsAuthority => false;

		public static IMemoryPackerEntityPool DefaultPool => (IMemoryPackerEntityPool)(object)PackerMemoryPool.Instance;

		public static string DefaultQueuePrefix
		{
			get
			{
				if (_defaultQueuePrefix != null)
				{
					return _defaultQueuePrefix;
				}
				string[] commandLineArgs = Environment.GetCommandLineArgs();
				string text = null;
				for (int i = 0; i < commandLineArgs.Length; i++)
				{
					if (commandLineArgs[i].Equals("-QueueName", StringComparison.InvariantCultureIgnoreCase))
					{
						text = commandLineArgs[i + 1];
						break;
					}
				}
				if (text == null)
				{
					throw new InvalidDataException("QueueName argument is null!");
				}
				_defaultQueuePrefix = text.Substring(0, text.IndexOf('_'));
				return _defaultQueuePrefix;
			}
		}

		public static void Init()
		{
		}

		static Defaults()
		{
			Messenger.OnWarning += delegate(string msg)
			{
				Debug.LogWarning((object)("[InterprocessLib] [WARN] " + msg));
			};
			Messenger.OnFailure += delegate(Exception ex)
			{
				Debug.LogError((object)$"[InterprocessLib] [ERROR] {ex}");
			};
			Application.quitting += Messenger.Shutdown;
		}
	}
	internal abstract class CollectionCommand : IMemoryPackable
	{
		public abstract IEnumerable? UntypedCollection { get; }

		public abstract int? Length { get; }

		public abstract Type StoredType { get; }

		public abstract Type CollectionType { get; }

		public abstract void Pack(ref MemoryPacker packer);

		public abstract void Unpack(ref MemoryUnpacker unpacker);

		public override string ToString()
		{
			return "CollectionCommand:" + CollectionType.Name + "<" + StoredType.Name + ">:Length=" + (Length?.ToString() ?? "NULL");
		}
	}
	internal abstract class ValueCommand : IMemoryPackable
	{
		public abstract object UntypedValue { get; }

		public abstract Type ValueType { get; }

		public abstract void Pack(ref MemoryPacker packer);

		public abstract void Unpack(ref MemoryUnpacker unpacker);

		public override string ToString()
		{
			return $"ValueCommand<{ValueType.Name}>:{UntypedValue}";
		}
	}
	internal abstract class ObjectCommand : IMemoryPackable
	{
		public abstract object? UntypedObject { get; }

		public abstract Type ObjectType { get; }

		public abstract void Pack(ref MemoryPacker packer);

		public abstract void Unpack(ref MemoryUnpacker unpacker);

		public override string ToString()
		{
			return "ObjectCommand<" + ObjectType.Name + ">:" + (UntypedObject?.ToString() ?? "NULL");
		}
	}
	internal sealed class EmptyCommand : IMemoryPackable
	{
		public void Pack(ref MemoryPacker packer)
		{
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
		}

		public override string ToString()
		{
			return "EmptyCommand";
		}
	}
	internal sealed class ValueCollectionCommand<C, T> : CollectionCommand where C : ICollection<T>?, new() where T : unmanaged
	{
		public C? Values;

		public override int? Length => Values?.Count;

		public override IEnumerable? UntypedCollection => Values;

		public override Type StoredType => typeof(T);

		public override Type CollectionType => typeof(C);

		public override void Pack(ref MemoryPacker packer)
		{
			int num = Values?.Count ?? (-1);
			((MemoryPacker)(ref packer)).Write<int>(num);
			if (Values == null)
			{
				return;
			}
			foreach (T value in Values)
			{
				((MemoryPacker)(ref packer)).Write<T>(value);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Values = default(C);
				return;
			}
			Values = new C();
			for (int i = 0; i < num; i++)
			{
				T item = default(T);
				((MemoryUnpacker)(ref unpacker)).Read<T>(ref item);
				Values.Add(item);
			}
		}
	}
	internal sealed class ValueArrayCommand<T> : CollectionCommand, IMemoryPackable where T : unmanaged
	{
		public T[]? Values;

		public override int? Length => Values?.Length;

		public override IEnumerable? UntypedCollection => Values;

		public override Type StoredType => typeof(T);

		public override Type CollectionType => typeof(T[]);

		public override void Pack(ref MemoryPacker packer)
		{
			T[]? values = Values;
			int num = ((values != null) ? values.Length : (-1));
			((MemoryPacker)(ref packer)).Write<int>(num);
			if (Values != null)
			{
				Span<T> destination = ((MemoryPacker)(ref packer)).Access<T>(num);
				Values.CopyTo(destination);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Values = null;
				return;
			}
			Values = new T[num];
			((MemoryUnpacker)(ref unpacker)).Access<T>(num).CopyTo(Values);
		}
	}
	internal sealed class TypeRegistrationCommand : TypeCommand
	{
		public override string ToString()
		{
			string[] obj = new string[5]
			{
				"TypeRegistrationCommand:",
				Type?.Name ?? "NULL",
				"<",
				null,
				null
			};
			IEnumerable<Type> enumerable = Type?.GenericTypeArguments;
			obj[3] = string.Join(",", enumerable ?? Array.Empty<Type>());
			obj[4] = ">";
			return string.Concat(obj);
		}
	}
	internal class TypeCommand : IMemoryPackable
	{
		public Type? Type;

		private static Dictionary<string, Type> _typeCache = new Dictionary<string, Type>();

		public void Pack(ref MemoryPacker packer)
		{
			PackType(Type, ref packer);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			Type = UnpackType(ref unpacker);
		}

		private void PackType(Type? type, ref MemoryPacker packer)
		{
			if ((object)type == null)
			{
				((MemoryPacker)(ref packer)).Write<bool>(false);
				return;
			}
			((MemoryPacker)(ref packer)).Write<bool>(true);
			if (type.IsGenericType)
			{
				((MemoryPacker)(ref packer)).Write<bool>(true);
				Type genericTypeDefinition = type.GetGenericTypeDefinition();
				((MemoryPacker)(ref packer)).Write(genericTypeDefinition.FullName);
				Type[] genericArguments = type.GetGenericArguments();
				((MemoryPacker)(ref packer)).Write<int>(genericArguments.Length);
				Type[] array = genericArguments;
				foreach (Type type2 in array)
				{
					PackType(type2, ref packer);
				}
			}
			else
			{
				((MemoryPacker)(ref packer)).Write<bool>(false);
				((MemoryPacker)(ref packer)).Write(type.FullName);
			}
		}

		private Type? UnpackType(ref MemoryUnpacker unpacker)
		{
			if (!((MemoryUnpacker)(ref unpacker)).Read<bool>())
			{
				return null;
			}
			if (((MemoryUnpacker)(ref unpacker)).Read<bool>())
			{
				string typeString = ((MemoryUnpacker)(ref unpacker)).ReadString();
				int num = ((MemoryUnpacker)(ref unpacker)).Read<int>();
				Type[] array = new Type[num];
				for (int i = 0; i < num; i++)
				{
					array[i] = UnpackType(ref unpacker);
				}
				if (array.Any((Type t) => (object)t == null))
				{
					return null;
				}
				Type type = FindType(typeString);
				if (type != null)
				{
					return type.MakeGenericType(array);
				}
				return null;
			}
			string typeString2 = ((MemoryUnpacker)(ref unpacker)).ReadString();
			return FindType(typeString2);
		}

		private Type? FindType(string typeString)
		{
			if (_typeCache.TryGetValue(typeString, out Type value))
			{
				return value;
			}
			value = System.Type.GetType(typeString);
			if ((object)value == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					value = assemblies[i].GetType(typeString);
					if (value != null)
					{
						break;
					}
				}
			}
			if (value != null)
			{
				_typeCache[typeString] = value;
			}
			return value;
		}

		public override string ToString()
		{
			string[] obj = new string[5]
			{
				"TypeCommand:",
				Type?.Name ?? "NULL",
				"<",
				null,
				null
			};
			IEnumerable<Type> enumerable = Type?.GenericTypeArguments;
			obj[3] = string.Join(",", enumerable ?? Array.Empty<Type>());
			obj[4] = ">";
			return string.Concat(obj);
		}
	}
	internal sealed class StringArrayCommand : CollectionCommand
	{
		public string?[]? Strings;

		public override int? Length => Strings?.Length;

		public override IEnumerable? UntypedCollection => Strings;

		public override Type StoredType => typeof(string);

		public override Type CollectionType => typeof(string[]);

		public override void Pack(ref MemoryPacker packer)
		{
			if (Strings == null)
			{
				((MemoryPacker)(ref packer)).Write<int>(-1);
				return;
			}
			int num = Strings.Length;
			((MemoryPacker)(ref packer)).Write<int>(num);
			string[] strings = Strings;
			foreach (string text in strings)
			{
				((MemoryPacker)(ref packer)).Write(text);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Strings = null;
				return;
			}
			Strings = new string[num];
			for (int i = 0; i < num; i++)
			{
				((MemoryUnpacker)(ref unpacker)).Read(ref Strings[i]);
			}
		}
	}
	internal sealed class StringCollectionCommand<C> : CollectionCommand where C : ICollection<string>?, new()
	{
		public IReadOnlyCollection<string?>? Strings;

		public override int? Length => Strings?.Count;

		public override IEnumerable? UntypedCollection => Strings;

		public override Type StoredType => typeof(string);

		public override Type CollectionType => typeof(C);

		public override void Pack(ref MemoryPacker packer)
		{
			if (Strings == null)
			{
				((MemoryPacker)(ref packer)).Write<int>(-1);
				return;
			}
			int count = Strings.Count;
			((MemoryPacker)(ref packer)).Write<int>(count);
			foreach (string @string in Strings)
			{
				((MemoryPacker)(ref packer)).Write(@string);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Strings = null;
				return;
			}
			C val = new C();
			for (int i = 0; i < num; i++)
			{
				string item = null;
				((MemoryUnpacker)(ref unpacker)).Read(ref item);
				val.Add(item);
			}
			Strings = (IReadOnlyCollection<string>)(object)val;
		}
	}
	internal sealed class ObjectCollectionCommand<C, T> : CollectionCommand where C : ICollection<T>?, new() where T : class?, IMemoryPackable, new()
	{
		public C? Objects;

		public override int? Length => Objects?.Count;

		public override IEnumerable? UntypedCollection => Objects;

		public override Type StoredType => typeof(T);

		public override Type CollectionType => typeof(C);

		public override void Pack(ref MemoryPacker packer)
		{
			if (Objects == null)
			{
				((MemoryPacker)(ref packer)).Write<int>(-1);
				return;
			}
			int count = Objects.Count;
			((MemoryPacker)(ref packer)).Write<int>(count);
			foreach (T @object in Objects)
			{
				((MemoryPacker)(ref packer)).WriteObject<T>(@object);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Objects = default(C);
				return;
			}
			Objects = new C();
			for (int i = 0; i < num; i++)
			{
				T item = new T();
				((MemoryUnpacker)(ref unpacker)).ReadObject<T>(ref item);
				Objects.Add(item);
			}
		}
	}
	internal sealed class ObjectArrayCommand<T> : CollectionCommand where T : class?, IMemoryPackable, new()
	{
		public T[]? Objects;

		public override int? Length => Objects?.Length;

		public override IEnumerable? UntypedCollection => Objects;

		public override Type StoredType => typeof(T);

		public override Type CollectionType => typeof(T[]);

		public override void Pack(ref MemoryPacker packer)
		{
			if (Objects == null)
			{
				((MemoryPacker)(ref packer)).Write<int>(-1);
				return;
			}
			int num = Objects.Length;
			((MemoryPacker)(ref packer)).Write<int>(num);
			T[] objects = Objects;
			foreach (T val in objects)
			{
				((MemoryPacker)(ref packer)).WriteObject<T>(val);
			}
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			int num = 0;
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref num);
			if (num == -1)
			{
				Objects = null;
				return;
			}
			Objects = new T[num];
			for (int i = 0; i < num; i++)
			{
				((MemoryUnpacker)(ref unpacker)).ReadObject<T>(ref Objects[i]);
			}
		}
	}
	internal sealed class ObjectCommand<T> : ObjectCommand where T : class?, IMemoryPackable, new()
	{
		public T? Object;

		public override object? UntypedObject => Object;

		public override Type ObjectType => typeof(T);

		public override void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).WriteObject<T>(Object);
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).ReadObject<T>(ref Object);
		}
	}
	internal sealed class ValueCommand<T> : ValueCommand where T : unmanaged
	{
		public T Value;

		public override object UntypedValue => Value;

		public override Type ValueType => typeof(T);

		public override void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<T>(Value);
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<T>(ref Value);
		}
	}
	internal sealed class StringCommand : IMemoryPackable
	{
		public string? String;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write(String);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read(ref String);
		}

		public override string ToString()
		{
			return "StringCommand:" + (String ?? "NULL");
		}
	}
	internal sealed class QueueOwnerInitCommand : IMemoryPackable
	{
		public void Pack(ref MemoryPacker packer)
		{
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
		}
	}
	internal sealed class WrapperCommand : RendererCommand
	{
		public int TypeIndex;

		public IMemoryPackable? Packable;

		public string? Owner;

		public string? Id;

		private static List<Type> CurrentRendererCommandTypes => ((List<Type>)typeof(PolymorphicMemoryPackableEntity<RendererCommand>).GetField("types", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null)) ?? throw new MissingFieldException("types");

		static WrapperCommand()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			new RendererInitData();
			List<Type> list = new List<Type>();
			list.AddRange(CurrentRendererCommandTypes);
			list.Add(typeof(WrapperCommand));
			PolymorphicMemoryPackableEntity<RendererCommand>.InitTypes(list);
		}

		public override void Pack(ref MemoryPacker packer)
		{
			if (Packable == null)
			{
				throw new ArgumentNullException("Packable");
			}
			if (Id == null)
			{
				throw new ArgumentNullException("Id");
			}
			if (Owner == null)
			{
				throw new ArgumentNullException("Owner");
			}
			((MemoryPacker)(ref packer)).Write(Owner);
			((MemoryPacker)(ref packer)).Write(Id);
			((MemoryPacker)(ref packer)).Write<int>(TypeIndex);
			Packable.Pack(ref packer);
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			MessagingQueue obj = (MessagingQueue)(object)((MemoryUnpacker)(ref unpacker)).Pool;
			((MemoryUnpacker)(ref unpacker)).Read(ref Owner);
			if (!obj.HasOwner(Owner))
			{
				throw new InvalidDataException("Cannot unpack for unregistered owner: " + Owner);
			}
			MessagingQueue.OwnerData ownerData = obj.GetOwnerData(Owner);
			((MemoryUnpacker)(ref unpacker)).Read(ref Id);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref TypeIndex);
			Packable = ownerData.IncomingTypeManager.Borrow(TypeIndex);
			Packable.Unpack(ref unpacker);
		}
	}
	public class Messenger : IDisposable
	{
		private MessagingQueue _currentQueue;

		private string _ownerId;

		private IMemoryPackerEntityPool _pool;

		public static event Action<Exception>? OnFailure;

		public static event Action<string>? OnWarning;

		public static event Action<string>? OnDebug;

		internal static event Action? OnShutdown;

		static Messenger()
		{
			Defaults.Init();
		}

		[Obsolete("Use the other constructors that don't take Type lists", false)]
		public Messenger(string ownerId, List<Type>? additionalObjectTypes = null, List<Type>? additionalValueTypes = null)
			: this(ownerId)
		{
		}

		public Messenger(string ownerId)
			: this(ownerId, Defaults.DefaultIsAuthority, Defaults.DefaultQueuePrefix + "-" + ownerId, null, 1048576L)
		{
		}

		public Messenger(string ownerId, bool isAuthority, string queueName, IMemoryPackerEntityPool? pool = null, long queueCapacity = 1048576L)
		{
			if (ownerId == null)
			{
				throw new ArgumentNullException("ownerId");
			}
			if (queueName == null)
			{
				throw new ArgumentNullException("queueName");
			}
			_ownerId = ownerId;
			_pool = pool ?? Defaults.DefaultPool;
			MessagingQueue messagingQueue = MessagingQueue.TryGetRegisteredQueue(queueName);
			if (messagingQueue == null)
			{
				_currentQueue = new MessagingQueue(isAuthority, queueName, queueCapacity, _pool, Messenger.OnFailure, Messenger.OnWarning, Messenger.OnDebug);
				OnShutdown += _currentQueue.Dispose;
			}
			else
			{
				_currentQueue = messagingQueue;
			}
			Init();
		}

		internal static void Shutdown()
		{
			Messenger.OnShutdown?.Invoke();
		}

		private void Init()
		{
			_currentQueue.RegisterOwner(_ownerId);
			if (!_currentQueue.IsConnected)
			{
				_currentQueue.Connect();
			}
			_currentQueue.SendPackable(_ownerId, "", new QueueOwnerInitCommand());
		}

		internal static void WarnHandler(string str)
		{
			Messenger.OnWarning?.Invoke(str);
		}

		internal static void FailHandler(Exception ex)
		{
			Messenger.OnFailure?.Invoke(ex);
		}

		internal static void DebugHandler(string str)
		{
			Messenger.OnDebug?.Invoke(str);
		}

		public void SendValue<T>(string id, T value) where T : unmanaged
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ValueCommand<T> valueCommand = _pool.Borrow<ValueCommand<T>>();
			valueCommand.Value = value;
			_currentQueue.SendPackable(_ownerId, id, valueCommand);
			_pool.Return<ValueCommand<T>>(valueCommand);
		}

		[Obsolete("Use SendValueCollection instead.")]
		public void SendValueList<T>(string id, List<T>? list) where T : unmanaged
		{
			SendValueCollection<List<T>, T>(id, list);
		}

		[Obsolete("Use SendValueCollection instead.")]
		public void SendValueHashSet<T>(string id, HashSet<T>? hashSet) where T : unmanaged
		{
			SendValueCollection<HashSet<T>, T>(id, hashSet);
		}

		public void SendValueCollection<C, T>(string id, C? collection) where C : ICollection<T>?, new() where T : unmanaged
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ValueCollectionCommand<C, T> valueCollectionCommand = _pool.Borrow<ValueCollectionCommand<C, T>>();
			valueCollectionCommand.Values = collection;
			_currentQueue.SendPackable(_ownerId, id, valueCollectionCommand);
			_pool.Return<ValueCollectionCommand<C, T>>(valueCollectionCommand);
		}

		public void SendValueArray<T>(string id, T[]? array) where T : unmanaged
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ValueArrayCommand<T> valueArrayCommand = _pool.Borrow<ValueArrayCommand<T>>();
			valueArrayCommand.Values = array;
			_currentQueue.SendPackable(_ownerId, id, valueArrayCommand);
			_pool.Return<ValueArrayCommand<T>>(valueArrayCommand);
		}

		public void SendString(string id, string? str)
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			StringCommand stringCommand = _pool.Borrow<StringCommand>();
			stringCommand.String = str;
			_currentQueue.SendPackable(_ownerId, id, stringCommand);
			_pool.Return<StringCommand>(stringCommand);
		}

		[Obsolete("Use SendStringCollection instead.")]
		public void SendStringList(string id, List<string>? list)
		{
			SendStringCollection<List<string>>(id, list);
		}

		public void SendStringCollection<C>(string id, IReadOnlyCollection<string?>? collection) where C : ICollection<string>?, new()
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			StringCollectionCommand<C> stringCollectionCommand = _pool.Borrow<StringCollectionCommand<C>>();
			stringCollectionCommand.Strings = collection;
			_currentQueue.SendPackable(_ownerId, id, stringCollectionCommand);
			_pool.Return<StringCollectionCommand<C>>(stringCollectionCommand);
		}

		public void SendStringArray(string id, string?[]? array)
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			StringArrayCommand stringArrayCommand = _pool.Borrow<StringArrayCommand>();
			stringArrayCommand.Strings = array;
			_currentQueue.SendPackable(_ownerId, id, stringArrayCommand);
			_pool.Return<StringArrayCommand>(stringArrayCommand);
		}

		public void SendEmptyCommand(string id)
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			EmptyCommand emptyCommand = _pool.Borrow<EmptyCommand>();
			_currentQueue.SendPackable(_ownerId, id, emptyCommand);
			_pool.Return<EmptyCommand>(emptyCommand);
		}

		public void SendObject<T>(string id, T? obj) where T : class?, IMemoryPackable, new()
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ObjectCommand<T> objectCommand = _pool.Borrow<ObjectCommand<T>>();
			objectCommand.Object = obj;
			_currentQueue.SendPackable(_ownerId, id, objectCommand);
			_pool.Return<ObjectCommand<T>>(objectCommand);
		}

		[Obsolete("Use SendObjectCollection instead.")]
		public void SendObjectList<T>(string id, List<T>? list) where T : class?, IMemoryPackable, new()
		{
			SendObjectCollection<List<T>, T>(id, list);
		}

		public void SendObjectCollection<C, T>(string id, C? collection) where C : ICollection<T>?, new() where T : class?, IMemoryPackable, new()
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ObjectCollectionCommand<C, T> objectCollectionCommand = _pool.Borrow<ObjectCollectionCommand<C, T>>();
			objectCollectionCommand.Objects = collection;
			_currentQueue.SendPackable(_ownerId, id, objectCollectionCommand);
			_pool.Return<ObjectCollectionCommand<C, T>>(objectCollectionCommand);
		}

		public void SendObjectArray<T>(string id, T[]? array) where T : class?, IMemoryPackable, new()
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			ObjectArrayCommand<T> objectArrayCommand = _pool.Borrow<ObjectArrayCommand<T>>();
			objectArrayCommand.Objects = array;
			_currentQueue.SendPackable(_ownerId, id, objectArrayCommand);
			_pool.Return<ObjectArrayCommand<T>>(objectArrayCommand);
		}

		public void SendType(string id, Type type)
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			TypeCommand typeCommand = _pool.Borrow<TypeCommand>();
			typeCommand.Type = type;
			_currentQueue.SendPackable(_ownerId, id, typeCommand);
			_pool.Return<TypeCommand>(typeCommand);
		}

		public void ReceiveValue<T>(string id, Action<T>? callback) where T : unmanaged
		{
			Action<T> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ValueCommand<T> cmd)
			{
				callback2?.Invoke(cmd.Value);
			});
		}

		[Obsolete("Use ReceiveValueCollection instead.")]
		public void ReceiveValueList<T>(string id, Action<List<T>>? callback) where T : unmanaged
		{
			ReceiveValueCollection<List<T>, T>(id, callback);
		}

		[Obsolete("Use ReceiveValueCollection instead.")]
		public void ReceiveValueHashSet<T>(string id, Action<HashSet<T>>? callback) where T : unmanaged
		{
			ReceiveValueCollection<HashSet<T>, T>(id, callback);
		}

		public void ReceiveValueCollection<C, T>(string id, Action<C>? callback) where C : ICollection<T>?, new() where T : unmanaged
		{
			Action<C> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ValueCollectionCommand<C, T> cmd)
			{
				callback2?.Invoke(cmd.Values);
			});
		}

		public void ReceiveValueArray<T>(string id, Action<T[]?>? callback) where T : unmanaged
		{
			Action<T[]?> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ValueArrayCommand<T> cmd)
			{
				callback2?.Invoke(cmd.Values);
			});
		}

		public void ReceiveString(string id, Action<string?>? callback)
		{
			Action<string?> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(StringCommand cmd)
			{
				callback2?.Invoke(cmd.String);
			});
		}

		[Obsolete("Use ReceiveStringCollection instead.")]
		public void ReceiveStringList(string id, Action<List<string>?>? callback)
		{
			ReceiveStringCollection(id, callback);
		}

		public void ReceiveStringCollection<C>(string id, Action<C>? callback) where C : ICollection<string>?, new()
		{
			Action<C> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(StringCollectionCommand<C> cmd)
			{
				callback2?.Invoke((C)cmd.Strings);
			});
		}

		public void ReceiveStringArray(string id, Action<string?[]?>? callback)
		{
			Action<string?[]?> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(StringArrayCommand cmd)
			{
				callback2?.Invoke(cmd.Strings);
			});
		}

		public void ReceiveEmptyCommand(string id, Action? callback)
		{
			Action callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback<EmptyCommand>(_ownerId, id, delegate
			{
				callback2?.Invoke();
			});
		}

		public void ReceiveObject<T>(string id, Action<T>? callback) where T : class?, IMemoryPackable, new()
		{
			Action<T> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectCommand<T> cmd)
			{
				callback2?.Invoke(cmd.Object);
			});
		}

		[Obsolete("Use ReceiveObjectCollection instead.")]
		public void ReceiveObjectList<T>(string id, Action<List<T>>? callback) where T : class?, IMemoryPackable, new()
		{
			ReceiveObjectCollection<List<T>, T>(id, callback);
		}

		public void ReceiveObjectCollection<C, T>(string id, Action<C>? callback) where C : ICollection<T>?, new() where T : class?, IMemoryPackable, new()
		{
			Action<C> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectCollectionCommand<C, T> cmd)
			{
				callback2?.Invoke(cmd.Objects);
			});
		}

		public void ReceiveObjectArray<T>(string id, Action<T[]>? callback) where T : class?, IMemoryPackable, new()
		{
			Action<T[]> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectArrayCommand<T> cmd)
			{
				callback2?.Invoke(cmd.Objects);
			});
		}

		public void ReceiveType(string id, Action<Type?> callback)
		{
			Action<Type?> callback2 = callback;
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_currentQueue.RegisterCallback(_ownerId, id, delegate(TypeCommand cmd)
			{
				callback2?.Invoke(cmd.Type);
			});
		}

		public void Dispose()
		{
			_currentQueue.UnregisterOwner(_ownerId);
		}
	}
	internal class MessagingQueue : IDisposable, IMemoryPackerEntityPool
	{
		internal class OwnerData
		{
			public readonly Dictionary<Type, Dictionary<string, object?>> TypedCallbacks = new Dictionary<Type, Dictionary<string, object>>();

			public TypeManager OutgoingTypeManager;

			public TypeManager IncomingTypeManager;

			public readonly string Id;

			public bool Initialized;

			public MessagingQueue Queue { get; private set; }

			public OwnerData(string id, MessagingQueue queue)
			{
				Id = id;
				Queue = queue;
				OutgoingTypeManager = new TypeManager(Queue._pool, OnOutgoingTypeRegistered);
				IncomingTypeManager = new TypeManager(Queue._pool, null);
			}

			public void OnOutgoingTypeRegistered(Type type)
			{
				TypeRegistrationCommand typeRegistrationCommand = new TypeRegistrationCommand();
				typeRegistrationCommand.Type = type;
				Queue.SendPackable(Id, "", typeRegistrationCommand);
			}
		}

		private MessagingManager _primary;

		private static readonly MethodInfo _handlePackableMethod = typeof(MessagingQueue).GetMethod("HandlePackable", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingMethodException("HandlePackable");

		private Action<string>? _onWarning;

		private Action<string>? _onDebug;

		private Action<Exception>? _onFailure;

		private readonly Dictionary<string, OwnerData> _ownerData = new Dictionary<string, OwnerData>();

		private static readonly Dictionary<string, MessagingQueue> _registeredQueues = new Dictionary<string, MessagingQueue>();

		private IMemoryPackerEntityPool _pool;

		public bool IsAuthority { get; }

		public string QueueName { get; }

		public long QueueCapacity { get; }

		public int ReceivedMessages => _primary.ReceivedMessages;

		public int SentMessages => _primary.SentMessages;

		public bool IsConnected { get; private set; }

		public bool IsDisposed { get; private set; }

		public void RegisterOwner(string ownerId)
		{
			_ownerData.Add(ownerId, new OwnerData(ownerId, this));
		}

		public bool HasOwner(string ownerName)
		{
			return _ownerData.ContainsKey(ownerName);
		}

		public OwnerData GetOwnerData(string ownerId)
		{
			return _ownerData[ownerId];
		}

		public void RegisterCallback<T>(string owner, string id, Action<T>? callback) where T : IMemoryPackable
		{
			if (!_ownerData[owner].TypedCallbacks.ContainsKey(typeof(T)))
			{
				_ownerData[owner].TypedCallbacks.Add(typeof(T), new Dictionary<string, object>());
			}
			_ownerData[owner].TypedCallbacks[typeof(T)][id] = callback;
		}

		public MessagingQueue(bool isAuthority, string queueName, long queueCapacity, IMemoryPackerEntityPool pool, Action<Exception>? failhandler = null, Action<string>? warnHandler = null, Action<string>? debugHandler = null)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			if (queueName == null)
			{
				throw new ArgumentNullException("queueName");
			}
			if (pool == null)
			{
				throw new ArgumentNullException("pool");
			}
			IsAuthority = isAuthority;
			QueueName = queueName;
			QueueCapacity = queueCapacity;
			_onDebug = debugHandler;
			_onWarning = warnHandler;
			_onFailure = failhandler;
			_pool = pool;
			_primary = new MessagingManager((IMemoryPackerEntityPool)(object)this);
			_primary.CommandHandler = new RenderCommandHandler(CommandHandler);
			_primary.FailureHandler = delegate(Exception ex)
			{
				_onFailure?.Invoke(ex);
			};
			_primary.WarningHandler = delegate(string msg)
			{
				_onWarning?.Invoke(msg);
			};
			_registeredQueues.Add(QueueName, this);
		}

		public void Connect()
		{
			if (IsConnected)
			{
				throw new InvalidOperationException("Already connected!");
			}
			new WrapperCommand();
			_primary.Connect(QueueName, IsAuthority, QueueCapacity);
			IsConnected = true;
		}

		public void Dispose()
		{
			_primary.Dispose();
			IsDisposed = true;
		}

		internal static MessagingQueue? TryGetRegisteredQueue(string queueName)
		{
			if (_registeredQueues.TryGetValue(queueName, out MessagingQueue value))
			{
				return value;
			}
			return null;
		}

		private void HandlePackable<T>(string ownerId, string id, T obj) where T : class, IMemoryPackable, new()
		{
			if (_ownerData[ownerId].TypedCallbacks.TryGetValue(typeof(T), out Dictionary<string, object> value) && value.ContainsKey(id))
			{
				((Action<T>)value[id])?.Invoke(obj);
				return;
			}
			_onWarning?.Invoke($"{QueueName}:{ownerId} Packable of type {typeof(T)} with Id {id} is not registered to receive a callback!");
		}

		private void CommandHandler(RendererCommand command, int messageSize)
		{
			if (command is WrapperCommand wrapperCommand)
			{
				OwnerData ownerData = _ownerData[wrapperCommand.Owner];
				IMemoryPackable packable = wrapperCommand.Packable;
				_onDebug?.Invoke($"{QueueName}:{ownerData.Id} Received {wrapperCommand.Id} {packable}");
				if (packable is QueueOwnerInitCommand)
				{
					if (ownerData.Initialized)
					{
						_onWarning?.Invoke(QueueName + ":" + ownerData.Id + " Received additional QueueOwnerInitCommand! Registered types will be reset!");
						ownerData.OutgoingTypeManager = new TypeManager((IMemoryPackerEntityPool)(object)this, ownerData.OnOutgoingTypeRegistered);
						ownerData.IncomingTypeManager = new TypeManager((IMemoryPackerEntityPool)(object)this, null);
					}
					else
					{
						ownerData.Initialized = true;
					}
					return;
				}
				if (!ownerData.Initialized)
				{
					throw new InvalidDataException("QueueOwnerInitCommand needs to be first!");
				}
				if (packable is TypeRegistrationCommand typeRegistrationCommand)
				{
					if ((object)typeRegistrationCommand.Type == null)
					{
						throw new InvalidDataException("Other process tried to register a type that could not be found in this process!");
					}
					_onDebug?.Invoke(QueueName + ":" + ownerData.Id + " * Registering incoming type: " + typeRegistrationCommand.Type.Name + "<" + string.Join(",", (IEnumerable<Type>)typeRegistrationCommand.Type.GenericTypeArguments) + ">");
					_ownerData[ownerData.Id].IncomingTypeManager.InvokeRegisterType(typeRegistrationCommand.Type);
				}
				else
				{
					_handlePackableMethod.MakeGenericMethod(((object)packable).GetType()).Invoke(this, new object[3] { ownerData.Id, wrapperCommand.Id, packable });
				}
			}
			else
			{
				_onWarning?.Invoke($"{QueueName} Received an unexpected RendererCommand! {command}");
			}
		}

		public void SendPackable<T>(string ownerId, string id, T packable) where T : class, IMemoryPackable, new()
		{
			if (packable == null)
			{
				throw new ArgumentNullException("packable");
			}
			if (ownerId == null)
			{
				throw new ArgumentNullException("ownerId");
			}
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			_onDebug?.Invoke($"{QueueName}:{ownerId} Sending: {id} {packable}");
			OwnerData ownerData = _ownerData[ownerId];
			if (!ownerData.OutgoingTypeManager.IsTypeRegistered<T>())
			{
				_onDebug?.Invoke(QueueName + ":" + ownerId + " * Registering outgoing type: " + typeof(T).Name + "<" + string.Join(",", (IEnumerable<Type>)typeof(T).GenericTypeArguments) + ">");
				ownerData.OutgoingTypeManager.RegisterType<T>();
			}
			WrapperCommand wrapperCommand = _pool.Borrow<WrapperCommand>();
			wrapperCommand.TypeIndex = ownerData.OutgoingTypeManager.GetTypeIndex(typeof(T));
			wrapperCommand.Owner = ownerId;
			wrapperCommand.Id = id;
			wrapperCommand.Packable = (IMemoryPackable?)(object)packable;
			_primary.SendCommand((RendererCommand)(object)wrapperCommand);
			_pool.Return<WrapperCommand>(wrapperCommand);
		}

		public void UnregisterOwner(string ownerId)
		{
			if (HasOwner(ownerId))
			{
				_ownerData.Remove(ownerId);
				if (_ownerData.Count == 0)
				{
					Dispose();
				}
				return;
			}
			throw new InvalidOperationException("Cannot unregister an owner who is not registered!");
		}

		T IMemoryPackerEntityPool.Borrow<T>()
		{
			return _pool.Borrow<T>();
		}

		void IMemoryPackerEntityPool.Return<T>(T value)
		{
			_pool.Return<T>(value);
		}
	}
	internal class TypeManager
	{
		private bool _initializedCoreTypes;

		private static readonly MethodInfo _registerTypeMethod = typeof(TypeManager).GetMethod("RegisterType", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingMethodException("RegisterType");

		private readonly List<Type> _newTypes = new List<Type>();

		private readonly List<Func<IMemoryPackable>> _borrowers = new List<Func<IMemoryPackable>>();

		private readonly List<Action<IMemoryPackable>> _returners = new List<Action<IMemoryPackable>>();

		private readonly Dictionary<Type, int> _typeToIndex = new Dictionary<Type, int>();

		private IMemoryPackerEntityPool _pool;

		private static readonly MethodInfo _borrowMethod = typeof(TypeManager).GetMethod("Borrow", BindingFlags.Instance | BindingFlags.NonPublic, null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("Borrow");

		private static readonly MethodInfo _returnMethod = typeof(TypeManager).GetMethod("Return", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(IMemoryPackable) }, null) ?? throw new MissingMethodException("Return");

		private static readonly List<Type> _coreTypes = new List<Type>(2)
		{
			typeof(QueueOwnerInitCommand),
			typeof(TypeRegistrationCommand)
		};

		private Action<Type>? _onRegisteredCallback;

		internal TypeManager(IMemoryPackerEntityPool pool, Action<Type>? onRegisteredCallback)
		{
			_pool = pool;
			_onRegisteredCallback = onRegisteredCallback;
			InitializeCoreTypes();
		}

		internal void InitializeCoreTypes()
		{
			if (!_initializedCoreTypes)
			{
				_coreTypes.ForEach(InvokeRegisterType);
				_initializedCoreTypes = true;
			}
		}

		internal Type GetTypeFromIndex(int index)
		{
			return _newTypes[index];
		}

		internal int GetTypeIndex(Type type)
		{
			return _typeToIndex[type];
		}

		internal bool IsTypeRegistered<T>() where T : class, IMemoryPackable, new()
		{
			return _typeToIndex.ContainsKey(typeof(T));
		}

		internal void InvokeRegisterType(Type type)
		{
			_registerTypeMethod.MakeGenericMethod(type).Invoke(this, null);
		}

		internal void RegisterType<T>() where T : class, IMemoryPackable, new()
		{
			Type typeFromHandle = typeof(T);
			_newTypes.Add(typeFromHandle);
			_borrowers.Add((Func<IMemoryPackable>)_borrowMethod.MakeGenericMethod(typeFromHandle).CreateDelegate(typeof(Func<IMemoryPackable>), this));
			_returners.Add((Action<IMemoryPackable>)_returnMethod.MakeGenericMethod(typeFromHandle).CreateDelegate(typeof(Action<IMemoryPackable>), this));
			_typeToIndex[typeFromHandle] = _newTypes.Count - 1;
			if (!_coreTypes.Contains(typeFromHandle))
			{
				_onRegisteredCallback?.Invoke(typeFromHandle);
			}
		}

		private IMemoryPackable Borrow<T>() where T : class, IMemoryPackable, new()
		{
			return (IMemoryPackable)(object)_pool.Borrow<T>();
		}

		private void Return<T>(IMemoryPackable obj) where T : class, IMemoryPackable, new()
		{
			_pool.Return<T>((T)(object)obj);
		}

		internal IMemoryPackable Borrow(Type type)
		{
			return _borrowers[_typeToIndex[type]]();
		}

		internal void Return(Type type, IMemoryPackable obj)
		{
			_returners[_typeToIndex[type]](obj);
		}

		internal IMemoryPackable Borrow(int index)
		{
			return _borrowers[index]();
		}

		internal void Return(int index, IMemoryPackable obj)
		{
			_returners[index](obj);
		}
	}
}
namespace InterprocessLib.Tests
{
	public static class Tests
	{
		private static Messenger? _messenger;

		private static Action<string>? _logCallback;

		public static void RunTests(Messenger messenger, Action<string> logCallback)
		{
			_messenger = messenger;
			_logCallback = logCallback;
			TestNullString();
			TestEmptyCommand();
			TestString();
			TestValue();
			TestNestedPackable();
			TestCustomRendererCommand();
			TestPackable();
			TestStruct();
			TestNestedStruct();
			TestValueList();
			TestValueHashSet();
			TestStringCollection();
			TestObjectList();
			TestVanillaObject();
			TestVanillaStruct();
			TestVanillaEnum();
			TestValueArray();
			TestObjectArray();
			TestObjectHashSet();
			TestStringArray();
			TestTypeCommand();
		}

		private static void TestTypeCommand()
		{
			_messenger.ReceiveType("TestTypeCommand", delegate(Type? type)
			{
				_logCallback("TestTypeCommand: " + (type?.FullName ?? "NULL"));
			});
			_messenger.SendType("TestTypeCommand", typeof(Dictionary<LinkedList<float>, float>));
		}

		private static void TestValueArray()
		{
			_messenger.ReceiveValueArray("TestValueArray", delegate(int[]? arr)
			{
				_logCallback("TestValueArray: " + string.Join(",", arr));
			});
			int[] array = new int[3] { 4, 7, -8 };
			_messenger.SendValueArray("TestValueArray", array);
		}

		private static void TestObjectArray()
		{
			_messenger.ReceiveObjectArray<TestCommand>("TestObjectArray", (Action<TestCommand[]>?)delegate(TestCommand?[] arr)
			{
				_logCallback("TestObjectArray: " + string.Join(",", (IEnumerable<TestCommand>)arr));
			});
			TestCommand[] array = new TestCommand[3]
			{
				new TestCommand(),
				null,
				null
			};
			array[0].Value = 64uL;
			array[0].Text = "Pizza";
			array[0].Time = DateTime.Now;
			array[1] = null;
			array[2] = new TestCommand();
			array[2].Value = 247uL;
			_messenger.SendObjectArray<TestCommand>("TestObjectArray", array);
		}

		private static void TestVanillaStruct()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			_messenger.ReceiveValue<HapticPointState>("TestVanillaStruct", (Action<HapticPointState>?)delegate(HapticPointState val)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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_003c: Unknown result type (might be due to invalid IL or missing references)
				_logCallback($"TestVanillaStruct: {val.force} {val.temperature} {val.pain} {val.vibration}");
			});
			HapticPointState value = default(HapticPointState);
			value.force = 8f;
			value.temperature = 4f;
			value.pain = 25f;
			value.vibration = 12f;
			_messenger.SendValue<HapticPointState>("TestVanillaStruct", value);
		}

		private static void TestVanillaEnum()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			_messenger.ReceiveValue<ShadowType>("TestVanillaEnum", (Action<ShadowType>?)delegate(ShadowType val)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				_logCallback($"TestVanillaEnum: {val}");
			});
			ShadowType value = (ShadowType)2;
			_messenger.SendValue<ShadowType>("TestVanillaEnum", value);
		}

		private static void TestNullString()
		{
			_messenger.ReceiveString("NullStr", delegate(string? str)
			{
				_logCallback("NullStr: " + str);
			});
			_messenger.SendString("NullStr", null);
		}

		private static void TestEmptyCommand()
		{
			_messenger.ReceiveEmptyCommand("TestEmptyCommand", delegate
			{
				_logCallback("TestEmptyCommand");
			});
			_messenger.SendEmptyCommand("TestEmptyCommand");
		}

		private static void TestString()
		{
			_messenger.ReceiveString("TestString", delegate(string? str)
			{
				_logCallback("TestString: " + (str ?? "NULL"));
			});
			_messenger.SendString("TestString", "I am a test string wow");
		}

		private static void TestValue()
		{
			_messenger.ReceiveValue("TestValue", delegate(int val)
			{
				_logCallback($"TestValue: {val}");
			});
			_messenger.SendValue("TestValue", 637);
		}

		private static void TestNestedPackable()
		{
			_messenger.ReceiveObject("TestNestedPackable", delegate(TestNestedPackable recvNestedPackable)
			{
				_logCallback(string.Format("TestNestedPackable: {0}, {1}, {2}, {3}, {4}", recvNestedPackable?.Value, ((object)recvNestedPackable?.Obj)?.ToString() ?? "NULL", recvNestedPackable?.Obj?.Value, recvNestedPackable?.Obj?.Text, recvNestedPackable?.Obj?.Time));
			});
			TestCommand testCommand = new TestCommand();
			testCommand.Value = 9999uL;
			testCommand.Text = "I am a nested command!";
			testCommand.Time = DateTime.MinValue;
			TestNestedPackable testNestedPackable = new TestNestedPackable();
			testNestedPackable.Value = 248;
			testNestedPackable.Obj = testCommand;
			_messenger.SendObject("TestNestedPackable", testNestedPackable);
		}

		private static void TestCustomRendererCommand()
		{
			_messenger.ReceiveObject<TestCommand>("TestCustomRendererCommand", (Action<TestCommand>?)delegate(TestCommand recvCmd)
			{
				_logCallback($"TestCustomRendererCommand: {recvCmd?.Value}, {recvCmd?.Text}, {recvCmd?.Time}");
			});
			TestCommand testCommand = new TestCommand();
			testCommand.Value = 2932uL;
			testCommand.Text = "Hello world";
			testCommand.Time = DateTime.Now;
			_messenger.SendObject<TestCommand>("TestCustomRendererCommand", testCommand);
		}

		private static void TestPackable()
		{
			_messenger.ReceiveObject("TestPackable", delegate(TestPackable recvObj)
			{
				_logCallback($"TestPackable: {recvObj?.Value}");
			});
			TestPackable testPackable = new TestPackable();
			testPackable.Value = 72u;
			_messenger.SendObject("TestPackable", testPackable);
		}

		private static void TestStruct()
		{
			_messenger.ReceiveValue("TestStruct", delegate(TestStruct recvStruct)
			{
				_logCallback($"TestStruct: {recvStruct.Value}");
			});
			TestStruct value = default(TestStruct);
			value.Value = 4;
			_messenger.SendValue("TestStruct", value);
		}

		private static void TestNestedStruct()
		{
			_messenger.ReceiveValue("TestNestedStruct", delegate(TestNestedStruct recvNestedStruct)
			{
				_logCallback($"TestNestedStruct: {recvNestedStruct.Nested.Value}");
			});
			TestStruct nested = default(TestStruct);
			TestNestedStruct value = default(TestNestedStruct);
			value.Nested = nested;
			_messenger.SendValue("TestNestedStruct", value);
		}

		private static void TestValueList()
		{
			_messenger.ReceiveValueCollection<List<float>, float>("TestValueList", delegate(List<float> list)
			{
				_logCallback("TestValueList: " + string.Join(",", list));
			});
			List<float> list2 = new List<float>();
			list2.Add(2f);
			list2.Add(7f);
			list2.Add(21f);
			_messenger.SendValueCollection<List<float>, float>("TestValueList", list2);
		}

		private static void TestValueHashSet()
		{
			_messenger.ReceiveValueCollection<HashSet<float>, float>("TestValueHashSet", delegate(HashSet<float> list)
			{
				_logCallback("TestValueHashSet: " + string.Join(",", list));
			});
			HashSet<float> hashSet = new HashSet<float>();
			hashSet.Add(99.92f);
			hashSet.Add(127.2f);
			hashSet.Add(-4.32f);
			_messenger.SendValueCollection<HashSet<float>, float>("TestValueHashSet", hashSet);
		}

		private static void TestObjectList()
		{
			_messenger.ReceiveObjectCollection<List<TestPackable>, TestPackable>("TestObjectList", delegate(List<TestPackable> list)
			{
				_logCallback("TestObjectList: " + string.Join(",", list));
			});
			List<TestPackable> list2 = new List<TestPackable>();
			list2.Add(new TestPackable
			{
				Value = 7u
			});
			list2.Add(new TestPackable
			{
				Value = 15u
			});
			list2.Add(new TestPackable
			{
				Value = 83u
			});
			_messenger.SendObjectCollection<List<TestPackable>, TestPackable>("TestObjectList", list2);
		}

		private static void TestObjectHashSet()
		{
			_messenger.ReceiveObjectCollection<HashSet<TestCommand>, TestCommand>("TestObjectHashSet", (Action<HashSet<TestCommand>>?)delegate(HashSet<TestCommand?> list)
			{
				_logCallback("TestObjectHashSet: " + string.Join(",", list));
			});
			HashSet<TestCommand> hashSet = new HashSet<TestCommand>();
			hashSet.Add(new TestCommand());
			hashSet.Add(null);
			hashSet.Add(new TestCommand
			{
				Value = 9uL
			});
			_messenger.SendObjectCollection<HashSet<TestCommand>, TestCommand>("TestObjectHashSet", hashSet);
		}

		private static void TestStringCollection()
		{
			_messenger.ReceiveStringCollection("TestStringCollection", delegate(List<string> list)
			{
				_logCallback("TestStringCollection: " + string.Join(",", list.Select((string s) => s ?? "NULL")));
			});
			List<string> list2 = new List<string>();
			list2.Add("Hello");
			list2.Add("World");
			list2.Add("owo");
			list2.Add(null);
			list2.Add("x3");
			_messenger.SendStringCollection<List<string>>("TestStringCollection", list2);
		}

		private static void TestStringArray()
		{
			_messenger.ReceiveStringArray("TestStringArray", delegate(string?[]? arr)
			{
				_logCallback("TestStringArray: " + string.Join(",", arr.Select((string s) => s ?? "NULL")));
			});
			string[] array = new string[5] { "Hello", "World", "owo", null, "x3" };
			_messenger.SendStringArray("TestStringArray", array);
		}

		private static void TestVanillaObject()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			_messenger.ReceiveObject<RendererInitData>("TestVanillaObject", (Action<RendererInitData>?)delegate(RendererInitData recv)
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				_logCallback($"TestVanillaObject: {recv.sharedMemoryPrefix} {recv.uniqueSessionId} {recv.mainProcessId} {recv.debugFramePacing} {recv.outputDevice} {recv.setWindowIcon} {recv.splashScreenOverride}");
			});
			RendererInitData obj = new RendererInitData();
			_messenger.SendObject<RendererInitData>("TestVanillaObject", obj);
		}
	}
	public class TestCommand : RendererCommand
	{
		public ulong Value;

		public string Text = "";

		public DateTime Time;

		public override void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<ulong>(Value);
			((MemoryPacker)(ref packer)).Write(Text);
			((MemoryPacker)(ref packer)).Write<DateTime>(Time);
		}

		public override void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<ulong>(ref Value);
			((MemoryUnpacker)(ref unpacker)).Read(ref Text);
			((MemoryUnpacker)(ref unpacker)).Read<DateTime>(ref Time);
		}

		public override string ToString()
		{
			return $"TestCommand: {Value}, {Text}, {Time}";
		}
	}
	public class TestNestedPackable : IMemoryPackable
	{
		public byte Value;

		public TestCommand? Obj;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<byte>(Value);
			((MemoryPacker)(ref packer)).WriteObject<TestCommand>(Obj);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<byte>(ref Value);
			((MemoryUnpacker)(ref unpacker)).ReadObject<TestCommand>(ref Obj);
		}
	}
	public class TestPackable : IMemoryPackable
	{
		public uint Value;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<uint>(Value);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<uint>(ref Value);
		}

		public override string ToString()
		{
			return $"TestPackable: {Value}";
		}
	}
	public struct TestStruct
	{
		public int Value;
	}
	public struct TestNestedStruct
	{
		public TestStruct Nested;
	}
}

Renderer/BepInEx/plugins/InterprocessLib.BepInEx/InterprocessLib.BepInEx_Extensions.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Nytra")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: AssemblyInformationalVersion("3.0.0+cec136eadee793dc3aceee57dbadeb04e56bd3e1")]
[assembly: AssemblyProduct("InterprocessLib.BepInEx_Extensions")]
[assembly: AssemblyTitle("InterprocessLib.BepInEx_Extensions")]
[assembly: AssemblyVersion("3.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[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 InterprocessLib
{
	public static class BepInExExtensions
	{
		private static Dictionary<ConfigEntryBase, bool> _syncStates = new Dictionary<ConfigEntryBase, bool>();

		public static void SyncConfigEntry<T>(this Messenger messenger, ConfigEntry<T> configEntry) where T : unmanaged
		{
			ConfigEntry<T> configEntry2 = configEntry;
			Messenger messenger2 = messenger;
			messenger2.ReceiveConfigEntry<T>(configEntry2);
			_syncStates[(ConfigEntryBase)(object)configEntry2] = true;
			configEntry2.SettingChanged += delegate
			{
				if (_syncStates.TryGetValue((ConfigEntryBase)(object)configEntry2, out var value) && value)
				{
					messenger2.SendConfigEntry<T>(configEntry2);
				}
			};
		}

		public static void SyncConfigEntry(this Messenger messenger, ConfigEntry<string> configEntry)
		{
			ConfigEntry<string> configEntry2 = configEntry;
			Messenger messenger2 = messenger;
			messenger2.ReceiveConfigEntry(configEntry2);
			_syncStates[(ConfigEntryBase)(object)configEntry2] = true;
			configEntry2.SettingChanged += delegate
			{
				if (_syncStates.TryGetValue((ConfigEntryBase)(object)configEntry2, out var value) && value)
				{
					messenger2.SendConfigEntry(configEntry2);
				}
			};
		}

		public static void SendConfigEntry<T>(this Messenger messenger, ConfigEntry<T> configEntry) where T : unmanaged
		{
			messenger.SendValue<T>(((ConfigEntryBase)configEntry).Definition.Key, configEntry.Value);
		}

		public static void SendConfigEntry(this Messenger messenger, ConfigEntry<string> configEntry)
		{
			messenger.SendString(((ConfigEntryBase)configEntry).Definition.Key, configEntry.Value);
		}

		public static void ReceiveConfigEntry<T>(this Messenger messenger, ConfigEntry<T> configEntry) where T : unmanaged
		{
			ConfigEntry<T> configEntry2 = configEntry;
			messenger.ReceiveValue<T>(((ConfigEntryBase)configEntry2).Definition.Key, (Action<T>)delegate(T val)
			{
				_syncStates[(ConfigEntryBase)(object)configEntry2] = false;
				configEntry2.Value = val;
				_syncStates[(ConfigEntryBase)(object)configEntry2] = true;
			});
		}

		public static void ReceiveConfigEntry(this Messenger messenger, ConfigEntry<string> configEntry)
		{
			ConfigEntry<string> configEntry2 = configEntry;
			messenger.ReceiveString(((ConfigEntryBase)configEntry2).Definition.Key, (Action<string>)delegate(string? str)
			{
				_syncStates[(ConfigEntryBase)(object)configEntry2] = false;
				configEntry2.Value = str;
				_syncStates[(ConfigEntryBase)(object)configEntry2] = true;
			});
		}
	}
}