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.1.0")] [assembly: AssemblyInformationalVersion("3.0.1+13cb696b14da8840cc9c79e41e9701df3b671dda")] [assembly: AssemblyProduct("InterprocessLib.Unity")] [assembly: AssemblyTitle("InterprocessLib.Unity")] [assembly: AssemblyVersion("3.0.1.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].EndsWith("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 : CollectionCommand where C : ICollection?, 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(num); if (Values == null) { return; } foreach (T value in Values) { ((MemoryPacker)(ref packer)).Write(value); } } public override void Unpack(ref MemoryUnpacker unpacker) { int num = 0; ((MemoryUnpacker)(ref unpacker)).Read(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(ref item); Values.Add(item); } } } internal sealed class ValueArrayCommand : 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(num); if (Values != null) { Span destination = ((MemoryPacker)(ref packer)).Access(num); Values.CopyTo(destination); } } public override void Unpack(ref MemoryUnpacker unpacker) { int num = 0; ((MemoryUnpacker)(ref unpacker)).Read(ref num); if (num == -1) { Values = null; return; } Values = new T[num]; ((MemoryUnpacker)(ref unpacker)).Access(num).CopyTo(Values); } } internal sealed class TypeRegistrationCommand : TypeCommand { public override string ToString() { string[] obj = new string[5] { "TypeRegistrationCommand:", Type?.Name ?? "NULL", "<", null, null }; IEnumerable enumerable = Type?.GenericTypeArguments; obj[3] = string.Join(",", enumerable ?? Array.Empty()); obj[4] = ">"; return string.Concat(obj); } } internal class TypeCommand : IMemoryPackable { public Type? Type; private static Dictionary _typeCache = new Dictionary(); 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(false); return; } ((MemoryPacker)(ref packer)).Write(true); if (type.IsGenericType) { ((MemoryPacker)(ref packer)).Write(true); Type genericTypeDefinition = type.GetGenericTypeDefinition(); ((MemoryPacker)(ref packer)).Write(genericTypeDefinition.FullName); Type[] genericArguments = type.GetGenericArguments(); ((MemoryPacker)(ref packer)).Write(genericArguments.Length); Type[] array = genericArguments; foreach (Type type2 in array) { PackType(type2, ref packer); } } else { ((MemoryPacker)(ref packer)).Write(false); ((MemoryPacker)(ref packer)).Write(type.FullName); } } private Type? UnpackType(ref MemoryUnpacker unpacker) { if (!((MemoryUnpacker)(ref unpacker)).Read()) { return null; } if (((MemoryUnpacker)(ref unpacker)).Read()) { string typeString = ((MemoryUnpacker)(ref unpacker)).ReadString(); int num = ((MemoryUnpacker)(ref unpacker)).Read(); 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 enumerable = Type?.GenericTypeArguments; obj[3] = string.Join(",", enumerable ?? Array.Empty()); 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(-1); return; } int num = Strings.Length; ((MemoryPacker)(ref packer)).Write(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(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 : CollectionCommand where C : ICollection?, new() { public IReadOnlyCollection? 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(-1); return; } int count = Strings.Count; ((MemoryPacker)(ref packer)).Write(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(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)(object)val; } } internal sealed class ObjectCollectionCommand : CollectionCommand where C : ICollection?, 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(-1); return; } int count = Objects.Count; ((MemoryPacker)(ref packer)).Write(count); foreach (T @object in Objects) { ((MemoryPacker)(ref packer)).WriteObject(@object); } } public override void Unpack(ref MemoryUnpacker unpacker) { int num = 0; ((MemoryUnpacker)(ref unpacker)).Read(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(ref item); Objects.Add(item); } } } internal sealed class ObjectArrayCommand : 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(-1); return; } int num = Objects.Length; ((MemoryPacker)(ref packer)).Write(num); T[] objects = Objects; foreach (T val in objects) { ((MemoryPacker)(ref packer)).WriteObject(val); } } public override void Unpack(ref MemoryUnpacker unpacker) { int num = 0; ((MemoryUnpacker)(ref unpacker)).Read(ref num); if (num == -1) { Objects = null; return; } Objects = new T[num]; for (int i = 0; i < num; i++) { ((MemoryUnpacker)(ref unpacker)).ReadObject(ref Objects[i]); } } } internal sealed class ObjectCommand : 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(Object); } public override void Unpack(ref MemoryUnpacker unpacker) { ((MemoryUnpacker)(ref unpacker)).ReadObject(ref Object); } } internal sealed class ValueCommand : 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(Value); } public override void Unpack(ref MemoryUnpacker unpacker) { ((MemoryUnpacker)(ref unpacker)).Read(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 CurrentRendererCommandTypes => ((List)typeof(PolymorphicMemoryPackableEntity).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 list = new List(); list.AddRange(CurrentRendererCommandTypes); list.Add(typeof(WrapperCommand)); PolymorphicMemoryPackableEntity.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(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(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? OnFailure; public static event Action? OnWarning; public static event Action? 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? additionalObjectTypes = null, List? 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(string id, T value) where T : unmanaged { if (id == null) { throw new ArgumentNullException("id"); } ValueCommand valueCommand = _pool.Borrow>(); valueCommand.Value = value; _currentQueue.SendPackable(_ownerId, id, valueCommand); _pool.Return>(valueCommand); } [Obsolete("Use SendValueCollection instead.")] public void SendValueList(string id, List? list) where T : unmanaged { SendValueCollection, T>(id, list); } [Obsolete("Use SendValueCollection instead.")] public void SendValueHashSet(string id, HashSet? hashSet) where T : unmanaged { SendValueCollection, T>(id, hashSet); } public void SendValueCollection(string id, C? collection) where C : ICollection?, new() where T : unmanaged { if (id == null) { throw new ArgumentNullException("id"); } ValueCollectionCommand valueCollectionCommand = _pool.Borrow>(); valueCollectionCommand.Values = collection; _currentQueue.SendPackable(_ownerId, id, valueCollectionCommand); _pool.Return>(valueCollectionCommand); } public void SendValueArray(string id, T[]? array) where T : unmanaged { if (id == null) { throw new ArgumentNullException("id"); } ValueArrayCommand valueArrayCommand = _pool.Borrow>(); valueArrayCommand.Values = array; _currentQueue.SendPackable(_ownerId, id, valueArrayCommand); _pool.Return>(valueArrayCommand); } public void SendString(string id, string? str) { if (id == null) { throw new ArgumentNullException("id"); } StringCommand stringCommand = _pool.Borrow(); stringCommand.String = str; _currentQueue.SendPackable(_ownerId, id, stringCommand); _pool.Return(stringCommand); } [Obsolete("Use SendStringCollection instead.")] public void SendStringList(string id, List? list) { SendStringCollection>(id, list); } public void SendStringCollection(string id, IReadOnlyCollection? collection) where C : ICollection?, new() { if (id == null) { throw new ArgumentNullException("id"); } StringCollectionCommand stringCollectionCommand = _pool.Borrow>(); stringCollectionCommand.Strings = collection; _currentQueue.SendPackable(_ownerId, id, stringCollectionCommand); _pool.Return>(stringCollectionCommand); } public void SendStringArray(string id, string?[]? array) { if (id == null) { throw new ArgumentNullException("id"); } StringArrayCommand stringArrayCommand = _pool.Borrow(); stringArrayCommand.Strings = array; _currentQueue.SendPackable(_ownerId, id, stringArrayCommand); _pool.Return(stringArrayCommand); } public void SendEmptyCommand(string id) { if (id == null) { throw new ArgumentNullException("id"); } EmptyCommand emptyCommand = _pool.Borrow(); _currentQueue.SendPackable(_ownerId, id, emptyCommand); _pool.Return(emptyCommand); } public void SendObject(string id, T? obj) where T : class?, IMemoryPackable, new() { if (id == null) { throw new ArgumentNullException("id"); } ObjectCommand objectCommand = _pool.Borrow>(); objectCommand.Object = obj; _currentQueue.SendPackable(_ownerId, id, objectCommand); _pool.Return>(objectCommand); } [Obsolete("Use SendObjectCollection instead.")] public void SendObjectList(string id, List? list) where T : class?, IMemoryPackable, new() { SendObjectCollection, T>(id, list); } public void SendObjectCollection(string id, C? collection) where C : ICollection?, new() where T : class?, IMemoryPackable, new() { if (id == null) { throw new ArgumentNullException("id"); } ObjectCollectionCommand objectCollectionCommand = _pool.Borrow>(); objectCollectionCommand.Objects = collection; _currentQueue.SendPackable(_ownerId, id, objectCollectionCommand); _pool.Return>(objectCollectionCommand); } public void SendObjectArray(string id, T[]? array) where T : class?, IMemoryPackable, new() { if (id == null) { throw new ArgumentNullException("id"); } ObjectArrayCommand objectArrayCommand = _pool.Borrow>(); objectArrayCommand.Objects = array; _currentQueue.SendPackable(_ownerId, id, objectArrayCommand); _pool.Return>(objectArrayCommand); } public void SendType(string id, Type type) { if (id == null) { throw new ArgumentNullException("id"); } TypeCommand typeCommand = _pool.Borrow(); typeCommand.Type = type; _currentQueue.SendPackable(_ownerId, id, typeCommand); _pool.Return(typeCommand); } public void ReceiveValue(string id, Action? callback) where T : unmanaged { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ValueCommand cmd) { callback2?.Invoke(cmd.Value); }); } [Obsolete("Use ReceiveValueCollection instead.")] public void ReceiveValueList(string id, Action>? callback) where T : unmanaged { ReceiveValueCollection, T>(id, callback); } [Obsolete("Use ReceiveValueCollection instead.")] public void ReceiveValueHashSet(string id, Action>? callback) where T : unmanaged { ReceiveValueCollection, T>(id, callback); } public void ReceiveValueCollection(string id, Action? callback) where C : ICollection?, new() where T : unmanaged { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ValueCollectionCommand cmd) { callback2?.Invoke(cmd.Values); }); } public void ReceiveValueArray(string id, Action? callback) where T : unmanaged { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ValueArrayCommand cmd) { callback2?.Invoke(cmd.Values); }); } public void ReceiveString(string id, Action? callback) { Action 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?>? callback) { ReceiveStringCollection(id, callback); } public void ReceiveStringCollection(string id, Action? callback) where C : ICollection?, new() { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(StringCollectionCommand cmd) { callback2?.Invoke((C)cmd.Strings); }); } public void ReceiveStringArray(string id, Action? callback) { Action 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(_ownerId, id, delegate { callback2?.Invoke(); }); } public void ReceiveObject(string id, Action? callback) where T : class?, IMemoryPackable, new() { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectCommand cmd) { callback2?.Invoke(cmd.Object); }); } [Obsolete("Use ReceiveObjectCollection instead.")] public void ReceiveObjectList(string id, Action>? callback) where T : class?, IMemoryPackable, new() { ReceiveObjectCollection, T>(id, callback); } public void ReceiveObjectCollection(string id, Action? callback) where C : ICollection?, new() where T : class?, IMemoryPackable, new() { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectCollectionCommand cmd) { callback2?.Invoke(cmd.Objects); }); } public void ReceiveObjectArray(string id, Action? callback) where T : class?, IMemoryPackable, new() { Action callback2 = callback; if (id == null) { throw new ArgumentNullException("id"); } _currentQueue.RegisterCallback(_ownerId, id, delegate(ObjectArrayCommand cmd) { callback2?.Invoke(cmd.Objects); }); } public void ReceiveType(string id, Action callback) { Action 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> TypedCallbacks = new Dictionary>(); 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? _onWarning; private Action? _onDebug; private Action? _onFailure; private readonly Dictionary _ownerData = new Dictionary(); private static readonly Dictionary _registeredQueues = new Dictionary(); 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(string owner, string id, Action? callback) where T : IMemoryPackable { if (!_ownerData[owner].TypedCallbacks.ContainsKey(typeof(T))) { _ownerData[owner].TypedCallbacks.Add(typeof(T), new Dictionary()); } _ownerData[owner].TypedCallbacks[typeof(T)][id] = callback; } public MessagingQueue(bool isAuthority, string queueName, long queueCapacity, IMemoryPackerEntityPool pool, Action? failhandler = null, Action? warnHandler = null, Action? 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(string ownerId, string id, T obj) where T : class, IMemoryPackable, new() { if (_ownerData[ownerId].TypedCallbacks.TryGetValue(typeof(T), out Dictionary value) && value.ContainsKey(id)) { ((Action)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)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(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()) { _onDebug?.Invoke(QueueName + ":" + ownerId + " * Registering outgoing type: " + typeof(T).Name + "<" + string.Join(",", (IEnumerable)typeof(T).GenericTypeArguments) + ">"); ownerData.OutgoingTypeManager.RegisterType(); } WrapperCommand wrapperCommand = _pool.Borrow(); 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); } 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() { return _pool.Borrow(); } void IMemoryPackerEntityPool.Return(T value) { _pool.Return(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 _newTypes = new List(); private readonly List> _borrowers = new List>(); private readonly List> _returners = new List>(); private readonly Dictionary _typeToIndex = new Dictionary(); private IMemoryPackerEntityPool _pool; private static readonly MethodInfo _borrowMethod = typeof(TypeManager).GetMethod("Borrow", BindingFlags.Instance | BindingFlags.NonPublic, null, Array.Empty(), 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 _coreTypes = new List(2) { typeof(QueueOwnerInitCommand), typeof(TypeRegistrationCommand) }; private Action? _onRegisteredCallback; internal TypeManager(IMemoryPackerEntityPool pool, Action? 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() where T : class, IMemoryPackable, new() { return _typeToIndex.ContainsKey(typeof(T)); } internal void InvokeRegisterType(Type type) { _registerTypeMethod.MakeGenericMethod(type).Invoke(this, null); } internal void RegisterType() where T : class, IMemoryPackable, new() { Type typeFromHandle = typeof(T); _newTypes.Add(typeFromHandle); _borrowers.Add((Func)_borrowMethod.MakeGenericMethod(typeFromHandle).CreateDelegate(typeof(Func), this)); _returners.Add((Action)_returnMethod.MakeGenericMethod(typeFromHandle).CreateDelegate(typeof(Action), this)); _typeToIndex[typeFromHandle] = _newTypes.Count - 1; if (!_coreTypes.Contains(typeFromHandle)) { _onRegisteredCallback?.Invoke(typeFromHandle); } } private IMemoryPackable Borrow() where T : class, IMemoryPackable, new() { return (IMemoryPackable)(object)_pool.Borrow(); } private void Return(IMemoryPackable obj) where T : class, IMemoryPackable, new() { _pool.Return((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? _logCallback; public static void RunTests(Messenger messenger, Action 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, 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("TestObjectArray", (Action?)delegate(TestCommand?[] arr) { _logCallback("TestObjectArray: " + string.Join(",", (IEnumerable)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("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("TestVanillaStruct", (Action?)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("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("TestVanillaEnum", (Action?)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("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("TestCustomRendererCommand", (Action?)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("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, float>("TestValueList", delegate(List list) { _logCallback("TestValueList: " + string.Join(",", list)); }); List list2 = new List(); list2.Add(2f); list2.Add(7f); list2.Add(21f); _messenger.SendValueCollection, float>("TestValueList", list2); } private static void TestValueHashSet() { _messenger.ReceiveValueCollection, float>("TestValueHashSet", delegate(HashSet list) { _logCallback("TestValueHashSet: " + string.Join(",", list)); }); HashSet hashSet = new HashSet(); hashSet.Add(99.92f); hashSet.Add(127.2f); hashSet.Add(-4.32f); _messenger.SendValueCollection, float>("TestValueHashSet", hashSet); } private static void TestObjectList() { _messenger.ReceiveObjectCollection, TestPackable>("TestObjectList", delegate(List list) { _logCallback("TestObjectList: " + string.Join(",", list)); }); List list2 = new List(); list2.Add(new TestPackable { Value = 7u }); list2.Add(new TestPackable { Value = 15u }); list2.Add(new TestPackable { Value = 83u }); _messenger.SendObjectCollection, TestPackable>("TestObjectList", list2); } private static void TestObjectHashSet() { _messenger.ReceiveObjectCollection, TestCommand>("TestObjectHashSet", (Action>?)delegate(HashSet list) { _logCallback("TestObjectHashSet: " + string.Join(",", list)); }); HashSet hashSet = new HashSet(); hashSet.Add(new TestCommand()); hashSet.Add(null); hashSet.Add(new TestCommand { Value = 9uL }); _messenger.SendObjectCollection, TestCommand>("TestObjectHashSet", hashSet); } private static void TestStringCollection() { _messenger.ReceiveStringCollection("TestStringCollection", delegate(List list) { _logCallback("TestStringCollection: " + string.Join(",", list.Select((string s) => s ?? "NULL"))); }); List list2 = new List(); list2.Add("Hello"); list2.Add("World"); list2.Add("owo"); list2.Add(null); list2.Add("x3"); _messenger.SendStringCollection>("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("TestVanillaObject", (Action?)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("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(Value); ((MemoryPacker)(ref packer)).Write(Text); ((MemoryPacker)(ref packer)).Write(Time); } public override void Unpack(ref MemoryUnpacker unpacker) { ((MemoryUnpacker)(ref unpacker)).Read(ref Value); ((MemoryUnpacker)(ref unpacker)).Read(ref Text); ((MemoryUnpacker)(ref unpacker)).Read(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(Value); ((MemoryPacker)(ref packer)).WriteObject(Obj); } public void Unpack(ref MemoryUnpacker unpacker) { ((MemoryUnpacker)(ref unpacker)).Read(ref Value); ((MemoryUnpacker)(ref unpacker)).ReadObject(ref Obj); } } public class TestPackable : IMemoryPackable { public uint Value; public void Pack(ref MemoryPacker packer) { ((MemoryPacker)(ref packer)).Write(Value); } public void Unpack(ref MemoryUnpacker unpacker) { ((MemoryUnpacker)(ref unpacker)).Read(ref Value); } public override string ToString() { return $"TestPackable: {Value}"; } } public struct TestStruct { public int Value; } public struct TestNestedStruct { public TestStruct Nested; } }