Decompiled source of SOTFEdit Companion v1.0.2
BepInEx/plugins/SOTFEdit_Companion/MessagePack.Annotations.dll
Decompiled 9 months agousing System; using System.CodeDom.Compiler; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("2.5.108.51978")] [assembly: AssemblyInformationalVersion("2.5.108+cb0ad5dd95")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("neuecc,aarnott")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Yoshifumi Kawai and contributors. All rights reserved.")] [assembly: AssemblyDescription("Attributes and interfaces for .NET types serializable with MessagePack.")] [assembly: AssemblyProduct("MessagePack.Annotations")] [assembly: AssemblyTitle("MessagePack.Annotations")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/neuecc/MessagePack-CSharp")] [assembly: AssemblyVersion("2.5.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } [GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.5.119.9565")] [ExcludeFromCodeCoverage] internal static class ThisAssembly { internal const string AssemblyConfiguration = "Release"; internal const string AssemblyFileVersion = "2.5.108.51978"; internal const string AssemblyInformationalVersion = "2.5.108+cb0ad5dd95"; internal const string AssemblyName = "MessagePack.Annotations"; internal const string AssemblyTitle = "MessagePack.Annotations"; internal const string AssemblyVersion = "2.5.0.0"; internal static readonly DateTime GitCommitDate = new DateTime(638145736080000000L, DateTimeKind.Utc); internal const string GitCommitId = "cb0ad5dd955cb9b14ca63019938a6aada43ce822"; internal const bool IsPrerelease = false; internal const bool IsPublicRelease = true; internal const string PublicKey = "0024000004800000940000000602000000240000525341310004000001000100293894d4e8ad2b53afbea4e949ef54c2a388b08b5ebd143c811da82f22aa20c839ed1c0b4da83e7195e8c1dbe1bf3934e4e8fd7fb93f893439106fbf055a97c7fac0f7f8c39e58e78371dc0e3825e5b9d7e2afff0372f03c4d67ff7df0dbfb58dcadeb1044840de152bf8270de7fc54255ace8efd026c16311760d1a2570c3e8"; internal const string PublicKeyToken = "b4a0369545f0a1be"; internal const string RootNamespace = "MessagePack"; } namespace MessagePack { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] public class MessagePackObjectAttribute : Attribute { public bool KeyAsPropertyName { get; private set; } public MessagePackObjectAttribute(bool keyAsPropertyName = false) { KeyAsPropertyName = keyAsPropertyName; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public class KeyAttribute : Attribute { public int? IntKey { get; private set; } public string? StringKey { get; private set; } public KeyAttribute(int x) { IntKey = x; } public KeyAttribute(string x) { StringKey = x ?? throw new ArgumentNullException("x"); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public class IgnoreMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] public class UnionAttribute : Attribute { public int Key { get; private set; } public Type SubType { get; private set; } public UnionAttribute(int key, Type subType) { Key = key; SubType = subType ?? throw new ArgumentNullException("subType"); } public UnionAttribute(int key, string subType) { Key = key; SubType = Type.GetType(subType, throwOnError: true); } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = true)] public class SerializationConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] public class MessagePackFormatterAttribute : Attribute { public Type FormatterType { get; private set; } public object?[]? Arguments { get; private set; } public MessagePackFormatterAttribute(Type formatterType) { FormatterType = formatterType ?? throw new ArgumentNullException("formatterType"); } public MessagePackFormatterAttribute(Type formatterType, params object?[]? arguments) { FormatterType = formatterType ?? throw new ArgumentNullException("formatterType"); Arguments = arguments; } } public interface IMessagePackSerializationCallbackReceiver { void OnBeforeSerialize(); void OnAfterDeserialize(); } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } }
BepInEx/plugins/SOTFEdit_Companion/MessagePack.dll
Decompiled 9 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Buffers.Binary; using System.Buffers.Text; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MessagePack.Formatters; using MessagePack.ImmutableCollection; using MessagePack.Internal; using MessagePack.LZ4; using MessagePack.Resolvers; using Microsoft.CodeAnalysis; using Microsoft.NET.StringTools; using Nerdbank.Streams; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("2.5.108.51978")] [assembly: AssemblyInformationalVersion("2.5.108+cb0ad5dd95")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("neuecc,aarnott")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Yoshifumi Kawai and contributors. All rights reserved.")] [assembly: AssemblyDescription("Extremely Fast MessagePack(MsgPack) Serializer for C# (.NET Framework, .NET 6, Unity, Xamarin).")] [assembly: AssemblyProduct("MessagePack")] [assembly: AssemblyTitle("MessagePack")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/neuecc/MessagePack-CSharp")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.5.0.0")] [module: UnverifiableCode] 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; } } } [GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.5.119.9565")] [ExcludeFromCodeCoverage] internal static class ThisAssembly { internal const string AssemblyConfiguration = "Release"; internal const string AssemblyFileVersion = "2.5.108.51978"; internal const string AssemblyInformationalVersion = "2.5.108+cb0ad5dd95"; internal const string AssemblyName = "MessagePack"; internal const string AssemblyTitle = "MessagePack"; internal const string AssemblyVersion = "2.5.0.0"; internal static readonly DateTime GitCommitDate = new DateTime(638145736080000000L, DateTimeKind.Utc); internal const string GitCommitId = "cb0ad5dd955cb9b14ca63019938a6aada43ce822"; internal const bool IsPrerelease = false; internal const bool IsPublicRelease = true; internal const string PublicKey = "0024000004800000940000000602000000240000525341310004000001000100293894d4e8ad2b53afbea4e949ef54c2a388b08b5ebd143c811da82f22aa20c839ed1c0b4da83e7195e8c1dbe1bf3934e4e8fd7fb93f893439106fbf055a97c7fac0f7f8c39e58e78371dc0e3825e5b9d7e2afff0372f03c4d67ff7df0dbfb58dcadeb1044840de152bf8270de7fc54255ace8efd026c16311760d1a2570c3e8"; internal const string PublicKeyToken = "b4a0369545f0a1be"; internal const string RootNamespace = "MessagePack"; } namespace Nerdbank.Streams { [DebuggerDisplay("{DebuggerDisplay,nq}")] internal class Sequence<T> : IBufferWriter<T>, IDisposable { private class SequenceSegment : ReadOnlySequenceSegment<T> { internal static readonly SequenceSegment Empty = new SequenceSegment(); private static readonly bool MayContainReferences = !typeof(T).GetTypeInfo().IsPrimitive; private T[]? array; internal int Start { get; private set; } internal int End { get; private set; } internal Memory<T> RemainingMemory => AvailableMemory.Slice(End); internal Span<T> RemainingSpan => AvailableMemory.Span.Slice(End); internal IMemoryOwner<T>? MemoryOwner { get; private set; } internal Memory<T> AvailableMemory { get { T[] array = this.array; if (array == null) { return MemoryOwner?.Memory ?? default(Memory<T>); } return array; } } internal int Length => checked(End - Start); internal int WritableBytes => checked(AvailableMemory.Length - End); internal new SequenceSegment? Next { get { return (SequenceSegment)base.Next; } set { base.Next = value; } } internal bool IsForeignMemory { get { if (array == null) { return MemoryOwner == null; } return false; } } internal void Assign(IMemoryOwner<T> memoryOwner) { MemoryOwner = memoryOwner; base.Memory = memoryOwner.Memory; } internal void Assign(T[] array) { this.array = array; base.Memory = array; } internal void AssignForeign(ReadOnlyMemory<T> memory) { base.Memory = memory; End = memory.Length; } internal void ResetMemory(ArrayPool<T>? arrayPool) { ClearReferences(Start, checked(End - Start)); base.Memory = default(ReadOnlyMemory<T>); Next = null; base.RunningIndex = 0L; Start = 0; End = 0; if (array != null) { arrayPool.Return(array); array = null; } else { MemoryOwner?.Dispose(); MemoryOwner = null; } } internal void SetNext(SequenceSegment segment) { Next = segment; checked { segment.RunningIndex = base.RunningIndex + Start + Length; if (!IsForeignMemory) { base.Memory = AvailableMemory.Slice(0, Start + Length); } } } internal void Advance(int count) { checked { Requires.Range(count >= 0 && End + count <= base.Memory.Length, "count"); End += count; } } internal void AdvanceTo(int offset) { ClearReferences(Start, checked(offset - Start)); Start = offset; } private void ClearReferences(int startIndex, int length) { if (MayContainReferences) { Span<T> span = AvailableMemory.Span; span = span.Slice(startIndex, length); span.Clear(); } } } private const int MaximumAutoGrowSize = 32768; private static readonly int DefaultLengthFromArrayPool; private static readonly ReadOnlySequence<T> Empty; private readonly Stack<SequenceSegment> segmentPool = new Stack<SequenceSegment>(); private readonly MemoryPool<T>? memoryPool; private readonly ArrayPool<T>? arrayPool; private SequenceSegment? first; private SequenceSegment? last; public int MinimumSpanLength { get; set; } public bool AutoIncreaseMinimumSpanLength { get; set; } = true; public ReadOnlySequence<T> AsReadOnlySequence => this; public long Length => AsReadOnlySequence.Length; private string DebuggerDisplay => $"Length: {AsReadOnlySequence.Length}"; public Sequence() : this(ArrayPool<T>.Create()) { } public Sequence(MemoryPool<T> memoryPool) { Requires.NotNull(memoryPool, "memoryPool"); this.memoryPool = memoryPool; } public Sequence(ArrayPool<T> arrayPool) { Requires.NotNull(arrayPool, "arrayPool"); this.arrayPool = arrayPool; } public static implicit operator ReadOnlySequence<T>(Sequence<T> sequence) { SequenceSegment sequenceSegment = sequence.first; if (sequenceSegment != null) { SequenceSegment sequenceSegment2 = sequence.last; if (sequenceSegment2 != null) { return new ReadOnlySequence<T>(sequenceSegment, sequenceSegment.Start, sequenceSegment2, sequenceSegment2.End); } } return Empty; } public void AdvanceTo(SequencePosition position) { SequenceSegment sequenceSegment = (SequenceSegment)position.GetObject(); if (sequenceSegment != null && (sequenceSegment != SequenceSegment.Empty || Length != 0L)) { int integer = position.GetInteger(); SequenceSegment next = first; while (next != sequenceSegment && next != null) { next = next.Next; } Requires.Argument(next != null, "position", "Position does not represent a valid position in this sequence."); Requires.Argument(integer >= next.Start, "position", "Position must not be earlier than current position."); for (next = first; next != sequenceSegment; next = RecycleAndGetNext(next)) { } sequenceSegment.AdvanceTo(integer); first = ((sequenceSegment.Length == 0) ? RecycleAndGetNext(sequenceSegment) : sequenceSegment); if (first == null) { last = null; } } } public void Advance(int count) { SequenceSegment? sequenceSegment = last; Verify.Operation(sequenceSegment != null, "Cannot advance before acquiring memory."); sequenceSegment.Advance(count); ConsiderMinimumSizeIncrease(); } public Memory<T> GetMemory(int sizeHint) { return GetSegment(sizeHint).RemainingMemory; } public Span<T> GetSpan(int sizeHint) { return GetSegment(sizeHint).RemainingSpan; } public void Append(ReadOnlyMemory<T> memory) { if (memory.Length > 0) { SequenceSegment sequenceSegment = ((segmentPool.Count > 0) ? segmentPool.Pop() : new SequenceSegment()); sequenceSegment.AssignForeign(memory); Append(sequenceSegment); } } [EditorBrowsable(EditorBrowsableState.Never)] public void Dispose() { Reset(); } public void Reset() { for (SequenceSegment sequenceSegment = first; sequenceSegment != null; sequenceSegment = RecycleAndGetNext(sequenceSegment)) { } first = (last = null); } private SequenceSegment GetSegment(int sizeHint) { Requires.Range(sizeHint >= 0, "sizeHint"); int? num = null; if (sizeHint == 0) { if (last == null || last.WritableBytes == 0) { num = -1; } } else if (last == null || last.WritableBytes < sizeHint) { num = Math.Max(MinimumSpanLength, sizeHint); } if (num.HasValue) { SequenceSegment sequenceSegment = ((segmentPool.Count > 0) ? segmentPool.Pop() : new SequenceSegment()); if (arrayPool != null) { sequenceSegment.Assign(arrayPool.Rent((num.Value == -1) ? DefaultLengthFromArrayPool : num.Value)); } else { sequenceSegment.Assign(memoryPool.Rent(num.Value)); } Append(sequenceSegment); } return last; } private void Append(SequenceSegment segment) { if (last == null) { first = (last = segment); return; } if (last.Length > 0) { last.SetNext(segment); } else { SequenceSegment next = first; if (first != last) { while (next.Next != last) { next = next.Next; } } else { first = segment; } next.SetNext(segment); RecycleAndGetNext(last); } last = segment; } private SequenceSegment? RecycleAndGetNext(SequenceSegment segment) { SequenceSegment? next = segment.Next; segment.ResetMemory(arrayPool); segmentPool.Push(segment); return next; } private void ConsiderMinimumSizeIncrease() { checked { if (AutoIncreaseMinimumSpanLength && MinimumSpanLength < 32768) { int num = Math.Min(32768, (int)Math.Min(2147483647L, unchecked(Length / 2))); if (MinimumSpanLength < num) { MinimumSpanLength = num; } } } } static Sequence() { checked { DefaultLengthFromArrayPool = 1 + unchecked(4095 / Unsafe.SizeOf<T>()); Empty = new ReadOnlySequence<T>(SequenceSegment.Empty, 0, SequenceSegment.Empty, 0); } } } internal static class Requires { [DebuggerStepThrough] public static void Range([DoesNotReturnIf(false)] bool condition, string parameterName, string? message = null) { if (!condition) { FailRange(parameterName, message); } } [DebuggerStepThrough] public static Exception FailRange(string parameterName, string? message = null) { if (string.IsNullOrEmpty(message)) { throw new ArgumentOutOfRangeException(parameterName); } throw new ArgumentOutOfRangeException(parameterName, message); } [DebuggerStepThrough] public static T NotNull<T>([NotNull] T value, string parameterName) where T : class { if (value == null) { throw new ArgumentNullException(parameterName); } return value; } [DebuggerStepThrough] public static void Argument([DoesNotReturnIf(false)] bool condition, string parameterName, string message) { if (!condition) { throw new ArgumentException(message, parameterName); } } [DebuggerStepThrough] public static void Argument([DoesNotReturnIf(false)] bool condition, string parameterName, string message, object arg1) { if (!condition) { throw new ArgumentException(string.Format(message, arg1), parameterName); } } [DebuggerStepThrough] public static void Argument([DoesNotReturnIf(false)] bool condition, string parameterName, string message, object arg1, object arg2) { if (!condition) { throw new ArgumentException(string.Format(message, arg1, arg2), parameterName); } } [DebuggerStepThrough] public static void Argument([DoesNotReturnIf(false)] bool condition, string parameterName, string message, params object[] args) { if (!condition) { throw new ArgumentException(string.Format(message, args), parameterName); } } } internal static class Verify { [DebuggerStepThrough] internal static void Operation([DoesNotReturnIf(false)] bool condition, string message) { if (!condition) { throw new InvalidOperationException(message); } } } } namespace MessagePack { public ref struct MessagePackReader { private SequenceReader<byte> reader; public CancellationToken CancellationToken { get; set; } public int Depth { get; set; } public ReadOnlySequence<byte> Sequence => reader.Sequence; public SequencePosition Position => reader.Position; public long Consumed => reader.Consumed; public bool End => reader.End; public bool IsNil => NextCode == 192; public MessagePackType NextMessagePackType => MessagePackCode.ToMessagePackType(NextCode); public byte NextCode { get { ThrowInsufficientBufferUnless(reader.TryPeek(out var value)); return value; } } public byte ReadByte() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return (byte)value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return (byte)value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return (byte)value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return (byte)value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (byte)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (byte)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (byte)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (byte)unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public ushort ReadUInt16() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return (ushort)value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return (ushort)value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return (ushort)value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (ushort)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (ushort)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (ushort)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (ushort)unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public uint ReadUInt32() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return (uint)value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return (uint)value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (uint)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (uint)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (uint)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (uint)unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public ulong ReadUInt64() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return (ulong)value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return (ulong)value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (ulong)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (ulong)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (ulong)unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public sbyte ReadSByte() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return (sbyte)value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return (sbyte)value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return (sbyte)value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return (sbyte)value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (sbyte)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (sbyte)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (sbyte)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return (sbyte)value; } throw ThrowInvalidCode(value); } } } public short ReadInt16() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return (short)value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return (short)value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return (short)value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (short)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (short)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public int ReadInt32() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); checked { switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return (int)value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return (int)value6; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return (int)value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return unchecked((sbyte)value); default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } } public long ReadInt64() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); switch (value) { case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value3)); return value3; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value2)); return value2; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value9)); return value9; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value8)); return value8; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value7)); return value7; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value6)); return checked((long)value6); } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value5)); return value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (sbyte)value; default: if (value >= 0 && value <= 127) { return value; } throw ThrowInvalidCode(value); } } public MessagePackReader(ReadOnlyMemory<byte> memory) { this = default(MessagePackReader); reader = new SequenceReader<byte>(memory); Depth = 0; } public MessagePackReader(in ReadOnlySequence<byte> readOnlySequence) { this = default(MessagePackReader); reader = new SequenceReader<byte>(in readOnlySequence); Depth = 0; } public MessagePackReader Clone(in ReadOnlySequence<byte> readOnlySequence) { MessagePackReader result = new MessagePackReader(in readOnlySequence); result.CancellationToken = CancellationToken; result.Depth = Depth; return result; } public MessagePackReader CreatePeekReader() { return this; } public void Skip() { ThrowInsufficientBufferUnless(TrySkip()); } internal bool TrySkip() { if (reader.Remaining == 0L) { return false; } byte nextCode = NextCode; int length; switch (nextCode) { case 192: case 194: case 195: return reader.TryAdvance(1L); case 204: case 208: return reader.TryAdvance(2L); case 205: case 209: return reader.TryAdvance(3L); case 202: case 206: case 210: return reader.TryAdvance(5L); case 203: case 207: case 211: return reader.TryAdvance(9L); case 222: case 223: return TrySkipNextMap(); case 220: case 221: return TrySkipNextArray(); case 217: case 218: case 219: if (TryGetStringLengthInBytes(out length)) { return reader.TryAdvance(length); } return false; case 196: case 197: case 198: if (TryGetBytesLength(out length)) { return reader.TryAdvance(length); } return false; case 199: case 200: case 201: case 212: case 213: case 214: case 215: case 216: { if (TryReadExtensionFormatHeader(out var extensionHeader)) { return reader.TryAdvance(extensionHeader.Length); } return false; } default: if (nextCode < 0 || nextCode > 127) { break; } goto case 224; case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return reader.TryAdvance(1L); } if (nextCode >= 128 && nextCode <= 143) { return TrySkipNextMap(); } if (nextCode >= 144 && nextCode <= 159) { return TrySkipNextArray(); } if (nextCode >= 160 && nextCode <= 191) { if (TryGetStringLengthInBytes(out length)) { return reader.TryAdvance(length); } return false; } throw ThrowInvalidCode(nextCode); } public Nil ReadNil() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); if (value != 192) { throw ThrowInvalidCode(value); } return Nil.Default; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryReadNil() { if (NextCode == 192) { reader.Advance(1L); return true; } return false; } public ReadOnlySequence<byte> ReadRaw(long length) { try { ReadOnlySequence<byte> result = reader.Sequence.Slice(reader.Position, length); reader.Advance(length); return result; } catch (ArgumentOutOfRangeException innerException) { throw ThrowNotEnoughBytesException(innerException); } } public ReadOnlySequence<byte> ReadRaw() { SequencePosition position = Position; Skip(); return Sequence.Slice(position, Position); } public int ReadArrayHeader() { ThrowInsufficientBufferUnless(TryReadArrayHeader(out var count)); ThrowInsufficientBufferUnless(reader.Remaining >= count); return count; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryReadArrayHeader(out int count) { count = -1; if (!reader.TryRead(out var value)) { return false; } switch (value) { case 220: { if (!reader.TryReadBigEndian(out short value3)) { return false; } count = (ushort)value3; break; } case 221: { if (!reader.TryReadBigEndian(out int value2)) { return false; } count = value2; break; } case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: count = value & 0xF; break; default: throw ThrowInvalidCode(value); } return true; } public int ReadMapHeader() { ThrowInsufficientBufferUnless(TryReadMapHeader(out var count)); ThrowInsufficientBufferUnless(reader.Remaining >= checked(count * 2)); return count; } public bool TryReadMapHeader(out int count) { count = -1; if (!reader.TryRead(out var value)) { return false; } switch (value) { case 222: { if (!reader.TryReadBigEndian(out short value3)) { return false; } count = (ushort)value3; break; } case 223: { if (!reader.TryReadBigEndian(out int value2)) { return false; } count = value2; break; } case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: count = checked((byte)(value & 0xF)); break; default: throw ThrowInvalidCode(value); } return true; } public bool ReadBoolean() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); return value switch { 195 => true, 194 => false, _ => throw ThrowInvalidCode(value), }; } public char ReadChar() { return (char)ReadUInt16(); } public float ReadSingle() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); switch (value) { case 202: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out float value3)); return value3; } case 203: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out double value2)); return (float)value2; } case 208: { ThrowInsufficientBufferUnless(reader.TryRead(out var value4)); return value4; } case 209: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out short value11)); return value11; } case 210: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out int value10)); return value10; } case 211: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out long value9)); return value9; } case 204: { ThrowInsufficientBufferUnless(reader.TryRead(out var value8)); return (int)value8; } case 205: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ushort value7)); return (int)value7; } case 206: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out uint value6)); return value6; } case 207: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out ulong value5)); return value5; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (sbyte)value; default: if (value >= 0 && value <= 127) { return (int)value; } throw ThrowInvalidCode(value); } } public double ReadDouble() { ThrowInsufficientBufferUnless(reader.TryRead(out var value)); byte value4; short value7; int value6; long value5; switch (value) { case 203: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out double value3)); return value3; } case 202: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out float value2)); return value2; } case 208: ThrowInsufficientBufferUnless(reader.TryRead(out value4)); return (sbyte)value4; case 209: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value7)); return value7; case 210: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value6)); return value6; case 211: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value5)); return value5; case 204: ThrowInsufficientBufferUnless(reader.TryRead(out value4)); return (int)value4; case 205: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value7)); return (int)(ushort)value7; case 206: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value6)); return (uint)value6; case 207: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value5)); return (ulong)value5; case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case byte.MaxValue: return (sbyte)value; default: if (value >= 0 && value <= 127) { return (int)value; } throw ThrowInvalidCode(value); } } public DateTime ReadDateTime() { return ReadDateTime(ReadExtensionFormatHeader()); } public DateTime ReadDateTime(ExtensionHeader header) { if (header.TypeCode != -1) { throw new MessagePackSerializationException($"Extension TypeCode is invalid. typeCode: {header.TypeCode}"); } int value; long value2; switch (header.Length) { case 4u: ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value)); return DateTimeConstants.UnixEpoch.AddSeconds((uint)value); case 8u: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value2)); long num2 = value2; long num; checked { num = (long)(unchecked((ulong)num2) >> 34); } ulong num3 = (ulong)num2 & 0x3FFFFFFFFuL; return DateTimeConstants.UnixEpoch.AddSeconds(num3).AddTicks(num / 100); } case 12u: { ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value)); long num = (uint)value; ThrowInsufficientBufferUnless(reader.TryReadBigEndian(out value2)); return DateTimeConstants.UnixEpoch.AddSeconds(value2).AddTicks(num / 100); } default: throw new MessagePackSerializationException($"Length of extension was {header.Length}. Either 4 or 8 were expected."); } } public ReadOnlySequence<byte>? ReadBytes() { if (TryReadNil()) { return null; } int bytesLength = GetBytesLength(); ThrowInsufficientBufferUnless(reader.Remaining >= bytesLength); ReadOnlySequence<byte> value = reader.Sequence.Slice(reader.Position, bytesLength); reader.Advance(bytesLength); return value; } public ReadOnlySequence<byte>? ReadStringSequence() { if (TryReadNil()) { return null; } int stringLengthInBytes = GetStringLengthInBytes(); ThrowInsufficientBufferUnless(reader.Remaining >= stringLengthInBytes); ReadOnlySequence<byte> value = reader.Sequence.Slice(reader.Position, stringLengthInBytes); reader.Advance(stringLengthInBytes); return value; } public bool TryReadStringSpan(out ReadOnlySpan<byte> span) { if (IsNil) { span = default(ReadOnlySpan<byte>); return false; } long consumed = reader.Consumed; int stringLengthInBytes = GetStringLengthInBytes(); ThrowInsufficientBufferUnless(reader.Remaining >= stringLengthInBytes); checked { int num = reader.CurrentSpanIndex + stringLengthInBytes; ReadOnlySpan<byte> currentSpan = reader.CurrentSpan; if (num <= currentSpan.Length) { currentSpan = reader.CurrentSpan; span = currentSpan.Slice(reader.CurrentSpanIndex, stringLengthInBytes); reader.Advance(stringLengthInBytes); return true; } reader.Rewind(reader.Consumed - consumed); span = default(ReadOnlySpan<byte>); return false; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string? ReadString() { if (TryReadNil()) { return null; } int stringLengthInBytes = GetStringLengthInBytes(); ReadOnlySpan<byte> unreadSpan = reader.UnreadSpan; if (unreadSpan.Length >= stringLengthInBytes) { string @string = StringEncoding.UTF8.GetString(unreadSpan.Slice(0, stringLengthInBytes)); reader.Advance(stringLengthInBytes); return @string; } return ReadStringSlow(stringLengthInBytes); } public ExtensionHeader ReadExtensionFormatHeader() { ThrowInsufficientBufferUnless(TryReadExtensionFormatHeader(out var extensionHeader)); ThrowInsufficientBufferUnless(reader.Remaining >= extensionHeader.Length); return extensionHeader; } public bool TryReadExtensionFormatHeader(out ExtensionHeader extensionHeader) { extensionHeader = default(ExtensionHeader); if (!reader.TryRead(out var value)) { return false; } uint length; switch (value) { case 212: length = 1u; break; case 213: length = 2u; break; case 214: length = 4u; break; case 215: length = 8u; break; case 216: length = 16u; break; case 199: { if (!reader.TryRead(out var value4)) { return false; } length = value4; break; } case 200: { if (!reader.TryReadBigEndian(out short value3)) { return false; } length = (ushort)value3; break; } case 201: { if (!reader.TryReadBigEndian(out int value2)) { return false; } length = (uint)value2; break; } default: throw ThrowInvalidCode(value); } if (!reader.TryRead(out var value5)) { return false; } extensionHeader = new ExtensionHeader((sbyte)value5, length); return true; } public ExtensionResult ReadExtensionFormat() { ExtensionHeader extensionHeader = ReadExtensionFormatHeader(); try { ReadOnlySequence<byte> data = reader.Sequence.Slice(reader.Position, extensionHeader.Length); reader.Advance(extensionHeader.Length); return new ExtensionResult(extensionHeader.TypeCode, data); } catch (ArgumentOutOfRangeException innerException) { throw ThrowNotEnoughBytesException(innerException); } } private static EndOfStreamException ThrowNotEnoughBytesException() { throw new EndOfStreamException(); } private static EndOfStreamException ThrowNotEnoughBytesException(Exception innerException) { throw new EndOfStreamException(new EndOfStreamException().Message, innerException); } [DoesNotReturn] private static Exception ThrowInvalidCode(byte code) { throw new MessagePackSerializationException($"Unexpected msgpack code {code} ({MessagePackCode.ToFormatName(code)}) encountered."); } private static void ThrowInsufficientBufferUnless(bool condition) { if (!condition) { ThrowNotEnoughBytesException(); } } private int GetBytesLength() { ThrowInsufficientBufferUnless(TryGetBytesLength(out var length)); return length; } private bool TryGetBytesLength(out int length) { if (!reader.TryRead(out var value)) { length = 0; return false; } switch (value) { case 196: { if (reader.TryRead(out var value2)) { length = value2; return true; } break; } case 197: case 218: { if (reader.TryReadBigEndian(out short value3)) { length = (ushort)value3; return true; } break; } case 198: case 219: if (reader.TryReadBigEndian(out length)) { return true; } break; case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: length = value & 0x1F; return true; default: throw ThrowInvalidCode(value); } length = 0; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool TryGetStringLengthInBytes(out int length) { if (!reader.TryRead(out var value)) { length = 0; return false; } if (value >= 160 && value <= 191) { length = value & 0x1F; return true; } return TryGetStringLengthInBytesSlow(value, out length); } private int GetStringLengthInBytes() { ThrowInsufficientBufferUnless(TryGetStringLengthInBytes(out var length)); return length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool TryGetStringLengthInBytesSlow(byte code, out int length) { switch (code) { case 217: { if (reader.TryRead(out var value2)) { length = value2; return true; } break; } case 218: { if (reader.TryReadBigEndian(out short value3)) { length = (ushort)value3; return true; } break; } case 219: { if (reader.TryReadBigEndian(out int value)) { length = value; return true; } break; } case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: length = code & 0x1F; return true; default: throw ThrowInvalidCode(code); } length = 0; return false; } private string ReadStringSlow(int byteLength) { ThrowInsufficientBufferUnless(reader.Remaining >= byteLength); int maxCharCount = StringEncoding.UTF8.GetMaxCharCount(byteLength); char[] array = ArrayPool<char>.Shared.Rent(maxCharCount); Decoder decoder = StringEncoding.UTF8.GetDecoder(); int num = byteLength; int num2 = 0; checked { while (num > 0) { int num3 = Math.Min(num, reader.UnreadSpan.Length); num -= num3; bool flush = num == 0; num2 += decoder.GetChars(reader.UnreadSpan.Slice(0, num3), array.AsSpan(num2), flush); reader.Advance(num3); } string result = new string(array, 0, num2); ArrayPool<char>.Shared.Return(array); return result; } } private bool TrySkipNextArray() { if (TryReadArrayHeader(out var count)) { return TrySkip(count); } return false; } private bool TrySkipNextMap() { if (TryReadMapHeader(out var count)) { return TrySkip(checked(count * 2)); } return false; } private bool TrySkip(int count) { for (int i = 0; i < count; i = checked(i + 1)) { if (!TrySkip()) { return false; } } return true; } } public static class MessagePackSerializer { public static class Typeless { public static MessagePackSerializerOptions DefaultOptions { get; set; } = TypelessContractlessStandardResolver.Options; public static void Serialize(ref MessagePackWriter writer, object? obj, MessagePackSerializerOptions? options = null) { MessagePackSerializer.Serialize(ref writer, obj, options ?? DefaultOptions); } public static void Serialize(IBufferWriter<byte> writer, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackSerializer.Serialize(writer, obj, options ?? DefaultOptions, cancellationToken); } public static byte[] Serialize(object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return MessagePackSerializer.Serialize(obj, options ?? DefaultOptions, cancellationToken); } public static void Serialize(Stream stream, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackSerializer.Serialize(stream, obj, options ?? DefaultOptions, cancellationToken); } public static Task SerializeAsync(Stream stream, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return MessagePackSerializer.SerializeAsync(stream, obj, options ?? DefaultOptions, cancellationToken); } public static object? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions? options = null) { return Deserialize<object>(ref reader, options ?? DefaultOptions); } public static object? Deserialize(in ReadOnlySequence<byte> byteSequence, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return Deserialize<object>(in byteSequence, options ?? DefaultOptions, cancellationToken); } public static object? Deserialize(Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return Deserialize<object>(stream, options ?? DefaultOptions, cancellationToken); } public static object? Deserialize(Memory<byte> bytes, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return Deserialize<object>(bytes, options ?? DefaultOptions, cancellationToken); } public static ValueTask<object?> DeserializeAsync(Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return DeserializeAsync<object>(stream, options ?? DefaultOptions, cancellationToken); } } private delegate int LZ4Transform(ReadOnlySpan<byte> input, Span<byte> output); private static class PrimitiveChecker<T> { public static readonly bool IsMessagePackFixedSizePrimitive; static PrimitiveChecker() { IsMessagePackFixedSizePrimitive = IsMessagePackFixedSizePrimitiveTypeHelper(typeof(T)); } } private class CompiledMethods { internal delegate void MessagePackWriterSerialize(ref MessagePackWriter writer, object? value, MessagePackSerializerOptions? options); internal delegate object? MessagePackReaderDeserialize(ref MessagePackReader reader, MessagePackSerializerOptions? options); private const bool PreferInterpretation = false; internal readonly Func<object?, MessagePackSerializerOptions?, CancellationToken, byte[]> Serialize_T_Options; internal readonly Action<Stream, object?, MessagePackSerializerOptions?, CancellationToken> Serialize_Stream_T_Options_CancellationToken; internal readonly Func<Stream, object?, MessagePackSerializerOptions?, CancellationToken, Task> SerializeAsync_Stream_T_Options_CancellationToken; internal readonly MessagePackWriterSerialize Serialize_MessagePackWriter_T_Options; internal readonly Action<IBufferWriter<byte>, object?, MessagePackSerializerOptions?, CancellationToken> Serialize_IBufferWriter_T_Options_CancellationToken; internal readonly MessagePackReaderDeserialize Deserialize_MessagePackReader_Options; internal readonly Func<Stream, MessagePackSerializerOptions?, CancellationToken, object?> Deserialize_Stream_Options_CancellationToken; internal readonly Func<Stream, MessagePackSerializerOptions?, CancellationToken, ValueTask<object?>> DeserializeAsync_Stream_Options_CancellationToken; internal readonly Func<ReadOnlyMemory<byte>, MessagePackSerializerOptions?, CancellationToken, object?> Deserialize_ReadOnlyMemory_Options; internal readonly Func<ReadOnlySequence<byte>, MessagePackSerializerOptions?, CancellationToken, object?> Deserialize_ReadOnlySequence_Options_CancellationToken; internal CompiledMethods(Type type) { TypeInfo typeInfo = type.GetTypeInfo(); MethodInfo method = GetMethod("Serialize", type, new Type[3] { null, typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "obj"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Serialize_T_Options = Expression.Lambda<Func<object, MessagePackSerializerOptions, CancellationToken, byte[]>>(Expression.Call(null, method, typeInfo.IsValueType ? Expression.Unbox(parameterExpression, type) : Expression.Convert(parameterExpression, type), parameterExpression2, parameterExpression3), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(preferInterpretation: false); MethodInfo method2 = GetMethod("Serialize", type, new Type[4] { typeof(Stream), null, typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression4 = Expression.Parameter(typeof(Stream), "stream"); ParameterExpression parameterExpression5 = Expression.Parameter(typeof(object), "obj"); ParameterExpression parameterExpression6 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression7 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Action<Stream, object, MessagePackSerializerOptions, CancellationToken> serialize_Stream_T_Options_CancellationToken = Expression.Lambda<Action<Stream, object, MessagePackSerializerOptions, CancellationToken>>(Expression.Call(null, method2, parameterExpression4, typeInfo.IsValueType ? Expression.Unbox(parameterExpression5, type) : Expression.Convert(parameterExpression5, type), parameterExpression6, parameterExpression7), new ParameterExpression[4] { parameterExpression4, parameterExpression5, parameterExpression6, parameterExpression7 }).Compile(preferInterpretation: false); Serialize_Stream_T_Options_CancellationToken = serialize_Stream_T_Options_CancellationToken; MethodInfo method3 = GetMethod("SerializeAsync", type, new Type[4] { typeof(Stream), null, typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression8 = Expression.Parameter(typeof(Stream), "stream"); ParameterExpression parameterExpression9 = Expression.Parameter(typeof(object), "obj"); ParameterExpression parameterExpression10 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression11 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Func<Stream, object, MessagePackSerializerOptions, CancellationToken, Task> serializeAsync_Stream_T_Options_CancellationToken = Expression.Lambda<Func<Stream, object, MessagePackSerializerOptions, CancellationToken, Task>>(Expression.Call(null, method3, parameterExpression8, typeInfo.IsValueType ? Expression.Unbox(parameterExpression9, type) : Expression.Convert(parameterExpression9, type), parameterExpression10, parameterExpression11), new ParameterExpression[4] { parameterExpression8, parameterExpression9, parameterExpression10, parameterExpression11 }).Compile(preferInterpretation: false); SerializeAsync_Stream_T_Options_CancellationToken = serializeAsync_Stream_T_Options_CancellationToken; MethodInfo method4 = GetMethod("Serialize", type, new Type[4] { typeof(IBufferWriter<byte>), null, typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression12 = Expression.Parameter(typeof(IBufferWriter<byte>), "writer"); ParameterExpression parameterExpression13 = Expression.Parameter(typeof(object), "obj"); ParameterExpression parameterExpression14 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression15 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Action<IBufferWriter<byte>, object, MessagePackSerializerOptions, CancellationToken> serialize_IBufferWriter_T_Options_CancellationToken = Expression.Lambda<Action<IBufferWriter<byte>, object, MessagePackSerializerOptions, CancellationToken>>(Expression.Call(null, method4, parameterExpression12, typeInfo.IsValueType ? Expression.Unbox(parameterExpression13, type) : Expression.Convert(parameterExpression13, type), parameterExpression14, parameterExpression15), new ParameterExpression[4] { parameterExpression12, parameterExpression13, parameterExpression14, parameterExpression15 }).Compile(preferInterpretation: false); Serialize_IBufferWriter_T_Options_CancellationToken = serialize_IBufferWriter_T_Options_CancellationToken; MethodInfo method5 = GetMethod("SerializeSemiGeneric", type, new Type[3] { typeof(MessagePackWriter).MakeByRefType(), typeof(object), typeof(MessagePackSerializerOptions) }); Serialize_MessagePackWriter_T_Options = (MessagePackWriterSerialize)method5.CreateDelegate(typeof(MessagePackWriterSerialize)); MethodInfo method6 = GetMethod("DeserializeSemiGeneric", type, new Type[2] { typeof(MessagePackReader).MakeByRefType(), typeof(MessagePackSerializerOptions) }); Deserialize_MessagePackReader_Options = (MessagePackReaderDeserialize)method6.CreateDelegate(typeof(MessagePackReaderDeserialize)); MethodInfo method7 = GetMethod("Deserialize", type, new Type[3] { typeof(Stream), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression16 = Expression.Parameter(typeof(Stream), "stream"); ParameterExpression parameterExpression17 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression18 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Func<Stream, MessagePackSerializerOptions, CancellationToken, object> deserialize_Stream_Options_CancellationToken = Expression.Lambda<Func<Stream, MessagePackSerializerOptions, CancellationToken, object>>(Expression.Convert(Expression.Call(null, method7, parameterExpression16, parameterExpression17, parameterExpression18), typeof(object)), new ParameterExpression[3] { parameterExpression16, parameterExpression17, parameterExpression18 }).Compile(preferInterpretation: false); Deserialize_Stream_Options_CancellationToken = deserialize_Stream_Options_CancellationToken; MethodInfo method8 = GetMethod("DeserializeObjectAsync", type, new Type[3] { typeof(Stream), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression19 = Expression.Parameter(typeof(Stream), "stream"); ParameterExpression parameterExpression20 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression21 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Func<Stream, MessagePackSerializerOptions, CancellationToken, ValueTask<object>> deserializeAsync_Stream_Options_CancellationToken = Expression.Lambda<Func<Stream, MessagePackSerializerOptions, CancellationToken, ValueTask<object>>>(Expression.Convert(Expression.Call(null, method8, parameterExpression19, parameterExpression20, parameterExpression21), typeof(ValueTask<object>)), new ParameterExpression[3] { parameterExpression19, parameterExpression20, parameterExpression21 }).Compile(preferInterpretation: false); DeserializeAsync_Stream_Options_CancellationToken = deserializeAsync_Stream_Options_CancellationToken; MethodInfo method9 = GetMethod("Deserialize", type, new Type[3] { typeof(ReadOnlyMemory<byte>), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression22 = Expression.Parameter(typeof(ReadOnlyMemory<byte>), "bytes"); ParameterExpression parameterExpression23 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression24 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Func<ReadOnlyMemory<byte>, MessagePackSerializerOptions, CancellationToken, object> deserialize_ReadOnlyMemory_Options = Expression.Lambda<Func<ReadOnlyMemory<byte>, MessagePackSerializerOptions, CancellationToken, object>>(Expression.Convert(Expression.Call(null, method9, parameterExpression22, parameterExpression23, parameterExpression24), typeof(object)), new ParameterExpression[3] { parameterExpression22, parameterExpression23, parameterExpression24 }).Compile(preferInterpretation: false); Deserialize_ReadOnlyMemory_Options = deserialize_ReadOnlyMemory_Options; MethodInfo method10 = GetMethod("Deserialize", type, new Type[3] { typeof(ReadOnlySequence<byte>).MakeByRefType(), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); ParameterExpression parameterExpression25 = Expression.Parameter(typeof(ReadOnlySequence<byte>), "bytes"); ParameterExpression parameterExpression26 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options"); ParameterExpression parameterExpression27 = Expression.Parameter(typeof(CancellationToken), "cancellationToken"); Func<ReadOnlySequence<byte>, MessagePackSerializerOptions, CancellationToken, object> deserialize_ReadOnlySequence_Options_CancellationToken = Expression.Lambda<Func<ReadOnlySequence<byte>, MessagePackSerializerOptions, CancellationToken, object>>(Expression.Convert(Expression.Call(null, method10, parameterExpression25, parameterExpression26, parameterExpression27), typeof(object)), new ParameterExpression[3] { parameterExpression25, parameterExpression26, parameterExpression27 }).Compile(preferInterpretation: false); Deserialize_ReadOnlySequence_Options_CancellationToken = deserialize_ReadOnlySequence_Options_CancellationToken; } private static void ThrowRefStructNotSupported() { throw new NotSupportedException("MessagePackWriter/Reader overload is not supported in MessagePackSerializer.NonGenerics."); } private static MethodInfo GetMethod(string methodName, Type type, Type?[] parameters) { string methodName2 = methodName; Type?[] parameters2 = parameters; return typeof(MessagePackSerializer).GetRuntimeMethods().Single(delegate(MethodInfo x) { if (methodName2 != x.Name) { return false; } ParameterInfo[] parameters3 = x.GetParameters(); if (parameters3.Length != parameters2.Length) { return false; } for (int i = 0; i < parameters3.Length; i = checked(i + 1)) { if ((!(parameters2[i] == null) || !parameters3[i].ParameterType.IsGenericParameter) && parameters3[i].ParameterType != parameters2[i]) { return false; } } return true; }).MakeGenericMethod(type); } } private static MessagePackSerializerOptions? defaultOptions; [ThreadStatic] private static byte[]? scratchArray; private static readonly LZ4Transform LZ4CodecEncode; private static readonly LZ4Transform LZ4CodecDecode; private static readonly Func<Type, CompiledMethods> CreateCompiledMethods; private static readonly ThreadsafeTypeKeyHashTable<CompiledMethods> Serializes; public static MessagePackSerializerOptions DefaultOptions { get { return defaultOptions ?? (defaultOptions = MessagePackSerializerOptions.Standard); } set { defaultOptions = value; } } public static void Serialize<T>(IBufferWriter<byte> writer, T value, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackWriter messagePackWriter = new MessagePackWriter(writer); messagePackWriter.CancellationToken = cancellationToken; MessagePackWriter writer2 = messagePackWriter; Serialize(ref writer2, value, options); writer2.Flush(); } public static void Serialize<T>(ref MessagePackWriter writer, T value, MessagePackSerializerOptions? options = null) { options = options ?? DefaultOptions; bool oldSpec = writer.OldSpec; if (options.OldSpec.HasValue) { writer.OldSpec = options.OldSpec.Value; } try { if (options.Compression.IsCompression() && !PrimitiveChecker<T>.IsMessagePackFixedSizePrimitive) { using (SequencePool.Rental rental = options.SequencePool.Rent()) { Sequence<byte> value2 = rental.Value; MessagePackWriter writer2 = writer.Clone(value2); options.Resolver.GetFormatterWithVerify<T>().Serialize(ref writer2, value, options); writer2.Flush(); ReadOnlySequence<byte> msgpackUncompressedData = value2; ToLZ4BinaryCore(in msgpackUncompressedData, ref writer, options.Compression, options.CompressionMinLength); return; } } options.Resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, options); } catch (Exception inner) { throw new MessagePackSerializationException("Failed to serialize " + typeof(T).FullName + " value.", inner); } finally { writer.OldSpec = oldSpec; } } public static byte[] Serialize<T>(T value, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { byte[] array = scratchArray; if (array == null) { array = (scratchArray = new byte[65536]); } options = options ?? DefaultOptions; MessagePackWriter messagePackWriter = new MessagePackWriter(options.SequencePool, array); messagePackWriter.CancellationToken = cancellationToken; MessagePackWriter writer = messagePackWriter; Serialize(ref writer, value, options); return writer.FlushAndGetArray(); } public static void Serialize<T>(Stream stream, T value, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? DefaultOptions; cancellationToken.ThrowIfCancellationRequested(); using SequencePool.Rental rental = options.SequencePool.Rent(); Serialize(rental.Value, value, options, cancellationToken); try { ReadOnlySequence<byte>.Enumerator enumerator = rental.Value.AsReadOnlySequence.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlyMemory<byte> current = enumerator.Current; cancellationToken.ThrowIfCancellationRequested(); stream.Write(current.Span); } } catch (Exception inner) { throw new MessagePackSerializationException("Error occurred while writing the serialized data to the stream.", inner); } } public static async Task SerializeAsync<T>(Stream stream, T value, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? DefaultOptions; cancellationToken.ThrowIfCancellationRequested(); using SequencePool.Rental sequenceRental = options.SequencePool.Rent(); Serialize(sequenceRental.Value, value, options, cancellationToken); try { ReadOnlySequence<byte>.Enumerator enumerator = sequenceRental.Value.AsReadOnlySequence.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlyMemory<byte> current = enumerator.Current; cancellationToken.ThrowIfCancellationRequested(); await stream.WriteAsync(current, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } catch (Exception inner) { throw new MessagePackSerializationException("Error occurred while writing the serialized data to the stream.", inner); } } public static T Deserialize<T>(in ReadOnlySequence<byte> byteSequence, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackReader messagePackReader = new MessagePackReader(in byteSequence); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; return Deserialize<T>(ref reader, options); } public static T Deserialize<T>(ref MessagePackReader reader, MessagePackSerializerOptions? options = null) { options = options ?? DefaultOptions; try { if (options.Compression.IsCompression()) { using (SequencePool.Rental rental = options.SequencePool.Rent()) { Sequence<byte> value = rental.Value; if (TryDecompress(ref reader, value)) { ReadOnlySequence<byte> readOnlySequence = value.AsReadOnlySequence; MessagePackReader reader2 = reader.Clone(in readOnlySequence); return options.Resolver.GetFormatterWithVerify<T>().Deserialize(ref reader2, options); } return options.Resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options); } } return options.Resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options); } catch (Exception inner) { throw new MessagePackSerializationException("Failed to deserialize " + typeof(T).FullName + " value.", inner); } } public static T Deserialize<T>(ReadOnlyMemory<byte> buffer, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackReader messagePackReader = new MessagePackReader(buffer); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; return Deserialize<T>(ref reader, options); } public static T Deserialize<T>(ReadOnlyMemory<byte> buffer, out int bytesRead, CancellationToken cancellationToken = default(CancellationToken)) { return Deserialize<T>(buffer, null, out bytesRead, cancellationToken); } public static T Deserialize<T>(ReadOnlyMemory<byte> buffer, MessagePackSerializerOptions? options, out int bytesRead, CancellationToken cancellationToken = default(CancellationToken)) { MessagePackReader messagePackReader = new MessagePackReader(buffer); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; T result = Deserialize<T>(ref reader, options); bytesRead = buffer.Slice(0, checked((int)reader.Consumed)).Length; return result; } public static T Deserialize<T>(Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? DefaultOptions; if (TryDeserializeFromMemoryStream<T>(stream, options, cancellationToken, out var result)) { return result; } using SequencePool.Rental rental = options.SequencePool.Rent(); Sequence<byte> value = rental.Value; try { int num; do { cancellationToken.ThrowIfCancellationRequested(); Span<byte> span = value.GetSpan(stream.CanSeek ? checked((int)Math.Min(options.SuggestedContiguousMemorySize, stream.Length - stream.Position)) : 0); num = stream.Read(span); value.Advance(num); } while (num > 0); } catch (Exception inner) { throw new MessagePackSerializationException("Error occurred while reading from the stream.", inner); } return DeserializeFromSequenceAndRewindStreamIfPossible<T>(stream, options, value, cancellationToken); } public static async ValueTask<T> DeserializeAsync<T>(Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { if (options == null) { options = DefaultOptions; } if (TryDeserializeFromMemoryStream<T>(stream, options, cancellationToken, out var result)) { return result; } using SequencePool.Rental sequenceRental = options.SequencePool.Rent(); Sequence<byte> sequence = sequenceRental.Value; try { int num; do { Memory<byte> memory = sequence.GetMemory(stream.CanSeek ? checked((int)Math.Min(options.SuggestedContiguousMemorySize, stream.Length - stream.Position)) : 0); num = await stream.ReadAsync(memory, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); sequence.Advance(num); } while (num > 0); } catch (Exception inner) { throw new MessagePackSerializationException("Error occurred while reading from the stream.", inner); } return DeserializeFromSequenceAndRewindStreamIfPossible<T>(stream, options, sequence, cancellationToken); } private static bool TryDeserializeFromMemoryStream<T>(Stream stream, MessagePackSerializerOptions options, CancellationToken cancellationToken, [MaybeNullWhen(false)] out T result) { cancellationToken.ThrowIfCancellationRequested(); if (stream is MemoryStream memoryStream && memoryStream.TryGetBuffer(out var buffer)) { result = Deserialize<T>(buffer.AsMemory(checked((int)memoryStream.Position)), options, out var bytesRead, cancellationToken); memoryStream.Seek(bytesRead, SeekOrigin.Current); return true; } result = default(T); return false; } private static T DeserializeFromSequenceAndRewindStreamIfPossible<T>(Stream streamToRewind, MessagePackSerializerOptions? options, ReadOnlySequence<byte> sequence, CancellationToken cancellationToken) { if (streamToRewind == null) { throw new ArgumentNullException("streamToRewind"); } MessagePackReader messagePackReader = new MessagePackReader(in sequence); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; T result = Deserialize<T>(ref reader, options); checked { if (streamToRewind.CanSeek && !reader.End) { int num = (int)reader.Sequence.Slice(reader.Position).Length; streamToRewind.Seek(-num, SeekOrigin.Current); } return result; } } private static int LZ4Operation(in ReadOnlySequence<byte> input, Span<byte> output, LZ4Transform lz4Operation) { byte[] array = null; checked { ReadOnlySpan<byte> input2; if (input.IsSingleSegment) { input2 = input.First.Span; } else { array = ArrayPool<byte>.Shared.Rent((int)input.Length); BuffersExtensions.CopyTo(in input, array); input2 = array.AsSpan(0, (int)input.Length); } try { return lz4Operation(input2, output); } finally { if (array != null) { ArrayPool<byte>.Shared.Return(array); } } } } private static bool TryDecompress(ref MessagePackReader reader, IBufferWriter<byte> writer) { checked { if (!reader.End) { Span<byte> span; if (reader.NextMessagePackType == MessagePackType.Extension && reader.CreatePeekReader().ReadExtensionFormatHeader().TypeCode == 99) { ReadOnlySequence<byte> readOnlySequence = reader.ReadExtensionFormat().Data; MessagePackReader messagePackReader = new MessagePackReader(in readOnlySequence); int num = messagePackReader.ReadInt32(); readOnlySequence = messagePackReader.Sequence; ReadOnlySequence<byte> input = readOnlySequence.Slice(messagePackReader.Position); span = writer.GetSpan(num); Span<byte> output = span.Slice(0, num); int count = LZ4Operation(in input, output, LZ4CodecDecode); writer.Advance(count); return true; } if (reader.NextMessagePackType == MessagePackType.Array) { MessagePackReader messagePackReader2 = reader.CreatePeekReader(); int num2 = messagePackReader2.ReadArrayHeader(); if (num2 != 0 && messagePackReader2.NextMessagePackType == MessagePackType.Extension && messagePackReader2.ReadExtensionFormatHeader().TypeCode == 98) { reader = messagePackReader2; int num3 = num2 - 1; int[] array = ArrayPool<int>.Shared.Rent(num3); try { for (int i = 0; i < num3; i++) { array[i] = reader.ReadInt32(); } for (int j = 0; j < num3; j++) { int num4 = array[j]; ReadOnlySequence<byte> input2 = reader.ReadBytes() ?? throw MessagePackSerializationException.ThrowUnexpectedNilWhileDeserializing<ReadOnlySequence<byte>>(); span = writer.GetSpan(num4); Span<byte> output2 = span.Slice(0, num4); int count2 = LZ4Operation(in input2, output2, LZ4CodecDecode); writer.Advance(count2); } return true; } finally { ArrayPool<int>.Shared.Return(array); } } } } return false; } } private static void ToLZ4BinaryCore(in ReadOnlySequence<byte> msgpackUncompressedData, ref MessagePackWriter writer, MessagePackCompression compression, int minCompressionSize) { if (msgpackUncompressedData.Length < minCompressionSize) { writer.WriteRaw(in msgpackUncompressedData); return; } checked { switch (compression) { case MessagePackCompression.Lz4Block: { int minimumLength = LZ4Codec.MaximumOutputLength((int)msgpackUncompressedData.Length); byte[] array = ArrayPool<byte>.Shared.Rent(minimumLength); try { int num5 = LZ4Operation(in msgpackUncompressedData, array, LZ4CodecEncode); writer.WriteExtensionFormatHeader(new ExtensionHeader(99, 5 + (uint)num5)); writer.WriteInt32((int)msgpackUncompressedData.Length); writer.WriteRaw(array.AsSpan(0, num5)); break; } finally { ArrayPool<byte>.Shared.Return(array); } } case MessagePackCompression.Lz4BlockArray: { int num = 0; int num2 = 0; ReadOnlySequence<byte>.Enumerator enumerator = msgpackUncompressedData.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlyMemory<byte> current = enumerator.Current; num++; num2 += GetUInt32WriteSize((uint)current.Length); } writer.WriteArrayHeader(num + 1); writer.WriteExtensionFormatHeader(new ExtensionHeader(98, num2)); enumerator = msgpackUncompressedData.GetEnumerator(); while (enumerator.MoveNext()) { writer.Write(enumerator.Current.Length); } enumerator = msgpackUncompressedData.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlyMemory<byte> current2 = enumerator.Current; int num3 = LZ4Codec.MaximumOutputLength(current2.Length); Span<byte> span = writer.GetSpan(num3 + 5); int num4 = LZ4Codec.Encode(current2.Span, span.Slice(5, span.Length - 5)); WriteBin32Header((uint)num4, span); writer.Advance(num4 + 5); } break; } default: throw new ArgumentException("Invalid MessagePackCompression Code. Code:" + compression); } } } private static int GetUInt32WriteSize(uint value) { if (value <= 127) { return 1; } if (value <= 255) { return 2; } if (value <= 65535) { return 3; } return 5; } private static void WriteBin32Header(uint value, Span<byte> span) { span[0] = 198; span[4] = (byte)value; span[3] = (byte)(value >> 8); span[2] = (byte)(value >> 16); span[1] = (byte)(value >> 24); } private static bool IsMessagePackFixedSizePrimitiveTypeHelper(Type type) { if (!(type == typeof(short)) && !(type == typeof(int)) && !(type == typeof(long)) && !(type == typeof(ushort)) && !(type == typeof(uint)) && !(type == typeof(ulong)) && !(type == typeof(float)) && !(type == typeof(double)) && !(type == typeof(bool)) && !(type == typeof(byte)) && !(type == typeof(sbyte))) { return type == typeof(char); } return true; } public static void SerializeToJson<T>(TextWriter textWriter, T obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? DefaultOptions; using SequencePool.Rental rental = options.SequencePool.Rent(); MessagePackWriter messagePackWriter = new MessagePackWriter(rental.Value); messagePackWriter.CancellationToken = cancellationToken; MessagePackWriter writer = messagePackWriter; Serialize(ref writer, obj, options); writer.Flush(); ReadOnlySequence<byte> readOnlySequence = rental.Value; MessagePackReader messagePackReader = new MessagePackReader(in readOnlySequence); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; ConvertToJson(ref reader, textWriter, options); } public static string SerializeToJson<T>(T obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { StringWriter stringWriter = new StringWriter(); SerializeToJson(stringWriter, obj, options, cancellationToken); return stringWriter.ToString(); } public static string ConvertToJson(ReadOnlyMemory<byte> bytes, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { ReadOnlySequence<byte> bytes2 = new ReadOnlySequence<byte>(bytes); return ConvertToJson(in bytes2, options, cancellationToken); } public static string ConvertToJson(in ReadOnlySequence<byte> bytes, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { StringWriter stringWriter = new StringWriter(); MessagePackReader messagePackReader = new MessagePackReader(in bytes); messagePackReader.CancellationToken = cancellationToken; MessagePackReader reader = messagePackReader; ConvertToJson(ref reader, stringWriter, options); return stringWriter.ToString(); } public static void ConvertToJson(ref MessagePackReader reader, TextWriter jsonWriter, MessagePackSerializerOptions? options = null) { if (reader.End) { return; } options = options ?? DefaultOptions; try { if (options.Compression.IsCompression()) { using (SequencePool.Rental rental = options.SequencePool.Rent()) { if (TryDecompress(ref reader, rental.Value)) { ReadOnlySequence<byte> readOnlySequence = rental.Value; MessagePackReader messagePackReader = new MessagePackReader(in readOnlySequence); messagePackReader.CancellationToken = reader.CancellationToken; MessagePackReader reader2 = messagePackReader; if (!reader2.End) { ToJsonCore(ref reader2, jsonWriter, options); } } else { ToJsonCore(ref reader, jsonWriter, options); } return; } } ToJsonCore(ref reader, jsonWriter, options); } catch (Exception inner) { throw new MessagePackSerializationException("Error occurred while translating msgpack to JSON.", inner); } } public static void ConvertFromJson(string str, ref MessagePackWriter writer, MessagePackSerializerOptions? options = null) { using StringReader reader = new StringReader(str); ConvertFromJson(reader, ref writer, options); } public static byte[] ConvertFromJson(string str, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? DefaultOptions; using SequencePool.Rental rental = options.SequencePool.Rent(); MessagePackWriter messagePackWriter = new MessagePackWriter(rental.Value); messagePackWriter.CancellationToken = cancellationToken; MessagePackWriter writer = messagePackWriter; using (StringReader reader = new StringReader(str)) { ConvertFromJson(reader, ref writer, options); } writer.Flush(); ReadOnlySequence<byte> sequence = rental.Value.AsReadOnlySequence; return BuffersExtensions.ToArray(in sequence); } public static void ConvertFromJson(TextReader reader, ref MessagePackWriter writer, MessagePackSerializerOptions? options = null) { options = options ?? DefaultOptions; if (options.Compression.IsCompression()) { using (SequencePool.Rental rental = options.SequencePool.Rent()) { MessagePackWriter writer2 = writer.Clone(rental.Value); using (TinyJsonReader jr = new TinyJsonReader(reader, disposeInnerReader: false)) { FromJsonCore(jr, ref writer2, options); } writer2.Flush(); ReadOnlySequence<byte> msgpackUncompressedData = rental.Value; ToLZ4BinaryCore(in msgpackUncompressedData, ref writer, options.Compression, options.CompressionMinLength); return; } } using TinyJsonReader jr2 = new TinyJsonReader(reader, disposeInnerReader: false); FromJsonCore(jr2, ref writer, options); } private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer, MessagePackSerializerOptions options) { uint num = 0u; checked { while (jr.Read()) { switch (jr.TokenType) { case TinyJsonToken.StartObject: { using (SequencePool.Rental rental2 = options.SequencePool.Rent()) { MessagePackWriter writer3 = writer.Clone(rental2.Value); uint num2 = FromJsonCore(jr, ref writer3, options); writer3.Flush(); num2 = unchecked(num2 / 2); writer.WriteMapHeader(num2); ReadOnlySequence<byte> rawMessagePackBlock = rental2.Value; writer.WriteRaw(in rawMessagePackBlock); } num++; break; } case TinyJsonToken.EndObject: return num; case TinyJsonToken.StartArray: { using (SequencePool.Rental rental = options.SequencePool.Rent()) { MessagePackWriter writer2 = writer.Clone(rental.Value); uint count = FromJsonCore(jr, ref writer2, options); writer2.Flush(); writer.WriteArrayHeader(count); ReadOnlySequence<byte> rawMessagePackBlock = rental.Value; writer.WriteRaw(in rawMessagePackBlock); } num++; break; } case TinyJsonToken.EndArray: return num; case TinyJsonToken.Number: switch (jr.ValueType) { case ValueType.Double: writer.Write(jr.DoubleValue); break; case ValueType.Long: writer.Write(jr.LongValue); break; case ValueType.ULong: writer.Write(jr.ULongValue); break; case ValueType.Decimal: DecimalFormatter.Instance.Serialize(ref writer, jr.DecimalValue, options); break; } num++; break; case TinyJsonToken.String: writer.Write(jr.StringValue); num++; break; case TinyJsonToken.True: writer.Write(value: true); num++; break; case TinyJsonToken.False: writer.Write(value: false); num++; break; case TinyJsonToken.Null: writer.WriteNil(); num++; break; } } return num; } } private static void ToJsonCore(ref MessagePackReader reader, TextWriter writer, MessagePackSerializerOptions options) { checked { switch (reader.NextMessagePackType) { case MessagePackType.Integer: if (MessagePackCode.IsSignedInteger(reader.NextCode)) { writer.Write(reader.ReadInt64().ToString(CultureInfo.InvariantCulture)); } else { writer.Write(reader.ReadUInt64().ToString(CultureInfo.InvariantCulture)); } break; case MessagePackType.Boolean: writer.Write(reader.ReadBoolean() ? "true" : "false"); break; case MessagePackType.Float: if (reader.NextCode == 202) { writer.Write(reader.ReadSingle().ToString(CultureInfo.InvariantCulture)); } else { writer.Write(reader.ReadDouble().ToString(CultureInfo.InvariantCulture)); } break; case MessagePackType.String: WriteJsonString(reader.ReadString(), writer); break; case MessagePackType.Binary: { ArraySegment<byte> arraySegment = ByteArraySegmentFormatter.Instance.Deserialize(ref reader, options); writer.Write("\"" + Convert.ToBase64String(arraySegment.Array ?? Array.Empty<byte>(), arraySegment.Offset, arraySegment.Count) + "\""); break; } case MessagePackType.Array: { int num2 = reader.ReadArrayHeader(); options.Security.DepthStep(ref reader); try { writer.Write("["); for (int i = 0; i < num2; i++) { ToJsonCore(ref reader, writer, options); if (i != num2 - 1) { writer.Write(","); } } writer.Write("]"); break; } finally { reader.Depth--; } } case MessagePackType.Map: { int num3 = reader.ReadMapHeader(); options.Security.DepthStep(ref reader); try { writer.Write("{"); for (int j = 0; j < num3; j++) { MessagePackType nextMessagePackType2 = reader.NextMessagePackType; if (nextMessagePackType2 == MessagePackType.String || nextMessagePackType2 == MessagePackType.Binary) { ToJsonCore(ref reader, writer, options); } else { writer.Write("\""); ToJsonCore(ref reader, writer, options); writer.Write("\""); } writer.Write(":"); ToJsonCore(ref reader, writer, options); if (j != num3 - 1) { writer.Write(","); } } writer.Write("}"); break; } finally { reader.Depth--; } } case MessagePackType.Extension: { ExtensionHeader header = reader.ReadExtensionFormatHeader(); if (header.TypeCode == -1) { DateTime dateTime = reader.ReadDateTime(header); writer.Write("\""); writer.Write(dateTime.ToString("o", CultureInfo.InvariantCulture)); writer.Write("\""); } else if (header.TypeCode == 100) { StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); SequencePosition position = reader.Position; ToJsonCore(ref reader, new StringWriter(stringBuilder2), options); int num = (int)reader.Sequence.Slice(position, reader.Position).Length; if (header.Length > num) { MessagePackType nextMessagePackType = reader.NextMessagePackType; if (nextMessagePackType != MessagePackType.Array && nextMessagePackType != MessagePackType.Map) { stringBuilder.Append("{"); } ToJsonCore(ref reader, new StringWriter(stringBuilder), options); if (nextMessagePackType != MessagePackType.Array) { stringBuilder2.Insert(0, "\"$type\":"); } if (nextMessagePackType != MessagePackType.Array && nextMessagePackType != MessagePackType.Map) { stringBuilder.Append("}"); } if (stringBuilder.Length > 2) { stringBuilder2.Append(","); } stringBuilder.Insert(1, stringBuilder2.ToString()); writer.Write(stringBuilder.ToString()); } else { writer.Write("{\"$type\":" + stringBuilder2.ToString() + "}"); } } else { ReadOnlySequence<byte> sequence = reader.ReadRaw(header.Length); writer.Write("["); writer.Write(header.TypeCode); writer.Write(","); writer.Write("\""); writer.Write(Convert.ToBase64String(BuffersExtensions.ToArray(in sequence))); writer.Write("\""); writer.Write("]"); } break; } case MessagePackType.Nil: reader.Skip(); writer.Write("null"); break; default: throw new MessagePackSerializationException($"code is invalid. code: {reader.NextCode} format: {MessagePackCode.ToFormatName(reader.NextCode)}"); } } } private static void WriteJsonString(string value, TextWriter builder) { builder.Write('"'); int length = value.Length; for (int i = 0; i < length; i = checked(i + 1)) { char c = value[i]; switch (c) { case '"': builder.Write("\\\""); break; case '\\': builder.Write("\\\\"); break; case '\b': builder.Write("\\b"); break; case '\f': builder.Write("\\f"); break; case '\n': builder.Write("\\n"); break; case '\r': builder.Write("\\r"); break; case '\t': builder.Write("\\t"); break; default: builder.Write(c); break; } } builder.Write('"'); } static MessagePackSerializer() { LZ4CodecEncode = LZ4Codec.Encode; LZ4CodecDecode = LZ4Codec.Decode; Serializes = new ThreadsafeTypeKeyHashTable<CompiledMethods>(64); CreateCompiledMethods = (Type t) => new CompiledMethods(t); } public static void Serialize(Type type, ref MessagePackWriter writer, object? obj, MessagePackSerializerOptions? options = null) { GetOrAdd(type).Serialize_MessagePackWriter_T_Options(ref writer, obj, options); } public static void Serialize(Type type, IBufferWriter<byte> writer, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { GetOrAdd(type).Serialize_IBufferWriter_T_Options_CancellationToken(writer, obj, options, cancellationToken); } public static byte[] Serialize(Type type, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).Serialize_T_Options(obj, options, cancellationToken); } public static void Serialize(Type type, Stream stream, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { GetOrAdd(type).Serialize_Stream_T_Options_CancellationToken(stream, obj, options, cancellationToken); } public static Task SerializeAsync(Type type, Stream stream, object? obj, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).SerializeAsync_Stream_T_Options_CancellationToken(stream, obj, options, cancellationToken); } public static object? Deserialize(Type type, ref MessagePackReader reader, MessagePackSerializerOptions? options = null) { return GetOrAdd(type).Deserialize_MessagePackReader_Options(ref reader, options); } public static object? Deserialize(Type type, Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).Deserialize_Stream_Options_CancellationToken(stream, options, cancellationToken); } public static ValueTask<object?> DeserializeAsync(Type type, Stream stream, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).DeserializeAsync_Stream_Options_CancellationToken(stream, options, cancellationToken); } public static object? Deserialize(Type type, ReadOnlyMemory<byte> bytes, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).Deserialize_ReadOnlyMemory_Options(bytes, options, cancellationToken); } public static object? Deserialize(Type type, ReadOnlySequence<byte> bytes, MessagePackSerializerOptions? options = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetOrAdd(type).Deserialize_ReadOnlySequence_Options_CancellationToken(bytes, options, cancellationToken); } private static void SerializeSemiGeneric<T>(ref MessagePackWriter writer, object valueObject, MessagePackSerializerOptions? options = null) { Serialize(ref writer, (T)valueObject, options); } private static object? DeserializeSemiGeneric<T>(ref MessagePackReader reader, MessagePackSerializerOptions? options = null) { return Deserialize<T>(ref reader, options); } private static async ValueTask<object?> DeserializeObjectAsync<T>(Stream stream, MessagePackSerializerOptions options, CancellationToken cancellationToken) { return await DeserializeAsync<T>(stream, options, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } private static CompiledMethods GetOrAdd(Type type) { return Serializes.GetOrAdd(type, CreateCompiledMethods); } } public class MessagePackStreamReader : IDisposable { private readonly Stream stream; private readonly bool leaveOpen; private SequencePool.Rental sequenceRental; private SequencePosition? endOfLastMessage; public ReadOnlySequence<byte> RemainingBytes { get { if (!endOfLastMessage.HasValue) { return ReadData.AsReadOnlySequence; } return ReadData.AsReadOnlySequence.Slice(endOfLastMessage.Value); } } private Sequence<byte> ReadData => sequenceRental.Value; public async ValueTask<int> ReadArrayHeaderAsync(CancellationToken cancellationToken) { RecycleLastMessage(); cancellationToken.ThrowIfCancellationRequested(); int length; while (!TryReadArrayHeader(out length)) { if (!(await TryReadMoreDataAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw new EndOfStreamException("The stream ended before a map header could be found."); } } return length; } public async IAsyncEnumerable<ReadOnlySequence<byte>> ReadArrayAsync([EnumeratorCancellation] CancellationToken cancellationToken) { RecycleLastMessage(); cancellationToken.ThrowIfCancellationRequested(); int length; while (!TryReadArrayHeader(out length)) { if (!(await TryReadMoreDataAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw new EndOfStreamException("The stream ended before an array header could be found."); } } for (int i = 0; i < length; i = checked(i + 1)) { ReadOnlySequence<byte>? readOnlySequence = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!readOnlySequence.HasValue) { throw new EndOfStreamException("Stream ended before all elements were read."); } yield return readOnlySequence.Value; } } private bool TryReadArrayHeader(out int length) { if (ReadData.Length > 0) { ReadOnlySequence<byte> readOnlySequence = ReadData; MessagePackReader messagePackReader = new MessagePackReader(in readOnlySequence); if (messagePackReader.TryReadArrayHeader(out length)) { endOfLastMessage = messagePackReader.Position; return true; } } length = 0; return false; } public async ValueTask<int> ReadMapHeaderAsync(CancellationToken cancellationToken) { RecycleLastMessage(); cancellationToken.ThrowIfCancellationRequested(); int count; while (!TryReadMapHeader(out count)) { if (!(await TryReadMoreDataAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw new EndOfStreamException("The stream ended before a map header could be found."); } } return count; } private bool TryReadMapHeader(out int count) { if (ReadData.Length > 0) { ReadOnlySequence<byte> readOnlySequence = ReadData; MessagePackReader messagePackReader = new MessagePackReader(in readOnlySequence); if (messagePackReader.TryReadMapHeader(out count)) { endOfLastMessage = messagePackReader.Position; return true; } } count = 0; return false; } public MessagePackStreamReader(Stream stream) : this(stream, leaveOpen: false) { } public MessagePackStreamReader(Stream stream, bool leaveOpen) : this(stream, leaveOpen, SequencePool.Shared) { } public MessagePackStreamReader(Stream stream, bool leaveOpen, SequencePool sequencePool) { if (sequencePool == null) { throw new ArgumentNullException("sequencePool"); } this.stream = stream ?? throw new ArgumentNullException("stream"); this.leaveOpen = leaveOpen; sequenceRental = sequencePool.Rent(); } public async ValueTask<ReadOnlySequence<byte>?> ReadAsync(CancellationToken cancellationToken) { RecycleLastMessage(); do { cancellationToken.ThrowIfCancellationRequested(); if (TryReadNextMessage(out var completeMessage)) { return completeMessage; } } while (await TryReadMoreDataAsync(cancellationToken)
BepInEx/plugins/SOTFEdit_Companion/SOTFEdit.Companion.Shared.dll
Decompiled 9 months agousing System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using MessagePack; using MessagePack.Formatters; using MessagePack.Formatters.SOTFEdit.Companion.Shared; using MessagePack.Formatters.SOTFEdit.Companion.Shared.Messages; using MessagePack.Internal; using MessagePack.Resolvers; using Microsoft.CodeAnalysis; using SOTFEdit.Companion.Shared; using SOTFEdit.Companion.Shared.Messages; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SOTFEdit.Companion.Shared")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b51329a2329d8ee3c0696ee45aeca38967302463")] [assembly: AssemblyProduct("SOTFEdit.Companion.Shared")] [assembly: AssemblyTitle("SOTFEdit.Companion.Shared")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace MessagePack.Formatters.SOTFEdit.Companion.Shared { public sealed class CharacterTargetFormatter : IMessagePackFormatter<CharacterTarget>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CharacterTarget value, MessagePackSerializerOptions options) { ((MessagePackWriter)(ref writer)).Write((int)value); } public CharacterTarget Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { return (CharacterTarget)((MessagePackReader)(ref reader)).ReadInt32(); } } public sealed class PoiGroupTypeFormatter : IMessagePackFormatter<PoiGroupType>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, PoiGroupType value, MessagePackSerializerOptions options) { ((MessagePackWriter)(ref writer)).Write((int)value); } public PoiGroupType Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { return (PoiGroupType)((MessagePackReader)(ref reader)).ReadInt32(); } } } namespace MessagePack.Formatters.SOTFEdit.Companion.Shared.Messages { public sealed class ICompanionMessageFormatter : IMessagePackFormatter<ICompanionMessage>, IMessagePackFormatter { private readonly Dictionary<RuntimeTypeHandle, KeyValuePair<int, int>> typeToKeyAndJumpMap; private readonly Dictionary<int, int> keyToJumpMap; public ICompanionMessageFormatter() { typeToKeyAndJumpMap = new Dictionary<RuntimeTypeHandle, KeyValuePair<int, int>>(10, RuntimeTypeHandleEqualityComparer.Default) { { typeof(CompanionPosMessage).TypeHandle, new KeyValuePair<int, int>(0, 0) }, { typeof(CompanionPosCollectionMessage).TypeHandle, new KeyValuePair<int, int>(1, 1) }, { typeof(CompanionTeleportMessage).TypeHandle, new KeyValuePair<int, int>(2, 2) }, { typeof(CompanionAddPoiMessage).TypeHandle, new KeyValuePair<int, int>(3, 3) }, { typeof(CompanionPoiListMessage).TypeHandle, new KeyValuePair<int, int>(4, 4) }, { typeof(CompanionPoiMessage).TypeHandle, new KeyValuePair<int, int>(5, 5) }, { typeof(CompanionDumpScenesMessage).TypeHandle, new KeyValuePair<int, int>(6, 6) }, { typeof(CompanionRequestPoiUpdateMessage).TypeHandle, new KeyValuePair<int, int>(7, 7) }, { typeof(CompanionNetworkPlayerUpdateMessage).TypeHandle, new KeyValuePair<int, int>(8, 8) }, { typeof(CompanionSettingsMessage).TypeHandle, new KeyValuePair<int, int>(9, 9) } }; keyToJumpMap = new Dictionary<int, int>(10) { { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 } }; } public void Serialize(ref MessagePackWriter writer, ICompanionMessage value, MessagePackSerializerOptions options) { if (value != null && typeToKeyAndJumpMap.TryGetValue(value.GetType().TypeHandle, out var value2)) { ((MessagePackWriter)(ref writer)).WriteArrayHeader(2); ((MessagePackWriter)(ref writer)).WriteInt32(value2.Key); switch (value2.Value) { case 0: FormatterResolverExtensions.GetFormatterWithVerify<CompanionPosMessage>(options.Resolver).Serialize(ref writer, (CompanionPosMessage)value, options); break; case 1: FormatterResolverExtensions.GetFormatterWithVerify<CompanionPosCollectionMessage>(options.Resolver).Serialize(ref writer, (CompanionPosCollectionMessage)value, options); break; case 2: FormatterResolverExtensions.GetFormatterWithVerify<CompanionTeleportMessage>(options.Resolver).Serialize(ref writer, (CompanionTeleportMessage)value, options); break; case 3: FormatterResolverExtensions.GetFormatterWithVerify<CompanionAddPoiMessage>(options.Resolver).Serialize(ref writer, (CompanionAddPoiMessage)value, options); break; case 4: FormatterResolverExtensions.GetFormatterWithVerify<CompanionPoiListMessage>(options.Resolver).Serialize(ref writer, (CompanionPoiListMessage)value, options); break; case 5: FormatterResolverExtensions.GetFormatterWithVerify<CompanionPoiMessage>(options.Resolver).Serialize(ref writer, (CompanionPoiMessage)value, options); break; case 6: FormatterResolverExtensions.GetFormatterWithVerify<CompanionDumpScenesMessage>(options.Resolver).Serialize(ref writer, (CompanionDumpScenesMessage)value, options); break; case 7: FormatterResolverExtensions.GetFormatterWithVerify<CompanionRequestPoiUpdateMessage>(options.Resolver).Serialize(ref writer, (CompanionRequestPoiUpdateMessage)value, options); break; case 8: FormatterResolverExtensions.GetFormatterWithVerify<CompanionNetworkPlayerUpdateMessage>(options.Resolver).Serialize(ref writer, (CompanionNetworkPlayerUpdateMessage)value, options); break; case 9: FormatterResolverExtensions.GetFormatterWithVerify<CompanionSettingsMessage>(options.Resolver).Serialize(ref writer, (CompanionSettingsMessage)value, options); break; } } else { ((MessagePackWriter)(ref writer)).WriteNil(); } } public ICompanionMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } if (((MessagePackReader)(ref reader)).ReadArrayHeader() != 2) { throw new InvalidOperationException("Invalid Union data was detected. Type:global::SOTFEdit.Companion.Shared.Messages.ICompanionMessage"); } options.Security.DepthStep(ref reader); int value = ((MessagePackReader)(ref reader)).ReadInt32(); if (!keyToJumpMap.TryGetValue(value, out value)) { value = -1; } ICompanionMessage result = null; switch (value) { case 0: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionPosMessage>(options.Resolver).Deserialize(ref reader, options); break; case 1: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionPosCollectionMessage>(options.Resolver).Deserialize(ref reader, options); break; case 2: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionTeleportMessage>(options.Resolver).Deserialize(ref reader, options); break; case 3: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionAddPoiMessage>(options.Resolver).Deserialize(ref reader, options); break; case 4: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionPoiListMessage>(options.Resolver).Deserialize(ref reader, options); break; case 5: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionPoiMessage>(options.Resolver).Deserialize(ref reader, options); break; case 6: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionDumpScenesMessage>(options.Resolver).Deserialize(ref reader, options); break; case 7: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionRequestPoiUpdateMessage>(options.Resolver).Deserialize(ref reader, options); break; case 8: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionNetworkPlayerUpdateMessage>(options.Resolver).Deserialize(ref reader, options); break; case 9: result = FormatterResolverExtensions.GetFormatterWithVerify<CompanionSettingsMessage>(options.Resolver).Deserialize(ref reader, options); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return result; } } public sealed class CompanionAddPoiMessageFormatter : IMessagePackFormatter<CompanionAddPoiMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionAddPoiMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(7); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.Title, options); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.Description, options); ((MessagePackWriter)(ref writer)).Write(value.Screenshot); ((MessagePackWriter)(ref writer)).Write(value.X); ((MessagePackWriter)(ref writer)).Write(value.Y); ((MessagePackWriter)(ref writer)).Write(value.Z); ((MessagePackWriter)(ref writer)).Write(value.AreaMask); } public CompanionAddPoiMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionAddPoiMessage companionAddPoiMessage = new CompanionAddPoiMessage(); for (int i = 0; i < num; i++) { switch (i) { case 0: companionAddPoiMessage.Title = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; case 1: companionAddPoiMessage.Description = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; case 2: { ReadOnlySequence<byte>? readOnlySequence = ((MessagePackReader)(ref reader)).ReadBytes(); companionAddPoiMessage.Screenshot = CodeGenHelpers.GetArrayFromNullableSequence(ref readOnlySequence); break; } case 3: companionAddPoiMessage.X = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 4: companionAddPoiMessage.Y = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 5: companionAddPoiMessage.Z = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 6: companionAddPoiMessage.AreaMask = ((MessagePackReader)(ref reader)).ReadInt32(); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionAddPoiMessage; } } public sealed class CompanionDumpScenesMessageFormatter : IMessagePackFormatter<CompanionDumpScenesMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionDumpScenesMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); } else { ((MessagePackWriter)(ref writer)).WriteArrayHeader(0); } } public CompanionDumpScenesMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } ((MessagePackReader)(ref reader)).Skip(); return new CompanionDumpScenesMessage(); } } public sealed class CompanionNetworkPlayerUpdateMessageFormatter : IMessagePackFormatter<CompanionNetworkPlayerUpdateMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionNetworkPlayerUpdateMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(2); FormatterResolverExtensions.GetFormatterWithVerify<HashSet<int>>(resolver).Serialize(ref writer, value.Added, options); FormatterResolverExtensions.GetFormatterWithVerify<HashSet<int>>(resolver).Serialize(ref writer, value.Deleted, options); } public CompanionNetworkPlayerUpdateMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionNetworkPlayerUpdateMessage companionNetworkPlayerUpdateMessage = new CompanionNetworkPlayerUpdateMessage(); for (int i = 0; i < num; i++) { switch (i) { case 0: companionNetworkPlayerUpdateMessage.Added = FormatterResolverExtensions.GetFormatterWithVerify<HashSet<int>>(resolver).Deserialize(ref reader, options); break; case 1: companionNetworkPlayerUpdateMessage.Deleted = FormatterResolverExtensions.GetFormatterWithVerify<HashSet<int>>(resolver).Deserialize(ref reader, options); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionNetworkPlayerUpdateMessage; } } public sealed class CompanionPoiListMessageFormatter : IMessagePackFormatter<CompanionPoiListMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionPoiListMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(2); FormatterResolverExtensions.GetFormatterWithVerify<PoiGroupType>(resolver).Serialize(ref writer, value.Type, options); FormatterResolverExtensions.GetFormatterWithVerify<List<CompanionPoiMessage>>(resolver).Serialize(ref writer, value.Pois, options); } public CompanionPoiListMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); PoiGroupType type = PoiGroupType.Generic; List<CompanionPoiMessage> pois = null; for (int i = 0; i < num; i++) { switch (i) { case 0: type = FormatterResolverExtensions.GetFormatterWithVerify<PoiGroupType>(resolver).Deserialize(ref reader, options); break; case 1: pois = FormatterResolverExtensions.GetFormatterWithVerify<List<CompanionPoiMessage>>(resolver).Deserialize(ref reader, options); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } CompanionPoiListMessage result = new CompanionPoiListMessage(type, pois); int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return result; } } public sealed class CompanionPoiMessageFormatter : IMessagePackFormatter<CompanionPoiMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionPoiMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(7); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.Title, options); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.Description, options); ((MessagePackWriter)(ref writer)).Write(value.X); ((MessagePackWriter)(ref writer)).Write(value.Y); ((MessagePackWriter)(ref writer)).Write(value.Z); ((MessagePackWriter)(ref writer)).Write(value.AreaMask); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.ScreenshotPath, options); } public CompanionPoiMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); string title = null; string description = null; float x = 0f; float y = 0f; float z = 0f; int areaMask = 0; string screenshotPath = null; for (int i = 0; i < num; i++) { switch (i) { case 0: title = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; case 1: description = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; case 2: x = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 3: y = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 4: z = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 5: areaMask = ((MessagePackReader)(ref reader)).ReadInt32(); break; case 6: screenshotPath = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } CompanionPoiMessage result = new CompanionPoiMessage(title, description, x, y, z, areaMask, screenshotPath); int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return result; } } public sealed class CompanionPosCollectionMessageFormatter : IMessagePackFormatter<CompanionPosCollectionMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionPosCollectionMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(1); FormatterResolverExtensions.GetFormatterWithVerify<List<CompanionPosMessage>>(resolver).Serialize(ref writer, value.Positions, options); } public CompanionPosCollectionMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionPosCollectionMessage companionPosCollectionMessage = new CompanionPosCollectionMessage(); for (int i = 0; i < num; i++) { if (i == 0) { companionPosCollectionMessage.Positions = FormatterResolverExtensions.GetFormatterWithVerify<List<CompanionPosMessage>>(resolver).Deserialize(ref reader, options); } else { ((MessagePackReader)(ref reader)).Skip(); } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionPosCollectionMessage; } } public sealed class CompanionPosMessageFormatter : IMessagePackFormatter<CompanionPosMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionPosMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(8); FormatterResolverExtensions.GetFormatterWithVerify<CharacterTarget>(resolver).Serialize(ref writer, value.Target, options); ((MessagePackWriter)(ref writer)).Write(value.X); ((MessagePackWriter)(ref writer)).Write(value.Y); ((MessagePackWriter)(ref writer)).Write(value.Z); ((MessagePackWriter)(ref writer)).Write(value.Rotation); ((MessagePackWriter)(ref writer)).Write(value.Mask); ((MessagePackWriter)(ref writer)).Write(value.InstanceId); FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Serialize(ref writer, value.Name, options); } public CompanionPosMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionPosMessage companionPosMessage = new CompanionPosMessage(); for (int i = 0; i < num; i++) { switch (i) { case 0: companionPosMessage.Target = FormatterResolverExtensions.GetFormatterWithVerify<CharacterTarget>(resolver).Deserialize(ref reader, options); break; case 1: companionPosMessage.X = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 2: companionPosMessage.Y = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 3: companionPosMessage.Z = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 4: companionPosMessage.Rotation = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 5: companionPosMessage.Mask = ((MessagePackReader)(ref reader)).ReadInt32(); break; case 6: companionPosMessage.InstanceId = ((MessagePackReader)(ref reader)).ReadInt32(); break; case 7: companionPosMessage.Name = FormatterResolverExtensions.GetFormatterWithVerify<string>(resolver).Deserialize(ref reader, options); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionPosMessage; } } public sealed class CompanionRequestPoiUpdateMessageFormatter : IMessagePackFormatter<CompanionRequestPoiUpdateMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionRequestPoiUpdateMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(1); FormatterResolverExtensions.GetFormatterWithVerify<PoiGroupType>(resolver).Serialize(ref writer, value.Type, options); } public CompanionRequestPoiUpdateMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionRequestPoiUpdateMessage companionRequestPoiUpdateMessage = new CompanionRequestPoiUpdateMessage(); for (int i = 0; i < num; i++) { if (i == 0) { companionRequestPoiUpdateMessage.Type = FormatterResolverExtensions.GetFormatterWithVerify<PoiGroupType>(resolver).Deserialize(ref reader, options); } else { ((MessagePackReader)(ref reader)).Skip(); } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionRequestPoiUpdateMessage; } } public sealed class CompanionSettingsMessageFormatter : IMessagePackFormatter<CompanionSettingsMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionSettingsMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(1); FormatterResolverExtensions.GetFormatterWithVerify<decimal>(resolver).Serialize(ref writer, value.PositionUpdateFrequency, options); } public CompanionSettingsMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionSettingsMessage companionSettingsMessage = new CompanionSettingsMessage(); for (int i = 0; i < num; i++) { if (i == 0) { companionSettingsMessage.PositionUpdateFrequency = FormatterResolverExtensions.GetFormatterWithVerify<decimal>(resolver).Deserialize(ref reader, options); } else { ((MessagePackReader)(ref reader)).Skip(); } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionSettingsMessage; } } public sealed class CompanionTeleportMessageFormatter : IMessagePackFormatter<CompanionTeleportMessage>, IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, CompanionTeleportMessage value, MessagePackSerializerOptions options) { if (value == null) { ((MessagePackWriter)(ref writer)).WriteNil(); return; } IFormatterResolver resolver = options.Resolver; ((MessagePackWriter)(ref writer)).WriteArrayHeader(6); FormatterResolverExtensions.GetFormatterWithVerify<CharacterTarget>(resolver).Serialize(ref writer, value.Target, options); ((MessagePackWriter)(ref writer)).Write(value.X); ((MessagePackWriter)(ref writer)).Write(value.Y); ((MessagePackWriter)(ref writer)).Write(value.Z); ((MessagePackWriter)(ref writer)).Write(value.AreaMask); ((MessagePackWriter)(ref writer)).Write(value.GraphMask); } public CompanionTeleportMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (((MessagePackReader)(ref reader)).TryReadNil()) { return null; } options.Security.DepthStep(ref reader); IFormatterResolver resolver = options.Resolver; int num = ((MessagePackReader)(ref reader)).ReadArrayHeader(); CompanionTeleportMessage companionTeleportMessage = new CompanionTeleportMessage(); for (int i = 0; i < num; i++) { switch (i) { case 0: companionTeleportMessage.Target = FormatterResolverExtensions.GetFormatterWithVerify<CharacterTarget>(resolver).Deserialize(ref reader, options); break; case 1: companionTeleportMessage.X = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 2: companionTeleportMessage.Y = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 3: companionTeleportMessage.Z = ((MessagePackReader)(ref reader)).ReadSingle(); break; case 4: companionTeleportMessage.AreaMask = ((MessagePackReader)(ref reader)).ReadInt32(); break; case 5: companionTeleportMessage.GraphMask = ((MessagePackReader)(ref reader)).ReadInt32(); break; default: ((MessagePackReader)(ref reader)).Skip(); break; } } int depth = ((MessagePackReader)(ref reader)).Depth; ((MessagePackReader)(ref reader)).Depth = depth - 1; return companionTeleportMessage; } } } namespace MessagePack.Resolvers { public class GeneratedResolver : IFormatterResolver { private static class FormatterCache<T> { internal static readonly IMessagePackFormatter<T> Formatter; static FormatterCache() { object formatter = GeneratedResolverGetFormatterHelper.GetFormatter(typeof(T)); if (formatter != null) { Formatter = (IMessagePackFormatter<T>)formatter; } } } public static readonly IFormatterResolver Instance = (IFormatterResolver)(object)new GeneratedResolver(); private GeneratedResolver() { } public IMessagePackFormatter<T> GetFormatter<T>() { return FormatterCache<T>.Formatter; } } internal static class GeneratedResolverGetFormatterHelper { private static readonly Dictionary<Type, int> lookup; static GeneratedResolverGetFormatterHelper() { lookup = new Dictionary<Type, int>(16) { { typeof(HashSet<int>), 0 }, { typeof(List<CompanionPoiMessage>), 1 }, { typeof(List<CompanionPosMessage>), 2 }, { typeof(CharacterTarget), 3 }, { typeof(PoiGroupType), 4 }, { typeof(ICompanionMessage), 5 }, { typeof(CompanionAddPoiMessage), 6 }, { typeof(CompanionDumpScenesMessage), 7 }, { typeof(CompanionNetworkPlayerUpdateMessage), 8 }, { typeof(CompanionPoiListMessage), 9 }, { typeof(CompanionPoiMessage), 10 }, { typeof(CompanionPosCollectionMessage), 11 }, { typeof(CompanionPosMessage), 12 }, { typeof(CompanionRequestPoiUpdateMessage), 13 }, { typeof(CompanionSettingsMessage), 14 }, { typeof(CompanionTeleportMessage), 15 } }; } internal static object GetFormatter(Type t) { if (!lookup.TryGetValue(t, out var value)) { return null; } return value switch { 0 => new HashSetFormatter<int>(), 1 => new ListFormatter<CompanionPoiMessage>(), 2 => new ListFormatter<CompanionPosMessage>(), 3 => new CharacterTargetFormatter(), 4 => new PoiGroupTypeFormatter(), 5 => new ICompanionMessageFormatter(), 6 => new CompanionAddPoiMessageFormatter(), 7 => new CompanionDumpScenesMessageFormatter(), 8 => new CompanionNetworkPlayerUpdateMessageFormatter(), 9 => new CompanionPoiListMessageFormatter(), 10 => new CompanionPoiMessageFormatter(), 11 => new CompanionPosCollectionMessageFormatter(), 12 => new CompanionPosMessageFormatter(), 13 => new CompanionRequestPoiUpdateMessageFormatter(), 14 => new CompanionSettingsMessageFormatter(), 15 => new CompanionTeleportMessageFormatter(), _ => null, }; } } } namespace SOTFEdit.Companion.Shared { public enum CharacterTarget { Player, Kelvin, Virginia, NetworkPlayer } public static class MessagePackInitializer { private static bool _initialized; public static void Initialize() { if (!_initialized) { StaticCompositeResolver.Instance.Register((IFormatterResolver[])(object)new IFormatterResolver[2] { GeneratedResolver.Instance, (IFormatterResolver)StandardResolver.Instance }); MessagePackSerializer.DefaultOptions = MessagePackSerializerOptions.Standard.WithResolver((IFormatterResolver)(object)StaticCompositeResolver.Instance); _initialized = true; } } } public enum PoiGroupType { Generic, Custom, Items, Actors, WorldItems, Bunkers, Printers, Laptops, Caves, Camps, Villages, Helicopters, Info, Doors, Crates, Supply, Ammo, CannibalVillages, Ponds, Lakes, Structures, ZipLines, Player, Followers } public static class PoiGroupTypeUtils { public static PoiGroupType[] GetSupportedCompanionPoiGroupTypes() { return (from e in Enum.GetValues<PoiGroupType>().Where(delegate(PoiGroupType e) { switch (e) { case PoiGroupType.Custom: case PoiGroupType.Items: case PoiGroupType.WorldItems: case PoiGroupType.Bunkers: case PoiGroupType.Printers: case PoiGroupType.Laptops: case PoiGroupType.Caves: case PoiGroupType.Villages: case PoiGroupType.Helicopters: case PoiGroupType.Doors: case PoiGroupType.Lakes: return true; default: return false; } }) orderby e.ToString() select e).ToArray(); } } } namespace SOTFEdit.Companion.Shared.Messages { [MessagePackObject(false)] public class CompanionAddPoiMessage : ICompanionMessage { [Key(0)] public string Title { get; set; } [Key(1)] public string Description { get; set; } [Key(2)] public byte[] Screenshot { get; set; } [Key(3)] public float X { get; set; } [Key(4)] public float Y { get; set; } [Key(5)] public float Z { get; set; } [Key(6)] public int AreaMask { get; set; } } [MessagePackObject(false)] public record CompanionDumpScenesMessage : ICompanionMessage; [MessagePackObject(false)] public class CompanionNetworkPlayerUpdateMessage : ICompanionMessage { [Key(0)] public HashSet<int>? Added { get; set; } [Key(1)] public HashSet<int>? Deleted { get; set; } } [MessagePackObject(false)] public class CompanionPoiListMessage : ICompanionMessage { [Key(0)] public PoiGroupType Type { get; } [Key(1)] public List<CompanionPoiMessage> Pois { get; } public CompanionPoiListMessage(PoiGroupType type, List<CompanionPoiMessage> pois) { Type = type; Pois = pois; } } [MessagePackObject(false)] public class CompanionPoiMessage : ICompanionMessage { [Key(0)] public string Title { get; init; } [Key(1)] public string? Description { get; init; } [Key(2)] public float X { get; init; } [Key(3)] public float Y { get; init; } [Key(4)] public float Z { get; init; } [Key(5)] public int AreaMask { get; init; } [Key(6)] public string? ScreenshotPath { get; init; } public CompanionPoiMessage(string title, string? description, float x, float y, float z, int areaMask, string? screenshotPath) { Title = title; Description = description; X = x; Y = y; Z = z; AreaMask = areaMask; ScreenshotPath = screenshotPath; } } [MessagePackObject(false)] public class CompanionPosCollectionMessage : ICompanionMessage { [Key(0)] public List<CompanionPosMessage> Positions { get; set; } } [MessagePackObject(false)] public record CompanionPosMessage : ICompanionMessage { [Key(0)] public CharacterTarget Target { get; set; } [Key(1)] public float X { get; set; } [Key(2)] public float Y { get; set; } [Key(3)] public float Z { get; set; } [Key(4)] public float Rotation { get; set; } [Key(5)] public int Mask { get; set; } [Key(6)] public int InstanceId { get; set; } [Key(7)] public string? Name { get; set; } } [MessagePackObject(false)] public class CompanionRequestPoiUpdateMessage : ICompanionMessage { [Key(0)] public PoiGroupType Type { get; set; } } [MessagePackObject(false)] public class CompanionSettingsMessage : ICompanionMessage { [Key(0)] public decimal PositionUpdateFrequency { get; set; } } [MessagePackObject(false)] public record CompanionTeleportMessage : ICompanionMessage { [Key(0)] public CharacterTarget Target { get; set; } [Key(1)] public float X { get; set; } [Key(2)] public float Y { get; set; } [Key(3)] public float Z { get; set; } [Key(4)] public int AreaMask { get; set; } [Key(5)] public int GraphMask { get; set; } } [Union(0, typeof(CompanionPosMessage))] [Union(1, typeof(CompanionPosCollectionMessage))] [Union(2, typeof(CompanionTeleportMessage))] [Union(3, typeof(CompanionAddPoiMessage))] [Union(4, typeof(CompanionPoiListMessage))] [Union(5, typeof(CompanionPoiMessage))] [Union(6, typeof(CompanionDumpScenesMessage))] [Union(7, typeof(CompanionRequestPoiUpdateMessage))] [Union(8, typeof(CompanionNetworkPlayerUpdateMessage))] [Union(9, typeof(CompanionSettingsMessage))] public interface ICompanionMessage { } }
BepInEx/plugins/SOTFEdit_Companion/SOTFEdit_Companion.dll
Decompiled 9 months agousing System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Utils.Collections; using Endnight.Utilities; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections; using Il2CppSystem.Collections.Concurrent; using Il2CppSystem.Collections.Generic; using Il2CppSystem.IO; using MessagePack; using Microsoft.CodeAnalysis; using Pathfinding; using SOTFEdit.Companion.Shared; using SOTFEdit.Companion.Shared.Messages; using SOTFEdit_Companion.Behaviors; using SOTFEdit_Companion.Connection; using SOTFEdit_Companion.Dialogs; using SOTFEdit_Companion.Infrastructure; using SOTFEdit_Companion.Models; using SOTFEdit_Companion.NetworkPlayer; using Sons.Ai.Vail; using Sons.Areas; using Sons.Gui; using Sons.Input; using Sons.Multiplayer.Client; using TheForest.Utils; using UnityEngine; using UnityEngine.Networking; using WatsonWebsocket; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SOTFEdit_Companion")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("SOTFEdit Companion")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+5b186d9fee3ead6ec9d857c8ae16fba8e01b5e4e")] [assembly: AssemblyProduct("SOTFEdit_Companion")] [assembly: AssemblyTitle("SOTFEdit_Companion")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SOTFEdit_Companion { public static class CompanionPoiStorage { private static List<CompanionPoiMessage> _companionPois = new List<CompanionPoiMessage>(); private static List<CompanionPoiMessage> _filteredPois = new List<CompanionPoiMessage>(); private static PoiGroupType? _currentType; private static string _lastFilter; public static void Replace(PoiGroupType poiGroupType, IEnumerable<CompanionPoiMessage> newPois) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) _currentType = poiGroupType; List<CompanionPoiMessage> list = new List<CompanionPoiMessage>(); list.AddRange(newPois); _companionPois = list; _lastFilter = null; } public static IEnumerable<CompanionPoiMessage> GetAllFiltered(string filter) { if (filter != _lastFilter) { _filteredPois = _companionPois.Where((CompanionPoiMessage poi) => FilterDescription(filter, poi.Description) || FilterTitle(filter, poi.Title)).ToList(); } return _filteredPois; } public static void Add(CompanionPoiMessage companionPoi) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (_currentType == (PoiGroupType?)1) { _companionPois.Add(companionPoi); _lastFilter = null; } } private static bool FilterTitle(string filter, string title) { return title.Contains(filter, StringComparison.InvariantCultureIgnoreCase); } private static bool FilterDescription(string filter, string description) { return description?.Contains(filter, StringComparison.InvariantCultureIgnoreCase) ?? false; } } [BepInPlugin("SOTFEdit_Companion", "SOTFEdit_Companion", "1.0.0")] public class SotfEditCompanionPlugin : BasePlugin { public static readonly ManualLogSource Logger = new ManualLogSource("SotfEditCompanionPlugin"); public override void Load() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown Logger.Sources.Add((ILogSource)(object)Logger); ClassInjector.RegisterTypeInIl2Cpp<UnityMainThreadDispatcher>(); ClassInjector.RegisterTypeInIl2Cpp<AddCoordsDialog>(); ClassInjector.RegisterTypeInIl2Cpp<ShowCoordsDialog>(); ClassInjector.RegisterTypeInIl2Cpp<SotfEditPlayerHandler>(); ClassInjector.RegisterTypeInIl2Cpp<SotfEditFollowerHandler>(); ClassInjector.RegisterTypeInIl2Cpp<SotfEditCompanionGameObject>(); bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("SOTFEdit_Companion"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!"); } Logger.LogInfo(val); GameObject val2 = new GameObject("SOTFEdit_Companion") { hideFlags = (HideFlags)61 }; val2.AddComponent<SotfEditCompanionGameObject>(); Object.DontDestroyOnLoad((Object)val2); } } public static class SotfEditPluginInfo { public const string PluginGuid = "SOTFEdit_Companion"; public const string PluginName = "SOTFEdit_Companion"; public const string PluginVersion = "1.0.0"; } public static class MyPluginInfo { public const string PLUGIN_GUID = "SOTFEdit_Companion"; public const string PLUGIN_NAME = "SOTFEdit_Companion"; public const string PLUGIN_VERSION = "1.0.2"; } } namespace SOTFEdit_Companion.NetworkPlayer { public class NetworkPlayerHandler { private readonly PlayerLocation _location; private CoopPlayerRemoteSetup _remoteSetup; public string Name { get; private set; } public int InstanceId { get; } public Vector3? LastPosition { get; private set; } public int LastMask { get; private set; } public float LastRotation { get; private set; } public NetworkPlayerHandler(PlayerLocation location) { InstanceId = ((Object)location).GetInstanceID(); RefreshName((Component)(object)location); _location = location; } private void RefreshName(Component location) { _remoteSetup = location.gameObject.GetComponent<CoopPlayerRemoteSetup>(); Name = (((Object)(object)_remoteSetup == (Object)null) ? null : _remoteSetup._cachedPlayerName); } public bool IsValid() { return BehaviourUtils.IsValid((Behaviour)(object)_location); } public void Refresh() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (BehaviourUtils.IsValid((Behaviour)(object)_location)) { Transform transform = ((Component)_location).transform; LastPosition = transform.position; Quaternion rotation = transform.rotation; LastRotation = ((Quaternion)(ref rotation)).eulerAngles.y; LastMask = _location.AreaMask; RefreshName((Component)(object)_location); } } } public static class NetworkPlayerManager { public static readonly ConcurrentDictionary<int, NetworkPlayerHandler> NetworkPlayerHandlers = new ConcurrentDictionary<int, NetworkPlayerHandler>(); public static bool ForceNetworkPlayerBroadcast { get; set; } public static void ReportNetworkPlayerLocations(List<PlayerLocation> newLocations) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_01f7: Expected O, but got Unknown HashSet<int> hashSet = new HashSet<int>(); HashSet<int> hashSet2 = new HashSet<int>(); bool flag = default(bool); foreach (PlayerLocation item in newLocations.Where((PlayerLocation newLocation) => NetworkPlayerHandlers.TryAdd(((Object)newLocation).GetInstanceID(), new NetworkPlayerHandler(newLocation)))) { hashSet.Add(((Object)item).GetInstanceID()); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Added Network Player: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(((Object)item).GetInstanceID()); } SotfEditCompanionPlugin.Logger.LogInfo(val); } foreach (KeyValuePair<int, NetworkPlayerHandler> item2 in NetworkPlayerHandlers.Where((KeyValuePair<int, NetworkPlayerHandler> kvp) => !kvp.Value.IsValid())) { hashSet2.Add(item2.Key); } hashSet2.ExceptWith(newLocations.Select((PlayerLocation loc) => ((Object)loc).GetInstanceID())); foreach (int item3 in hashSet2) { BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Removed Network Player"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(item3); } SotfEditCompanionPlugin.Logger.LogInfo(val); NetworkPlayerHandlers.Remove(item3, out var _); } if (ForceNetworkPlayerBroadcast) { ForceNetworkPlayerBroadcast = false; SotfEditCompanionPlugin.Logger.LogInfo((object)"Forced Network Player Broadcast"); ConnectionHandler.Instance.BroadcastAsync(MessagePackSerializer.Serialize<ICompanionMessage>((ICompanionMessage)new CompanionNetworkPlayerUpdateMessage { Added = NetworkPlayerHandlers.Select((KeyValuePair<int, NetworkPlayerHandler> handler) => handler.Key).ToHashSet() }, (MessagePackSerializerOptions)null, default(CancellationToken))); } else if (hashSet.Count > 0 || hashSet2.Count > 0) { ConnectionHandler.Instance.BroadcastAsync(MessagePackSerializer.Serialize<ICompanionMessage>((ICompanionMessage)new CompanionNetworkPlayerUpdateMessage { Added = hashSet, Deleted = hashSet2 }, (MessagePackSerializerOptions)null, default(CancellationToken))); } } } } namespace SOTFEdit_Companion.Models { public static class Configuration { private static readonly ConfigFile ConfigFile; public static ConfigEntry<int> ListenPort { get; } public static ConfigEntry<string> ListenAddress { get; } public static ConfigEntry<KeyCode> TeleportKey { get; } public static ConfigEntry<KeyCode> CustomPoiKey { get; } static Configuration() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown ConfigFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "SOTFEdit_Companion.cfg"), true); ListenAddress = ConfigFile.Bind<string>("TCP", "ListenAddress", "127.0.0.1", "Local Server IP or address"); ListenPort = ConfigFile.Bind<int>("TCP", "ListenPort", 35321, "Local Server Port"); TeleportKey = ConfigFile.Bind<KeyCode>("Hotkeys", "Teleport", (KeyCode)289, "Hotkey used to teleport to the points of interest"); CustomPoiKey = ConfigFile.Bind<KeyCode>("Hotkeys", "CustomPoi", (KeyCode)290, "Hotkey used to create custom points of interest"); } } public class FollowerState { public int LastMask = 1; public Vector3 LastPosition; public float LastRotation; public void UpdateLocation(VailActor actor) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (BehaviourUtils.IsValid((Behaviour)(object)actor)) { LastPosition = actor.Position(); Quaternion val = actor.Rotation(); LastRotation = ((Quaternion)(ref val)).eulerAngles.y; LastMask = actor.GetNavGraphMask().value; } } } } namespace SOTFEdit_Companion.Infrastructure { public static class Actions { public static Action TeleportPlayer(float x, float y, float z, int areaMask) { return Action.op_Implicit((Action)delegate { TeleportPlayerInternal(x, y, z, areaMask); }); } private static void TeleportPlayerInternal(float x, float y, float z, int areaMask) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) if (!ValidateTeleportation()) { return; } LocalPlayer.TeleportTo(new Vector3(x, y, z)); if (PlayerLocation.GetLocalPlayerAreaMask() != areaMask) { PlayerLocation.SetLocalPlayerAreaMask(areaMask); AreaMask val = (AreaMask)areaMask; if (AreaMaskExtensions.IsCaveOrBunkerArea(val)) { CaveEntranceManager.OnCaveEnter(val); } else { CaveEntranceManager.OnCaveExit(val); } } } public static Action TeleportKelvin(float x, float y, float z, int areaMask, int graphMask) { return Action.op_Implicit((Action)delegate { TeleportActor(SotfEditFollowerHandler.Instance.kelvinActor, x, y, z, areaMask, graphMask); }); } public static Action TeleportVirginia(float x, float y, float z, int areaMask, int graphMask) { return Action.op_Implicit((Action)delegate { TeleportActor(SotfEditFollowerHandler.Instance.virginiaActor, x, y, z, areaMask, graphMask); }); } private static void TeleportActor(VailActor follower, float x, float y, float z, int areaMask, int graphMask) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (!ValidateTeleportation() || !BehaviourUtils.IsValid((Behaviour)(object)follower)) { if ((Object)(object)follower != (Object)null) { bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Actor "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(follower.UniqueId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" can not be teleported because it is inactive"); } SotfEditCompanionPlugin.Logger.LogWarning(val); } else { SotfEditCompanionPlugin.Logger.LogWarning((object)"Actor can not be teleported because it is null"); } } else { follower.SetPositionAndRotation(new Vector3(x, y, z), follower.Rotation(), false); if (follower.GetNavGraphMask().value != graphMask) { follower.SetNavGraphMask(new GraphMask(graphMask)); } } } private static bool ValidateTeleportation() { if (SotfEditCompanionGameObject.IsPlayerAvailable()) { return true; } SotfEditCompanionPlugin.Logger.LogWarning((object)"Teleportation not possible, player is not in game"); return false; } } public static class Coroutines { public static IEnumerator FindActors(SotfEditFollowerHandler followerHandler) { return CollectionExtensions.WrapToIl2Cpp(FindActorsInternal(followerHandler)); } public static IEnumerator CollectAndSendPositions(SotfEditCompanionGameObject gameObject) { return CollectionExtensions.WrapToIl2Cpp(CollectAndSendPositionsInternal(gameObject)); } public static IEnumerator FindPlayers(SotfEditPlayerHandler playerHandler) { return CollectionExtensions.WrapToIl2Cpp(FindPlayersInternal(playerHandler)); } private static IEnumerator FindPlayersInternal(SotfEditPlayerHandler playerHandler) { bool flag = default(bool); while (true) { if (SotfEditCompanionGameObject.IsPlayerAvailable()) { List<PlayerLocation> players = PlayerLocation._players; List<PlayerLocation> list = new List<PlayerLocation>(); Enumerator<PlayerLocation> enumerator = players.GetEnumerator(); while (enumerator.MoveNext()) { PlayerLocation current = enumerator.Current; if (!BehaviourUtils.IsValid((Behaviour)(object)current)) { BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)current).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not active"); } SotfEditCompanionPlugin.Logger.LogInfo(val); } else if (current.IsLocalPlayer) { if (!BehaviourUtils.IsValid((Behaviour)(object)playerHandler.playerLocation)) { playerHandler.playerLocation = current; SotfEditCompanionPlugin.Logger.LogInfo((object)"Player found"); } } else { list.Add(current); } } NetworkPlayerManager.ReportNetworkPlayerLocations(list); } yield return (object)new WaitForSeconds(5f); } } private static IEnumerator CollectAndSendPositionsInternal(SotfEditCompanionGameObject gameObject) { while (true) { if (!SotfEditCompanionGameObject.IsPaused() && SotfEditCompanionGameObject.IsPlayerAvailable()) { SotfEditPlayerHandler playerHandler = gameObject.playerHandler; playerHandler.RefreshLocation(); Vector3 lastPosition = playerHandler.lastPosition; List<CompanionPosMessage> list = new List<CompanionPosMessage> { new CompanionPosMessage { Target = (CharacterTarget)0, Mask = playerHandler.lastMask, Rotation = playerHandler.lastRotation, X = lastPosition.x, Y = lastPosition.y, Z = lastPosition.z } }; SotfEditFollowerHandler followerHandler = gameObject.followerHandler; followerHandler.RefreshLocations(); if (!followerHandler.MustFindKelvin()) { FollowerState kelvinState = followerHandler.KelvinState; Vector3 lastPosition2 = kelvinState.LastPosition; list.Add(BuildFollowerCompanionPosMessage((CharacterTarget)1, kelvinState, lastPosition2)); } if (!followerHandler.MustFindVirginia()) { FollowerState virginiaState = followerHandler.VirginiaState; Vector3 lastPosition3 = virginiaState.LastPosition; list.Add(BuildFollowerCompanionPosMessage((CharacterTarget)2, virginiaState, lastPosition3)); } list.AddRange(CollectPositionsFromNetworkPlayers()); byte[] data = MessagePackSerializer.Serialize<ICompanionMessage>((ICompanionMessage)new CompanionPosCollectionMessage { Positions = list }, (MessagePackSerializerOptions)null, default(CancellationToken)); gameObject.ConnectionHandler.BroadcastAsync(data); } yield return (object)new WaitForSeconds(gameObject.timeBetweenUpdates); } } private static IEnumerable<CompanionPosMessage> CollectPositionsFromNetworkPlayers() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown List<CompanionPosMessage> list = new List<CompanionPosMessage>(); foreach (NetworkPlayerHandler value in NetworkPlayerManager.NetworkPlayerHandlers.Values) { if (value.IsValid()) { value.Refresh(); Vector3? lastPosition = value.LastPosition; if (lastPosition.HasValue) { Vector3 valueOrDefault = lastPosition.GetValueOrDefault(); list.Add(new CompanionPosMessage { Target = (CharacterTarget)3, Mask = value.LastMask, Rotation = value.LastRotation, X = valueOrDefault.x, Y = valueOrDefault.y, Z = valueOrDefault.z, InstanceId = value.InstanceId, Name = (value.Name ?? "???") }); } } } return list; } private static CompanionPosMessage BuildFollowerCompanionPosMessage(CharacterTarget target, FollowerState state, Vector3 lastKelvinPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown return new CompanionPosMessage { Target = target, Mask = state.LastMask, Rotation = state.LastRotation, X = lastKelvinPos.x, Y = lastKelvinPos.y, Z = lastKelvinPos.z }; } private static IEnumerator FindActorsInternal(SotfEditFollowerHandler followerHandler) { while (true) { bool num = SotfEditCompanionGameObject.IsPlayerAvailable(); VailWorldSimulation instance = VailWorldSimulation._instance; if (num && (Object)(object)instance != (Object)null && !instance.IsDisabled) { if (followerHandler.MustFindKelvin()) { followerHandler.kelvinActor = null; VailActor val = VailActorManager.FindActiveActor((VailActorTypeId)9); if (BehaviourUtils.IsValid((Behaviour)(object)val)) { SotfEditCompanionPlugin.Logger.LogInfo((object)"Kelvin found"); followerHandler.kelvinActor = val; } } if (followerHandler.MustFindVirginia()) { VailActor val2 = VailActorManager.FindActiveActor((VailActorTypeId)10); if (BehaviourUtils.IsValid((Behaviour)(object)val2)) { SotfEditCompanionPlugin.Logger.LogInfo((object)"Virginia found"); followerHandler.virginiaActor = val2; } } } yield return (object)new WaitForSeconds(5f); } } public static IEnumerator WrapAction(Action action) { return CollectionExtensions.WrapToIl2Cpp(WrapActionInternal(action)); } private static IEnumerator WrapActionInternal(Action action) { action.Invoke(); yield return null; } public static IEnumerator AddPoi(string title, string description) { return CollectionExtensions.WrapToIl2Cpp(AddPoiInternal(title, description)); } private static IEnumerator AddPoiInternal(string title, string description) { UiManager.SetShowHud(false); yield return (object)new WaitForEndOfFrame(); Texture2D obj = ScreenCapture.CaptureScreenshotAsTexture(); UiManager.SetShowHud(true); Il2CppStructArray<byte> val = ImageConversion.EncodeToJPG(obj, 90); SotfEditPlayerHandler instance = SotfEditPlayerHandler.Instance; Vector3 lastPosition = instance.lastPosition; byte[] data = MessagePackSerializer.Serialize<ICompanionMessage>((ICompanionMessage)new CompanionAddPoiMessage { Title = title, Description = description, Screenshot = Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)val), X = lastPosition.x, Y = lastPosition.y, Z = lastPosition.z, AreaMask = instance.lastMask }, (MessagePackSerializerOptions)null, default(CancellationToken)); ConnectionHandler.Instance.BroadcastAsync(data); } public static IEnumerator LoadImage(string path, ConcurrentDictionary<string, Texture2D> imageCache) { imageCache[path] = null; return CollectionExtensions.WrapToIl2Cpp(LoadImageInternal(path, imageCache)); } private static IEnumerator LoadImageInternal(string path, ConcurrentDictionary<string, Texture2D> imageCache) { if (string.IsNullOrEmpty(path)) { yield break; } if (path.StartsWith("http") || path.StartsWith("https")) { UnityWebRequest request = UnityWebRequest.Get(path); yield return request.SendWebRequest(); if ((int)request.result == 1) { Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, request.downloadHandler.data); imageCache[path] = val; } } else { try { if (File.Exists(path)) { Texture2D val2 = new Texture2D(2, 2); ImageConversion.LoadImage(val2, File.ReadAllBytes(path)); imageCache[path] = val2; } } catch (Exception) { } } yield return null; } } public static class Inputs { public static void ToggleInputs(bool showDialog) { InputSystem.SetState((InputState)0, showDialog); Cursor.lockState = (CursorLockMode)((!showDialog) ? 1 : 0); Cursor.visible = showDialog; } } } namespace SOTFEdit_Companion.Dialogs { public class AddCoordsDialog : MonoBehaviour { private const string DisclaimerText = "Please enter the title and optionally a description for the POI"; private const string TitleText = "Title: "; private const string DescriptionText = "Description: "; private readonly Vector2 _dialogSize = new Vector2(400f, 130f); private string _description = ""; private Rect _dialogRect; private bool _displayDialog; private GUIStyle _greenButtonStyle; private GUIStyle _labelStyle; private GUIStyle _redButtonStyle; private string _title = ""; private void Awake() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) _dialogRect = new Rect(((float)Screen.width - _dialogSize.x) / 2f, ((float)Screen.height - _dialogSize.y) / 2f, _dialogSize.x, _dialogSize.y); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(Configuration.CustomPoiKey.Value)) { ShowDialog(); } } private void OnGUI() { //IL_000f: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (_displayDialog) { CreateStyles(); GUI.backgroundColor = Color.black; _dialogRect = GUI.Window(9998, _dialogRect, WindowFunction.op_Implicit((Action<int>)DialogWindow), "Add a POI"); } } private void CreateStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (_labelStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label); val.normal.textColor = Color.white; _labelStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.button); val2.normal.textColor = Color.white; GUIStyle val3 = val2; GUIStyle val4 = new GUIStyle(val3); val4.normal.background = MakeTex(2, 2, Color.green); _greenButtonStyle = val4; GUIStyle val5 = new GUIStyle(val3); val5.normal.background = MakeTex(2, 2, Color.red); _redButtonStyle = val5; } } public void DialogWindow(int windowID) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) GUILayout.TextField("Please enter the title and optionally a description for the POI", _labelStyle, Array.Empty<GUILayoutOption>()); _title = CreateTextField("Title: ", _title); _description = CreateTextField("Description: ", _description); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); if (GUILayout.Button("OK", _greenButtonStyle, (Il2CppReferenceArray<GUILayoutOption>)null)) { string title = _title; string description = _description; CloseDialog(); UnityMainThreadDispatcher.Enqueue(Coroutines.AddPoi(title, description)); } if (GUILayout.Button("Cancel", _redButtonStyle, (Il2CppReferenceArray<GUILayoutOption>)null)) { CloseDialog(); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private string CreateTextField(string label, string value) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label(label, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(_labelStyle.CalcSize(new GUIContent(label)).x) }); value = GUILayout.TextField(value, (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.EndHorizontal(); return value; } private void CloseDialog() { _title = ""; _description = ""; _displayDialog = false; Inputs.ToggleInputs(showDialog: false); } private static Texture2D MakeTex(int width, int height, Color col) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(Il2CppStructArray<Color>.op_Implicit(array)); val.Apply(); return val; } private void ShowDialog() { if ((_displayDialog || (SotfEditCompanionGameObject.IsPlayerAvailable() && !SotfEditCompanionGameObject.IsPaused() && !SotfEditCompanionGameObject.IsInInventory())) && ConnectionHandler.Instance.HasConnections) { _displayDialog = !_displayDialog; Inputs.ToggleInputs(_displayDialog); } } } public class ShowCoordsDialog : MonoBehaviour { private static readonly PoiGroupType[] SupportedPoiGroupTypes = PoiGroupTypeUtils.GetSupportedCompanionPoiGroupTypes(); private readonly Vector2 _dialogSize = new Vector2(600f, 800f); private readonly ConcurrentDictionary<string, Texture2D> _imageCache = new ConcurrentDictionary<string, Texture2D>(); private GUIStyle _descriptionStyle; private Rect _dialogRect; private bool _displayDialog; private Vector2 _dropdownPosition; private string _filter = ""; private GUIStyle _redButtonStyle; private Vector2 _scrollPosition; private bool _showDropdown; private GUIStyle _titleStyle; private void Awake() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) _dialogRect = new Rect(((float)Screen.width - _dialogSize.x) / 2f, ((float)Screen.height - _dialogSize.y) / 2f, _dialogSize.x, _dialogSize.y); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(Configuration.TeleportKey.Value)) { ShowDialog(); } } private void OnGUI() { //IL_000f: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (_displayDialog) { CreateStyles(); GUI.backgroundColor = Color.black; _dialogRect = GUI.Window(9999, _dialogRect, WindowFunction.op_Implicit((Action<int>)DialogWindow), "Custom POIs"); if (_showDropdown) { float num = (float)SupportedPoiGroupTypes.Length * 20f; Rect val = default(Rect); ((Rect)(ref val))..ctor(_dropdownPosition.x, _dropdownPosition.y, 100f, num); GUI.Window(9997, val, WindowFunction.op_Implicit((Action<int>)DropdownWindow), "Categories"); } } } public void DialogWindow(int windowID) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label("Filter: ", _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); _filter = GUILayout.TextField(_filter, (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); if (GUILayout.Button("Categories", (Il2CppReferenceArray<GUILayoutOption>)null)) { _showDropdown = !_showDropdown; _dropdownPosition = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); } GUILayout.EndHorizontal(); GUILayout.Space(10f); _scrollPosition = GUILayout.BeginScrollView(_scrollPosition, Array.Empty<GUILayoutOption>()); Texture2D val = default(Texture2D); foreach (CompanionPoiMessage item in CompanionPoiStorage.GetAllFiltered(_filter)) { GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); int num = 150; if (!string.IsNullOrEmpty(item.ScreenshotPath)) { if (_imageCache.TryGetValue(item.ScreenshotPath, ref val)) { num = (int)(((Object)(object)val == (Object)null) ? 113f : (200f * ((float)((Texture)val).height / (float)((Texture)val).width))); GUILayout.Box((Texture)(object)val, (GUILayoutOption[])(object)new GUILayoutOption[3] { GUILayout.Width(200f), GUILayout.Height((float)num), GUILayout.ExpandHeight(false) }); } else { ((MonoBehaviour)this).StartCoroutine(Coroutines.LoadImage(item.ScreenshotPath, _imageCache)); GUILayout.Label("Loading...", (GUILayoutOption[])(object)new GUILayoutOption[3] { GUILayout.Width(300f), GUILayout.Height(150f), GUILayout.ExpandHeight(false) }); } } else { GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[3] { GUILayout.Width(300f), GUILayout.Height(150f), GUILayout.ExpandHeight(false) }); } GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height((float)num) }); GUILayout.FlexibleSpace(); GUILayout.Label(item.Title, _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(false) }); GUILayout.Label(item.Description ?? "", _descriptionStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(false) }); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height((float)num), GUILayout.ExpandWidth(false) }); GUILayout.FlexibleSpace(); if (GUILayout.Button("Teleport", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false) })) { SotfEditPlayerHandler.TeleportTo(item.X, item.Y, item.Z, item.AreaMask); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(10f); } GUILayout.EndScrollView(); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); if (GUILayout.Button("Cancel", _redButtonStyle, (Il2CppReferenceArray<GUILayoutOption>)null)) { CloseDialog(); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void DropdownWindow(int windowID) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown PoiGroupType[] supportedPoiGroupTypes = SupportedPoiGroupTypes; for (int i = 0; i < supportedPoiGroupTypes.Length; i++) { PoiGroupType type = supportedPoiGroupTypes[i]; if (GUILayout.Button(((object)(PoiGroupType)(ref type)).ToString(), (Il2CppReferenceArray<GUILayoutOption>)null)) { _scrollPosition = default(Vector2); _filter = ""; ConnectionHandler.Instance.SendToFirstClientAsync(MessagePackSerializer.Serialize<ICompanionMessage>((ICompanionMessage)new CompanionRequestPoiUpdateMessage { Type = type }, (MessagePackSerializerOptions)null, default(CancellationToken))); _showDropdown = false; } } } private void CreateStyles() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (_redButtonStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.button); val.normal.textColor = Color.white; GUIStyle val2 = val; GUIStyle val3 = new GUIStyle(val2); val3.normal.background = MakeTex(2, 2, Color.red); _redButtonStyle = val3; _descriptionStyle = new GUIStyle(GUI.skin.label) { wordWrap = true }; GUIStyle val4 = new GUIStyle(GUI.skin.label) { wordWrap = true }; val4.normal.textColor = Color.green; _titleStyle = val4; } } private void CloseDialog() { _showDropdown = false; _displayDialog = false; Inputs.ToggleInputs(showDialog: false); } private static Texture2D MakeTex(int width, int height, Color col) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(Il2CppStructArray<Color>.op_Implicit(array)); val.Apply(); return val; } private void ShowDialog() { if ((_displayDialog || (SotfEditCompanionGameObject.IsPlayerAvailable() && !SotfEditCompanionGameObject.IsPaused() && !SotfEditCompanionGameObject.IsInInventory())) && ConnectionHandler.Instance.HasConnections) { _displayDialog = !_displayDialog; Inputs.ToggleInputs(_displayDialog); } } } } namespace SOTFEdit_Companion.Connection { public class ConnectionHandler { public delegate void EventHandler(); private WatsonWsServer _server; public static ConnectionHandler Instance { get; private set; } public bool HasConnections { get; private set; } public event EventHandler OnNoConnectionsOpen; public event EventHandler OnConnected; public ConnectionHandler() { Instance = this; } public void Initialize() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown if (_server == null) { MessagePackInitializer.Initialize(); _server = new WatsonWsServer(Configuration.ListenAddress.Value, Configuration.ListenPort.Value, false); _server.ClientConnected += OnClientConnected; _server.ClientDisconnected += OnClientDisconnected; _server.MessageReceived += MessageHandler.OnMessageReceived; } } private void OnClientDisconnected(object sender, DisconnectionEventArgs e) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Client "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((object)e.Client).ToString()); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" disconnected"); } SotfEditCompanionPlugin.Logger.LogInfo(val); if (!_server.ListClients().Any()) { HasConnections = false; val = new BepInExInfoLogInterpolatedStringHandler(29, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("All clients have disconnected"); } SotfEditCompanionPlugin.Logger.LogInfo(val); this.OnNoConnectionsOpen?.Invoke(); } } private void OnClientConnected(object sender, ConnectionEventArgs e) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Client "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((object)e.Client).ToString()); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" connected"); } SotfEditCompanionPlugin.Logger.LogInfo(val); HasConnections = true; this.OnConnected?.Invoke(); } public void Start() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown _server.Start(); bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Listening for SOTFEdit connection at "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Configuration.ListenAddress.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(":"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Configuration.ListenPort.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("..."); } SotfEditCompanionPlugin.Logger.LogInfo(val); } public void Shutdown() { if (_server.IsListening) { _server.Stop(); } } public void SendToFirstClientAsync(byte[] data) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown WatsonWsServer server = _server; if (server == null || !server.IsListening) { return; } ClientMetadata val = _server.ListClients().FirstOrDefault(); if (val == null) { return; } try { _server.SendAsync(val.Guid, data, WebSocketMessageType.Binary, default(CancellationToken)); } catch (Exception ex) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("An exception occured while sending a message: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message); } SotfEditCompanionPlugin.Logger.LogError(val2); } } public void BroadcastAsync(byte[] data) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown WatsonWsServer server = _server; if (server == null || !server.IsListening) { return; } bool flag = default(bool); foreach (ClientMetadata item in _server.ListClients()) { try { _server.SendAsync(item.Guid, data, WebSocketMessageType.Binary, default(CancellationToken)); } catch (Exception ex) { BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("An exception occured while sending a message: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message); } SotfEditCompanionPlugin.Logger.LogError(val); } } } } public static class MessageHandler { public static void OnMessageReceived(object sender, MessageReceivedEventArgs e) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown try { ICompanionMessage val = MessagePackSerializer.Deserialize<ICompanionMessage>((ReadOnlyMemory<byte>)e.Data, (MessagePackSerializerOptions)null, default(CancellationToken)); CompanionTeleportMessage val2 = (CompanionTeleportMessage)(object)((val is CompanionTeleportMessage) ? val : null); if (val2 == null) { CompanionPoiListMessage val3 = (CompanionPoiListMessage)(object)((val is CompanionPoiListMessage) ? val : null); if (val3 == null) { CompanionPoiMessage val4 = (CompanionPoiMessage)(object)((val is CompanionPoiMessage) ? val : null); if (val4 == null) { CompanionSettingsMessage val5 = (CompanionSettingsMessage)(object)((val is CompanionSettingsMessage) ? val : null); if (val5 != null) { ProcessSettings(val5); } } else { ProcessCompanionPoi(val4); } } else { ProcessCompanionPoiList(val3); } } else { ProcessTeleportation(val2); } } catch (Exception ex) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val6 = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Unable to deserialize message: "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(ex.Message); } SotfEditCompanionPlugin.Logger.LogError(val6); } } private static void ProcessSettings(CompanionSettingsMessage settings) { UnityMainThreadDispatcher.Enqueue(Action.op_Implicit((Action)delegate { ApplySettings(settings); })); } private static void ApplySettings(CompanionSettingsMessage settings) { SotfEditCompanionPlugin.Logger.LogInfo((object)"Applying settings received from SOTFEdit..."); if (settings.PositionUpdateFrequency > 0m) { SotfEditCompanionGameObject.Instance.timeBetweenUpdates = (float)settings.PositionUpdateFrequency; } } private static void ProcessCompanionPoi(CompanionPoiMessage companionPoi) { CompanionPoiStorage.Add(companionPoi); } private static void ProcessCompanionPoiList(CompanionPoiListMessage poiListMessage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) CompanionPoiStorage.Replace(poiListMessage.Type, poiListMessage.Pois); } private static void ProcessTeleportation(CompanionTeleportMessage message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) CharacterTarget target = message.Target; switch ((int)target) { case 0: SotfEditPlayerHandler.TeleportTo(message.X, message.Y, message.Z, message.AreaMask); return; case 1: SotfEditFollowerHandler.TeleportKelvinTo(message.X, message.Y, message.Z, message.AreaMask, message.GraphMask); return; case 2: SotfEditFollowerHandler.TeleportVirginiaTo(message.X, message.Y, message.Z, message.AreaMask, message.GraphMask); return; } bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(34, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unsupported teleportation target: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<CharacterTarget>(message.Target); } SotfEditCompanionPlugin.Logger.LogWarning(val); } } } namespace SOTFEdit_Companion.Behaviors { public static class BehaviourUtils { public static bool IsValid(Behaviour behaviour) { if (Object.op_Implicit((Object)(object)behaviour)) { return behaviour.isActiveAndEnabled; } return false; } } public class SotfEditCompanionGameObject : MonoBehaviour { public SotfEditPlayerHandler playerHandler; public SotfEditFollowerHandler followerHandler; public float timeBetweenUpdates = 0.1f; private readonly IEnumerator _collector; private bool _hasConnections; public ConnectionHandler ConnectionHandler; public static SotfEditCompanionGameObject Instance { get; private set; } public SotfEditCompanionGameObject() { Instance = this; _collector = Coroutines.CollectAndSendPositions(this); } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } ((Component)this).gameObject.AddComponent<UnityMainThreadDispatcher>(); playerHandler = ((Component)this).gameObject.AddComponent<SotfEditPlayerHandler>(); followerHandler = ((Component)this).gameObject.AddComponent<SotfEditFollowerHandler>(); ((Component)this).gameObject.AddComponent<AddCoordsDialog>(); ((Component)this).gameObject.AddComponent<ShowCoordsDialog>(); ConnectionHandler = new ConnectionHandler(); ConnectionHandler.Initialize(); ConnectionHandler.OnConnected += OnConnected; ConnectionHandler.OnNoConnectionsOpen += OnNoConnectionsOpen; } private void Start() { ConnectionHandler.Start(); } private void OnDestroy() { ConnectionHandler?.Shutdown(); Instance = null; } private void OnNoConnectionsOpen() { UnityMainThreadDispatcher.Enqueue(Action.op_Implicit((Action)StopCollecting)); } private void StopCollecting() { if (_hasConnections) { _hasConnections = false; ((MonoBehaviour)this).StopCoroutine(_collector); } playerHandler.StopCollecting(); followerHandler.StopCollecting(); } private void OnConnected() { UnityMainThreadDispatcher.Enqueue(Action.op_Implicit((Action)StartCollecting)); NetworkPlayerManager.ForceNetworkPlayerBroadcast = true; } private void StartCollecting() { if (!_hasConnections) { ((MonoBehaviour)this).StartCoroutine(_collector); _hasConnections = true; } playerHandler.StartCollecting(); followerHandler.StartCollecting(); } public static bool IsPlayerAvailable() { if (IsInGame()) { return BehaviourUtils.IsValid((Behaviour)(object)LocalPlayer._instance); } return false; } private static bool IsInGame() { return LocalPlayer.IsInWorld; } public static bool IsInInventory() { return LocalPlayer.IsInInventory; } public static bool IsPaused() { return PauseMenu.IsActive; } } public class SotfEditFollowerHandler : MonoBehaviour { public VailActor kelvinActor; public VailActor virginiaActor; private readonly IEnumerator _followerFinder; public readonly FollowerState KelvinState = new FollowerState(); public readonly FollowerState VirginiaState = new FollowerState(); public static SotfEditFollowerHandler Instance { get; private set; } public SotfEditFollowerHandler() { _followerFinder = Coroutines.FindActors(this); } private void Awake() { Instance = this; } private void OnDestroy() { StopCollecting(); Instance = null; } public void RefreshLocations() { if (!MustFindKelvin()) { KelvinState.UpdateLocation(kelvinActor); } if (!MustFindVirginia()) { VirginiaState.UpdateLocation(virginiaActor); } } public bool MustFindKelvin() { return !BehaviourUtils.IsValid((Behaviour)(object)kelvinActor); } public bool MustFindVirginia() { return !BehaviourUtils.IsValid((Behaviour)(object)virginiaActor); } public void StopCollecting() { ((MonoBehaviour)this).StopCoroutine(_followerFinder); } public void StartCollecting() { ((MonoBehaviour)this).StartCoroutine(_followerFinder); } public static void TeleportKelvinTo(float x, float y, float z, int areaMask, int graphMask) { UnityMainThreadDispatcher.Enqueue(Actions.TeleportKelvin(x, y, z, areaMask, graphMask)); } public static void TeleportVirginiaTo(float x, float y, float z, int areaMask, int graphMask) { UnityMainThreadDispatcher.Enqueue(Actions.TeleportVirginia(x, y, z, areaMask, graphMask)); } } public class SotfEditPlayerHandler : MonoBehaviour { public Vector3 lastPosition; public int lastMask; public PlayerLocation playerLocation; public float lastRotation; private readonly IEnumerator _playerFinder; public static SotfEditPlayerHandler Instance { get; private set; } public SotfEditPlayerHandler() { _playerFinder = Coroutines.FindPlayers(this); } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } } private void OnDestroy() { StopCollecting(); Instance = null; } public void RefreshLocation() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (SotfEditCompanionGameObject.IsPlayerAvailable() && BehaviourUtils.IsValid((Behaviour)(object)playerLocation)) { Transform transform = ((Component)playerLocation).transform; lastPosition = transform.position; Quaternion rotation = transform.rotation; lastRotation = ((Quaternion)(ref rotation)).eulerAngles.y; lastMask = playerLocation.AreaMask; } } public void StopCollecting() { ((MonoBehaviour)this).StopCoroutine(_playerFinder); } public void StartCollecting() { ((MonoBehaviour)this).StartCoroutine(_playerFinder); } public static void TeleportTo(float x, float y, float z, int areaMask) { UnityMainThreadDispatcher.Enqueue(Actions.TeleportPlayer(x, y, z, areaMask)); } } public class UnityMainThreadDispatcher : MonoBehaviour { private static readonly Queue<IEnumerator> ExecutionQueue = new Queue<IEnumerator>(); public void Update() { lock (ExecutionQueue) { while (ExecutionQueue.Count > 0) { ((MonoBehaviour)this).StartCoroutine(ExecutionQueue.Dequeue()); } } } public static void Enqueue(IEnumerator action) { lock (ExecutionQueue) { ExecutionQueue.Enqueue(action); } } public static void Enqueue(Action action) { Enqueue(Coroutines.WrapAction(action)); } } }
BepInEx/plugins/SOTFEdit_Companion/WatsonWebsocket.dll
Decompiled 9 months agousing System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Joel Christner")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("(c)2023 Joel Christner")] [assembly: AssemblyDescription("WatsonWebsocket is the EASIEST and FASTEST way to build client and server applications that rely on messaging using websockets. It's. Really. Easy.")] [assembly: AssemblyFileVersion("4.0.9.0")] [assembly: AssemblyInformationalVersion("4.0.9")] [assembly: AssemblyProduct("WatsonWebsocket")] [assembly: AssemblyTitle("WatsonWebsocket")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/jchristn/WatsonWebsocket")] [assembly: AssemblyVersion("4.0.9.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace WatsonWebsocket { public class ClientMetadata { internal HttpListenerContext HttpContext; internal WebSocket Ws; internal WebSocketContext WsContext; internal readonly CancellationTokenSource TokenSource; internal readonly SemaphoreSlim SendLock = new SemaphoreSlim(1); public Guid Guid { get; } = Guid.NewGuid(); public string IpPort => Ip + ":" + Port; public string Ip { get; } public int Port { get; } public string Name { get; set; } public object Metadata { get; set; } public ClientMetadata(HttpListenerContext httpContext, WebSocket ws, WebSocketContext wsContext, CancellationTokenSource tokenSource) { HttpContext = httpContext ?? throw new ArgumentNullException("httpContext"); Ws = ws ?? throw new ArgumentNullException("ws"); WsContext = wsContext ?? throw new ArgumentNullException("wsContext"); TokenSource = tokenSource ?? throw new ArgumentNullException("tokenSource"); Ip = HttpContext.Request.RemoteEndPoint.Address.ToString(); Port = HttpContext.Request.RemoteEndPoint.Port; } public override string ToString() { string text = "["; text = text + Guid.ToString() + "|" + IpPort; if (!string.IsNullOrEmpty(Name)) { text = text + "|" + Name; } return text + "]"; } } public class ConnectionEventArgs : EventArgs { public ClientMetadata Client { get; } public HttpListenerRequest HttpRequest { get; } internal ConnectionEventArgs(ClientMetadata client, HttpListenerRequest http) { Client = client; HttpRequest = http; } } public class DisconnectionEventArgs : EventArgs { public ClientMetadata Client { get; } internal DisconnectionEventArgs(ClientMetadata client) { Client = client; } } public class MessageReceivedEventArgs : EventArgs { public WebSocketMessageType MessageType = WebSocketMessageType.Binary; public ClientMetadata Client { get; } public ArraySegment<byte> Data { get; } internal MessageReceivedEventArgs(ClientMetadata client, ArraySegment<byte> data, WebSocketMessageType messageType) { Client = client; Data = data; MessageType = messageType; } } public class Statistics { private DateTime _StartTime = DateTime.Now.ToUniversalTime(); private long _ReceivedBytes; private long _ReceivedMessages; private long _SentBytes; private long _SentMessages; public DateTime StartTime => _StartTime; public TimeSpan UpTime => DateTime.Now.ToUniversalTime() - _StartTime; public long ReceivedBytes => _ReceivedBytes; public long ReceivedMessages => _ReceivedMessages; public int ReceivedMessageSizeAverage { get { if (_ReceivedBytes > 0 && _ReceivedMessages > 0) { return (int)(_ReceivedBytes / _ReceivedMessages); } return 0; } } public long SentBytes => _SentBytes; public long SentMessages => _SentMessages; public decimal SentMessageSizeAverage { get { if (_SentBytes > 0 && _SentMessages > 0) { return (int)(_SentBytes / _SentMessages); } return 0m; } } public override string ToString() { return "--- Statistics ---" + Environment.NewLine + " Started : " + _StartTime.ToString() + Environment.NewLine + " Uptime : " + UpTime.ToString() + Environment.NewLine + " Received : " + Environment.NewLine + " Bytes : " + ReceivedBytes + Environment.NewLine + " Messages : " + ReceivedMessages + Environment.NewLine + " Average : " + ReceivedMessageSizeAverage + " bytes" + Environment.NewLine + " Sent : " + Environment.NewLine + " Bytes : " + SentBytes + Environment.NewLine + " Messages : " + SentMessages + Environment.NewLine + " Average : " + SentMessageSizeAverage + " bytes" + Environment.NewLine; } public void Reset() { _ReceivedBytes = 0L; _ReceivedMessages = 0L; _SentBytes = 0L; _SentMessages = 0L; } internal void IncrementReceivedMessages() { _ReceivedMessages = Interlocked.Increment(ref _ReceivedMessages); } internal void IncrementSentMessages() { _SentMessages = Interlocked.Increment(ref _SentMessages); } internal void AddReceivedBytes(long bytes) { _ReceivedBytes = Interlocked.Add(ref _ReceivedBytes, bytes); } internal void AddSentBytes(long bytes) { _SentBytes = Interlocked.Add(ref _SentBytes, bytes); } } public class WatsonWsClient : IDisposable { public Action<string> Logger; private string _Header = "[WatsonWsClient] "; private bool _AcceptInvalidCertificates = true; private Uri _ServerUri; private string _ServerIp; private int _ServerPort; private string _ServerIpPort; private string _Url; private int _KeepAliveIntervalSeconds = 30; private ClientWebSocket _ClientWs; private CookieContainer _Cookies = new CookieContainer(); private Action<ClientWebSocketOptions> _PreConfigureOptions; private readonly SemaphoreSlim _SendLock = new SemaphoreSlim(1); private readonly SemaphoreSlim _AwaitingSyncResposeLock = new SemaphoreSlim(1); private CancellationTokenSource _TokenSource = new CancellationTokenSource(); private CancellationToken _Token; private Statistics _Stats = new Statistics(); private readonly bool _IsBrowser = RuntimeInformation.RuntimeIdentifier == "browser-wasm"; public bool AcceptInvalidCertificates { get { return _AcceptInvalidCertificates; } set { _AcceptInvalidCertificates = value; } } public bool Connected { get { if (_ClientWs != null && _ClientWs.State == WebSocketState.Open) { return true; } return false; } } public bool EnableStatistics { get; set; } = true; [UnsupportedOSPlatform("browser")] public int KeepAliveInterval { get { if (_IsBrowser) { throw new PlatformNotSupportedException(); } return _KeepAliveIntervalSeconds; } set { if (_IsBrowser) { throw new PlatformNotSupportedException(); } if (value < 1) { throw new ArgumentException("ConnectTimeoutSeconds must be greater than zero."); } _KeepAliveIntervalSeconds = value; } } public Statistics Stats => _Stats; public event EventHandler<MessageReceivedEventArgs> MessageReceived; public event EventHandler ServerConnected; public event EventHandler ServerDisconnected; private event EventHandler<MessageReceivedEventArgs> _AwaitingSyncResponseEvent; public WatsonWsClient(string serverIp, int serverPort, bool ssl) { if (string.IsNullOrEmpty(serverIp)) { throw new ArgumentNullException("serverIp"); } if (serverPort < 1) { throw new ArgumentOutOfRangeException("serverPort"); } _ServerIp = serverIp; _ServerPort = serverPort; _ServerIpPort = serverIp + ":" + serverPort; if (ssl) { _Url = "wss://" + _ServerIp + ":" + _ServerPort; } else { _Url = "ws://" + _ServerIp + ":" + _ServerPort; } _ServerUri = new Uri(_Url); _Token = _TokenSource.Token; _ClientWs = new ClientWebSocket(); } public WatsonWsClient(Uri uri) { _ServerUri = uri; _ServerIp = uri.Host; _ServerPort = uri.Port; _ServerIpPort = uri.Host + ":" + uri.Port; _Token = _TokenSource.Token; _ClientWs = new ClientWebSocket(); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } [UnsupportedOSPlatform("browser")] public WatsonWsClient ConfigureOptions(Action<ClientWebSocketOptions> options) { if (_IsBrowser) { throw new PlatformNotSupportedException(); } if (!Connected) { _PreConfigureOptions = options; } return this; } [UnsupportedOSPlatform("browser")] public void AddCookie(Cookie cookie) { if (_IsBrowser) { throw new PlatformNotSupportedException(); } _Cookies.Add(cookie); } public void Start() { _Stats = new Statistics(); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } if (!_IsBrowser) { _ClientWs.Options.Cookies = _Cookies; _ClientWs.Options.KeepAliveInterval = TimeSpan.FromSeconds(_KeepAliveIntervalSeconds); if (_PreConfigureOptions != null) { _PreConfigureOptions(_ClientWs.Options); } } _ClientWs.ConnectAsync(_ServerUri, _Token).ContinueWith(AfterConnect).Wait(); } public Task StartAsync() { _Stats = new Statistics(); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } if (!_IsBrowser) { _ClientWs.Options.Cookies = _Cookies; _ClientWs.Options.KeepAliveInterval = TimeSpan.FromSeconds(_KeepAliveIntervalSeconds); if (_PreConfigureOptions != null) { _PreConfigureOptions(_ClientWs.Options); } } return _ClientWs.ConnectAsync(_ServerUri, _Token).ContinueWith(AfterConnect); } public bool StartWithTimeout(int timeout = 30, CancellationToken token = default(CancellationToken)) { if (timeout < 1) { throw new ArgumentException("Timeout must be greater than zero seconds."); } _Stats = new Statistics(); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } Stopwatch stopwatch = new Stopwatch(); TimeSpan timeSpan = TimeSpan.FromSeconds(timeout); stopwatch.Start(); try { while (stopwatch.Elapsed < timeSpan && !token.IsCancellationRequested) { _ClientWs = new ClientWebSocket(); if (!_IsBrowser) { _ClientWs.Options.Cookies = _Cookies; _ClientWs.Options.KeepAliveInterval = TimeSpan.FromSeconds(_KeepAliveIntervalSeconds); if (_PreConfigureOptions != null) { _PreConfigureOptions(_ClientWs.Options); } } try { _ClientWs.ConnectAsync(_ServerUri, token).ContinueWith(AfterConnect).Wait(); } catch (TaskCanceledException) { return false; } catch (OperationCanceledException) { return false; } catch (WebSocketException) { } Task.Delay(100).Wait(); if (_ClientWs.State == WebSocketState.Open) { return true; } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { } return false; } public async Task<bool> StartWithTimeoutAsync(int timeout = 30, CancellationToken token = default(CancellationToken)) { if (timeout < 1) { throw new ArgumentException("Timeout must be greater than zero seconds."); } _Stats = new Statistics(); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } Stopwatch sw = new Stopwatch(); TimeSpan timeOut = TimeSpan.FromSeconds(timeout); sw.Start(); try { while (sw.Elapsed < timeOut && !token.IsCancellationRequested) { _ClientWs = new ClientWebSocket(); if (!_IsBrowser) { _ClientWs.Options.Cookies = _Cookies; _ClientWs.Options.KeepAliveInterval = TimeSpan.FromSeconds(_KeepAliveIntervalSeconds); if (_PreConfigureOptions != null) { _PreConfigureOptions(_ClientWs.Options); } } try { await _ClientWs.ConnectAsync(_ServerUri, token).ContinueWith(AfterConnect); } catch (TaskCanceledException) { return false; } catch (OperationCanceledException) { return false; } catch (WebSocketException) { } await Task.Delay(100); if (_ClientWs.State == WebSocketState.Open) { return true; } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { } return false; } public void Stop() { Stop(WebSocketCloseStatus.NormalClosure, _ClientWs.CloseStatusDescription); } public async Task StopAsync() { await StopAsync(WebSocketCloseStatus.NormalClosure, _ClientWs.CloseStatusDescription); } public void Stop(WebSocketCloseStatus closeCode, string reason) { _ClientWs.CloseOutputAsync(closeCode, reason, _Token).Wait(); } public async Task StopAsync(WebSocketCloseStatus closeCode, string reason) { await _ClientWs.CloseOutputAsync(closeCode, reason, _Token).ConfigureAwait(continueOnCapturedContext: false); } public async Task<bool> SendAsync(string data, WebSocketMessageType msgType = WebSocketMessageType.Text, CancellationToken token = default(CancellationToken)) { if (string.IsNullOrEmpty(data)) { throw new ArgumentNullException("data"); } return await MessageWriteAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(data)), msgType, token); } public async Task<bool> SendAsync(byte[] data, WebSocketMessageType msgType = WebSocketMessageType.Binary, CancellationToken token = default(CancellationToken)) { return await MessageWriteAsync(new ArraySegment<byte>(data), msgType, token); } public async Task<bool> SendAsync(ArraySegment<byte> data, WebSocketMessageType msgType = WebSocketMessageType.Binary, CancellationToken token = default(CancellationToken)) { if (data.Array == null || data.Count < 1) { throw new ArgumentNullException("data"); } return await MessageWriteAsync(data, msgType, token); } public async Task<string> SendAndWaitAsync(string data, int timeout = 30, CancellationToken token = default(CancellationToken)) { if (string.IsNullOrEmpty(data)) { throw new ArgumentNullException("data"); } if (timeout < 1) { throw new ArgumentException("Timeout must be greater than zero seconds.", "data"); } string result = null; ManualResetEvent receivedEvent = new ManualResetEvent(initialState: false); await _AwaitingSyncResposeLock.WaitAsync(_Token); await Task.Run(async delegate { _AwaitingSyncResponseEvent += delegate(object? s, MessageReceivedEventArgs e) { result = Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count); receivedEvent.Set(); }; await MessageWriteAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(data)), WebSocketMessageType.Text, token); receivedEvent.WaitOne(TimeSpan.FromSeconds(timeout)); this._AwaitingSyncResponseEvent = null; _AwaitingSyncResposeLock.Release(); }); return result; } public async Task<ArraySegment<byte>> SendAndWaitAsync(byte[] data, int timeout = 30, CancellationToken token = default(CancellationToken)) { return await SendAndWaitAsync(new ArraySegment<byte>(data), timeout, token); } public async Task<ArraySegment<byte>> SendAndWaitAsync(ArraySegment<byte> data, int timeout = 30, CancellationToken token = default(CancellationToken)) { if (data.Array == null || data.Count < 1) { throw new ArgumentNullException("data"); } if (timeout < 1) { throw new ArgumentException("Timeout must be zero or greater.", "data"); } ArraySegment<byte> result = default(ArraySegment<byte>); ManualResetEvent receivedEvent = new ManualResetEvent(initialState: false); await _AwaitingSyncResposeLock.WaitAsync(_Token); await Task.Run(async delegate { _AwaitingSyncResponseEvent += delegate(object? s, MessageReceivedEventArgs e) { result = e.Data; receivedEvent.Set(); }; await MessageWriteAsync(data, WebSocketMessageType.Binary, token); receivedEvent.WaitOne(TimeSpan.FromSeconds(timeout)); this._AwaitingSyncResponseEvent = null; _AwaitingSyncResposeLock.Release(); }); return result; } protected virtual void Dispose(bool disposing) { if (disposing) { if (_ClientWs != null && _ClientWs.State == WebSocketState.Open) { Stop(); _ClientWs.Dispose(); } _TokenSource.Cancel(); Logger?.Invoke(_Header + "dispose complete"); } } private void SetInvalidCertificateAcceptance() { if (_ClientWs.State == WebSocketState.Open) { ClientWebSocketOptions options = _ClientWs.Options; options.RemoteCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(options.RemoteCertificateValidationCallback, (RemoteCertificateValidationCallback)((object message, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) => true)); } } private void AfterConnect(Task task) { if (!task.IsCompleted || _ClientWs.State != WebSocketState.Open) { return; } Task.Run(delegate { Task.Run(() => DataReceiver(), _Token); this.ServerConnected?.Invoke(this, EventArgs.Empty); }, _Token); } private async Task DataReceiver() { byte[] buffer = new byte[65536]; try { while (!_Token.IsCancellationRequested) { MessageReceivedEventArgs messageReceivedEventArgs = await MessageReadAsync(buffer); if (messageReceivedEventArgs == null) { continue; } if (EnableStatistics) { _Stats.IncrementReceivedMessages(); _Stats.AddReceivedBytes(messageReceivedEventArgs.Data.Count); } if (messageReceivedEventArgs.MessageType != WebSocketMessageType.Close) { if (this._AwaitingSyncResponseEvent != null) { this._AwaitingSyncResponseEvent?.Invoke(this, messageReceivedEventArgs); } else { this.MessageReceived?.Invoke(this, messageReceivedEventArgs); } } } } catch (OperationCanceledException) { Logger?.Invoke(_Header + "data receiver canceled"); } catch (WebSocketException) { Logger?.Invoke(_Header + "websocket disconnected"); } catch (Exception ex3) { Logger?.Invoke(_Header + "exception: " + Environment.NewLine + ex3.ToString()); } this.ServerDisconnected?.Invoke(this, EventArgs.Empty); } private async Task<MessageReceivedEventArgs> MessageReadAsync(byte[] buffer) { if (_ClientWs == null) { return null; } ArraySegment<byte> data = default(ArraySegment<byte>); WebSocketReceiveResult result = null; using (MemoryStream dataMs = new MemoryStream()) { buffer = new byte[buffer.Length]; ArraySegment<byte> bufferSegment = new ArraySegment<byte>(buffer); if (_ClientWs.State == WebSocketState.CloseReceived || _ClientWs.State == WebSocketState.Closed) { throw new WebSocketException("Websocket close received"); } while (_ClientWs.State == WebSocketState.Open) { result = await _ClientWs.ReceiveAsync(bufferSegment, _Token); if (result.Count > 0) { await dataMs.WriteAsync(buffer, 0, result.Count); } if (result.EndOfMessage) { data = new ArraySegment<byte>(dataMs.GetBuffer(), 0, (int)dataMs.Length); break; } } } return new MessageReceivedEventArgs(null, data, result.MessageType); } private async Task<bool> MessageWriteAsync(ArraySegment<byte> data, WebSocketMessageType msgType, CancellationToken token) { bool disconnectDetected = false; using (CancellationTokenSource.CreateLinkedTokenSource(_Token, token)) { _ = 1; try { if (_ClientWs == null || _ClientWs.State != WebSocketState.Open) { Logger?.Invoke(_Header + "not connected"); disconnectDetected = true; return false; } await _SendLock.WaitAsync(_Token).ConfigureAwait(continueOnCapturedContext: false); try { await _ClientWs.SendAsync(data, msgType, endOfMessage: true, token).ConfigureAwait(continueOnCapturedContext: false); } catch { } finally { _SendLock.Release(); } if (EnableStatistics) { _Stats.IncrementSentMessages(); _Stats.AddSentBytes(data.Count); } return true; } catch (TaskCanceledException) { if (_Token.IsCancellationRequested) { Logger?.Invoke(_Header + "canceled"); disconnectDetected = true; } else if (token.IsCancellationRequested) { Logger?.Invoke(_Header + "message send canceled"); } return false; } catch (OperationCanceledException) { if (_Token.IsCancellationRequested) { Logger?.Invoke(_Header + "canceled"); disconnectDetected = true; } else if (token.IsCancellationRequested) { Logger?.Invoke(_Header + "message send canceled"); } return false; } catch (WebSocketException) { Logger?.Invoke(_Header + "websocket disconnected"); disconnectDetected = true; return false; } catch (ObjectDisposedException) { Logger?.Invoke(_Header + "disposed"); disconnectDetected = true; return false; } catch (SocketException) { Logger?.Invoke(_Header + "socket disconnected"); disconnectDetected = true; return false; } catch (InvalidOperationException) { Logger?.Invoke(_Header + "disconnected due to invalid operation"); disconnectDetected = true; return false; } catch (IOException) { Logger?.Invoke(_Header + "IO disconnected"); disconnectDetected = true; return false; } catch (Exception ex8) { Logger?.Invoke(_Header + "exception: " + Environment.NewLine + ex8.ToString()); disconnectDetected = true; return false; } finally { if (disconnectDetected) { Dispose(); this.ServerDisconnected?.Invoke(this, EventArgs.Empty); } } } } } public class WatsonWsServer : IDisposable { public List<string> PermittedIpAddresses = new List<string>(); public Action<string> Logger; public Action<HttpListenerContext> HttpHandler; private string _Header = "[WatsonWsServer] "; private bool _AcceptInvalidCertificates = true; private List<string> _ListenerPrefixes = new List<string>(); private HttpListener _Listener; private readonly object _PermittedIpsLock = new object(); private ConcurrentDictionary<Guid, ClientMetadata> _Clients = new ConcurrentDictionary<Guid, ClientMetadata>(); private CancellationTokenSource _TokenSource = new CancellationTokenSource(); private CancellationToken _Token; private Task _AcceptConnectionsTask; private Statistics _Stats = new Statistics(); public bool IsListening { get { if (_Listener != null) { return _Listener.IsListening; } return false; } } public bool EnableStatistics { get; set; } = true; public bool AcceptInvalidCertificates { get { return _AcceptInvalidCertificates; } set { _AcceptInvalidCertificates = value; } } public Statistics Stats => _Stats; public event EventHandler<ConnectionEventArgs> ClientConnected; public event EventHandler<DisconnectionEventArgs> ClientDisconnected; public event EventHandler ServerStopped; public event EventHandler<MessageReceivedEventArgs> MessageReceived; public WatsonWsServer(string hostname = "localhost", int port = 9000, bool ssl = false) { if (port < 0) { throw new ArgumentOutOfRangeException("port"); } if (string.IsNullOrEmpty(hostname)) { hostname = "localhost"; } if (ssl) { _ListenerPrefixes.Add("https://" + hostname + ":" + port + "/"); } else { _ListenerPrefixes.Add("http://" + hostname + ":" + port + "/"); } _Listener = new HttpListener(); foreach (string listenerPrefix in _ListenerPrefixes) { _Listener.Prefixes.Add(listenerPrefix); } _Token = _TokenSource.Token; } public WatsonWsServer(List<string> hostnames, int port, bool ssl = false) { if (port < 0) { throw new ArgumentOutOfRangeException("port"); } if (hostnames == null) { throw new ArgumentNullException("hostnames"); } if (hostnames.Count < 1) { throw new ArgumentException("At least one hostname must be supplied."); } foreach (string hostname in hostnames) { if (ssl) { _ListenerPrefixes.Add("https://" + hostname + ":" + port + "/"); } else { _ListenerPrefixes.Add("http://" + hostname + ":" + port + "/"); } } _Listener = new HttpListener(); foreach (string listenerPrefix in _ListenerPrefixes) { _Listener.Prefixes.Add(listenerPrefix); } _Token = _TokenSource.Token; } public WatsonWsServer(Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } if (uri.Port < 0) { throw new ArgumentException("Port must be zero or greater."); } string host; if (!IPAddress.TryParse(uri.Host, out IPAddress _)) { IPHostEntry hostEntry = Dns.GetHostEntry(uri.Host); if (hostEntry.AddressList.Length == 0) { throw new ArgumentException("Cannot resolve address to IP."); } host = hostEntry.AddressList.First().ToString(); } else { host = uri.Host; } UriBuilder uriBuilder = new UriBuilder(uri) { Host = host }; _ListenerPrefixes.Add(uriBuilder.ToString()); _Listener = new HttpListener(); foreach (string listenerPrefix in _ListenerPrefixes) { _Listener.Prefixes.Add(listenerPrefix); } _Token = _TokenSource.Token; } public void Dispose() { Dispose(disposing: true); } public void Start() { if (IsListening) { throw new InvalidOperationException("Watson websocket server is already running."); } _Stats = new Statistics(); string text = _Header + "starting on:"; foreach (string listenerPrefix in _ListenerPrefixes) { text = text + " " + listenerPrefix; } Logger?.Invoke(text); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } _TokenSource = new CancellationTokenSource(); _Token = _TokenSource.Token; _Listener.Start(); _AcceptConnectionsTask = Task.Run(() => AcceptConnections(_Token), _Token); } public Task StartAsync(CancellationToken token = default(CancellationToken)) { if (IsListening) { throw new InvalidOperationException("Watson websocket server is already running."); } _Stats = new Statistics(); string text = _Header + "starting on:"; foreach (string listenerPrefix in _ListenerPrefixes) { text = text + " " + listenerPrefix; } Logger?.Invoke(text); if (_AcceptInvalidCertificates) { SetInvalidCertificateAcceptance(); } _TokenSource = CancellationTokenSource.CreateLinkedTokenSource(token); _Token = token; _Listener.Start(); _AcceptConnectionsTask = Task.Run(() => AcceptConnections(_Token), _Token); return Task.Delay(1); } public void Stop() { if (!IsListening) { throw new InvalidOperationException("Watson websocket server is not running."); } Logger?.Invoke(_Header + "stopping"); _Listener.Stop(); } public Task<bool> SendAsync(Guid guid, string data, WebSocketMessageType msgType = WebSocketMessageType.Text, CancellationToken token = default(CancellationToken)) { if (string.IsNullOrEmpty(data)) { data = ""; } return SendAsync(guid, Encoding.UTF8.GetBytes(data), msgType, token); } public Task<bool> SendAsync(Guid guid, byte[] data, WebSocketMessageType msgType = WebSocketMessageType.Binary, CancellationToken token = default(CancellationToken)) { if (data == null) { data = new byte[0]; } return SendAsync(guid, new ArraySegment<byte>(data), msgType, token); } public Task<bool> SendAsync(Guid guid, ArraySegment<byte> data, WebSocketMessageType msgType = WebSocketMessageType.Binary, CancellationToken token = default(CancellationToken)) { if (data.Array == null || data.Count < 1) { throw new ArgumentNullException("data"); } if (!_Clients.TryGetValue(guid, out var value)) { Logger?.Invoke(_Header + "unable to find client " + guid); return Task.FromResult(result: false); } Task<bool> result = MessageWriteAsync(value, data, msgType, token); value = null; return result; } public bool IsClientConnected(Guid guid) { return _Clients.Any((KeyValuePair<Guid, ClientMetadata> c) => c.Key.Equals(guid)); } public IEnumerable<ClientMetadata> ListClients() { return _Clients.Values; } public void DisconnectClient(Guid guid) { if (_Clients.TryGetValue(guid, out var value)) { lock (value) { value.Ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", value.TokenSource.Token).Wait(); value.TokenSource.Cancel(); value.Ws.Dispose(); } } } public TaskAwaiter GetAwaiter() { return _AcceptConnectionsTask.GetAwaiter(); } protected virtual void Dispose(bool disposing) { if (!disposing) { return; } if (_Clients != null) { foreach (KeyValuePair<Guid, ClientMetadata> client in _Clients) { client.Value.Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", client.Value.TokenSource.Token); client.Value.TokenSource.Cancel(); } } if (_Listener != null) { if (_Listener.IsListening) { _Listener.Stop(); } _Listener.Close(); } _TokenSource.Cancel(); } private void SetInvalidCertificateAcceptance() { ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, (RemoteCertificateValidationCallback)((object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) => true)); } private async Task AcceptConnections(CancellationToken cancelToken) { bool exiting = false; while (!cancelToken.IsCancellationRequested) { try { if (!_Listener.IsListening) { Task.Delay(100).Wait(); continue; } HttpListenerContext ctx = await _Listener.GetContextAsync().ConfigureAwait(continueOnCapturedContext: false); string text = ctx.Request.RemoteEndPoint.Address.ToString(); string ipPort = text + ":" + ctx.Request.RemoteEndPoint.Port; lock (_PermittedIpsLock) { if (PermittedIpAddresses != null && PermittedIpAddresses.Count > 0 && !PermittedIpAddresses.Contains(text)) { Logger?.Invoke(_Header + "rejecting " + ipPort + " (not permitted)"); ctx.Response.StatusCode = 401; ctx.Response.Close(); continue; } } if (ctx.Request.IsWebSocketRequest) { await Task.Run(delegate { Logger?.Invoke(_Header + "starting data receiver for " + ipPort); CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; Task.Run(async delegate { WebSocketContext webSocketContext = await ctx.AcceptWebSocketAsync(null); WebSocket webSocket = webSocketContext.WebSocket; ClientMetadata md = new ClientMetadata(ctx, webSocket, webSocketContext, tokenSource); _Clients.TryAdd(md.Guid, md); this.ClientConnected?.Invoke(this, new ConnectionEventArgs(md, ctx.Request)); await Task.Run(() => DataReceiver(md), token); }, token); }, _Token).ConfigureAwait(continueOnCapturedContext: false); } else if (HttpHandler == null) { Logger?.Invoke(_Header + "non-websocket request rejected from " + ipPort); ctx.Response.StatusCode = 400; ctx.Response.Close(); } else { Logger?.Invoke(_Header + "non-websocket request from " + ipPort + " HTTP-forwarded: " + ctx.Request.HttpMethod.ToString() + " " + ctx.Request.RawUrl); HttpHandler(ctx); } } catch (TaskCanceledException) { exiting = true; break; } catch (OperationCanceledException) { exiting = true; break; } catch (ObjectDisposedException) { exiting = true; break; } catch (HttpListenerException) { exiting = true; break; } catch (Exception ex5) { Logger?.Invoke(_Header + "listener exception:" + Environment.NewLine + ex5.ToString()); } finally { if (exiting) { Logger?.Invoke(_Header + "listener stopped"); this.ServerStopped?.Invoke(this, EventArgs.Empty); } } } } private async Task DataReceiver(ClientMetadata client) { string header = "[WatsonWsServer " + client.Guid.ToString() + "] "; Logger?.Invoke(header + "starting data receiver"); byte[] buffer = new byte[65536]; try { while (true) { MessageReceivedEventArgs msg = await MessageReadAsync(client, buffer).ConfigureAwait(continueOnCapturedContext: false); if (msg == null) { continue; } if (EnableStatistics) { _Stats.IncrementReceivedMessages(); _Stats.AddReceivedBytes(msg.Data.Count); } if (msg.Data != null) { Task.Run(delegate { this.MessageReceived?.Invoke(this, msg); }, client.TokenSource.Token); } else { await Task.Delay(10).ConfigureAwait(continueOnCapturedContext: false); } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (WebSocketException) { } catch (Exception ex4) { Logger?.Invoke(header + "exception: " + Environment.NewLine + ex4.ToString()); } finally { _Clients.TryRemove(client.Guid, out var _); _ = client.IpPort; this.ClientDisconnected?.Invoke(this, new DisconnectionEventArgs(client)); client.Ws.Dispose(); Logger?.Invoke(header + "disconnected"); } } private async Task<MessageReceivedEventArgs> MessageReadAsync(ClientMetadata client, byte[] buffer) { string header = "[WatsonWsServer " + client.Guid.ToString() + "] "; using MemoryStream ms = new MemoryStream(); ArraySegment<byte> seg = new ArraySegment<byte>(buffer); WebSocketReceiveResult webSocketReceiveResult; do { webSocketReceiveResult = await client.Ws.ReceiveAsync(seg, client.TokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); if (webSocketReceiveResult.CloseStatus.HasValue) { Logger?.Invoke(header + "close received"); await client.Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); throw new WebSocketException("Websocket closed."); } if (client.Ws.State != WebSocketState.Open) { Logger?.Invoke(header + "websocket no longer open"); throw new WebSocketException("Websocket closed."); } if (client.TokenSource.Token.IsCancellationRequested) { Logger?.Invoke(header + "cancel requested"); } if (webSocketReceiveResult.Count > 0) { ms.Write(buffer, 0, webSocketReceiveResult.Count); } } while (!webSocketReceiveResult.EndOfMessage); return new MessageReceivedEventArgs(client, new ArraySegment<byte>(ms.GetBuffer(), 0, (int)ms.Length), webSocketReceiveResult.MessageType); } private async Task<bool> MessageWriteAsync(ClientMetadata md, ArraySegment<byte> data, WebSocketMessageType msgType, CancellationToken token) { string header = "[WatsonWsServer " + md.IpPort + "] "; using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_Token, token, md.TokenSource.Token)) { _ = 1; try { await md.SendLock.WaitAsync(md.TokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); try { await md.Ws.SendAsync(data, msgType, endOfMessage: true, linkedCts.Token).ConfigureAwait(continueOnCapturedContext: false); } finally { md.SendLock.Release(); } if (EnableStatistics) { _Stats.IncrementSentMessages(); _Stats.AddSentBytes(data.Count); } return true; } catch (TaskCanceledException) { if (_Token.IsCancellationRequested) { Logger?.Invoke(header + "server canceled"); } else if (token.IsCancellationRequested) { Logger?.Invoke(header + "message send canceled"); } else if (md.TokenSource.Token.IsCancellationRequested) { Logger?.Invoke(header + "client canceled"); } } catch (OperationCanceledException) { if (_Token.IsCancellationRequested) { Logger?.Invoke(header + "canceled"); } else if (token.IsCancellationRequested) { Logger?.Invoke(header + "message send canceled"); } else if (md.TokenSource.Token.IsCancellationRequested) { Logger?.Invoke(header + "client canceled"); } } catch (ObjectDisposedException) { Logger?.Invoke(header + "disposed"); } catch (WebSocketException) { Logger?.Invoke(header + "websocket disconnected"); } catch (SocketException) { Logger?.Invoke(header + "socket disconnected"); } catch (InvalidOperationException) { Logger?.Invoke(header + "disconnected due to invalid operation"); } catch (IOException) { Logger?.Invoke(header + "IO disconnected"); } catch (Exception ex8) { Logger?.Invoke(header + "exception: " + Environment.NewLine + ex8.ToString()); } finally { md = null; } } return false; } } }