Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CrowdControl Valheim v2.0.1
BepInEx/plugins/ConnectorLib.JSON.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("© 2024 Warp World, Inc.")] [assembly: AssemblyFileVersion("5.0.8924.25521")] [assembly: AssemblyInformationalVersion("5.0.8924.25521+1ef6cca7b48ffec6f735086f83465220347f78d1")] [assembly: AssemblyProduct("ConnectorLib.JSON")] [assembly: AssemblyTitle("ConnectorLib.JSON")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.0.8924.25521")] [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] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ConnectorLib.JSON { internal class AnnotatedEnumConverter<T> : JsonConverter<T> where T : struct, Enum { [AttributeUsage(AttributeTargets.Field)] public class JsonValueAttribute : Attribute { public readonly string Value; public JsonValueAttribute(string value) { Value = value; base..ctor(); } } private static readonly Dictionary<T, JsonValueAttribute?> _attributes; static AnnotatedEnumConverter() { T[] source = (T[])Enum.GetValues(typeof(T)); _attributes = source.Select((T m) => new KeyValuePair<T, JsonValueAttribute>(m, GetAttributeOfType<JsonValueAttribute>(m))).ToDictionary(); } private static T? GetAttributeOfType<T>(Enum enumVal) where T : Attribute { Enum enumVal2 = enumVal; Type type = enumVal2.GetType(); MemberInfo memberInfo = type.GetTypeInfo().DeclaredMembers.First((MemberInfo m) => string.Equals(m.Name, enumVal2.ToString(), StringComparison.Ordinal)); object[] array = memberInfo.GetCustomAttributes(typeof(T), inherit: false).ToArray(); return (array.Length != 0) ? ((T)array[0]) : null; } public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) { JsonValueAttribute jsonValueAttribute = _attributes[value]; if (jsonValueAttribute != null) { serializer.Serialize(writer, (object)jsonValueAttribute.Value); } else { serializer.Serialize(writer, (object)Enum.GetName(typeof(T), value)); } } public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer) { string value = serializer.Deserialize<string>(reader); if (value == null) { return default(T); } KeyValuePair<T, JsonValueAttribute>? keyValuePair = _attributes.Cast<KeyValuePair<T, JsonValueAttribute>?>().FirstOrDefault((KeyValuePair<T, JsonValueAttribute>? a) => (a?.Value?.Value?.Equals(value, StringComparison.OrdinalIgnoreCase)).GetValueOrDefault()); if (keyValuePair.HasValue) { return keyValuePair.Value.Key; } if (Enum.TryParse<T>(value, ignoreCase: true, out var result)) { return result; } return default(T); } } public class CamelCaseStringEnumConverter : JsonConverter<Enum> { public override void WriteJson(JsonWriter writer, Enum? value, JsonSerializer serializer) { if (value == null) { serializer.Serialize(writer, (object)null); } else { serializer.Serialize(writer, (object)value.ToCamelCase()); } } public override Enum ReadJson(JsonReader reader, Type objectType, Enum? existingValue, bool hasExistingValue, JsonSerializer serializer) { return ReadJToken(JToken.ReadFrom(reader), objectType); } public static Enum ReadJToken(JToken reader, Type objectType) { //IL_0002: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_000c: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 JTokenType type = reader.Type; JTokenType val = type; if ((int)val != 6) { if ((int)val == 8) { string text = Extensions.Value<string>((IEnumerable<JToken>)reader); if (text == null) { throw new SerializationException("The value was null."); } try { object obj = Enum.Parse(objectType, text, ignoreCase: true); return (Enum)obj; } catch (Exception) { throw new SerializationException("The value was not recognized."); } } throw new SerializationException("The value was not a string or number."); } int? num = Extensions.Value<int>((IEnumerable<JToken>)reader); if (!num.HasValue) { throw new SerializationException("The value was null."); } return (Enum)Enum.ToObject(objectType, num.Value); } } [Serializable] public class EffectRequest : SimpleJSONRequest { [Serializable] public class Target { public string? service; public string? id; public string? name; public string? avatar; } public string? code; public string? message; public JToken? parameters; public uint? quantity; public JArray? targets; public long? duration; public string? viewer; public JArray? viewers; public int? cost; public EffectRequest() { type = RequestType.Start; } } [Serializable] public class EffectResponse : SimpleJSONResponse { private class MetadataConverter : JsonConverter<Dictionary<string, EffectResponseMetadata>?> { public override void WriteJson(JsonWriter writer, Dictionary<string, EffectResponseMetadata>? value, JsonSerializer serializer) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (value == null) { serializer.Serialize(writer, (object)null); return; } JObject val = new JObject(); foreach (KeyValuePair<string, EffectResponseMetadata> item in value) { JObject val2 = JObject.FromObject((object)item.Value); val2.Remove("key"); val[item.Key] = (JToken)(object)val2; } serializer.Serialize(writer, (object)val); } public override Dictionary<string, EffectResponseMetadata>? ReadJson(JsonReader reader, Type objectType, Dictionary<string, EffectResponseMetadata>? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown JObject val = (JObject)serializer.Deserialize(reader); if (val == null) { return null; } Dictionary<string, EffectResponseMetadata> dictionary = new Dictionary<string, EffectResponseMetadata>(); foreach (JProperty item in val.Properties()) { JObject val2 = (JObject)item.Value; val2["key"] = JToken.op_Implicit(item.Name); dictionary.Add(item.Name, ((JToken)val2).ToObject<EffectResponseMetadata>()); } return dictionary; } } public EffectStatus status; public string? message; public long timeRemaining; [JsonConverter(typeof(MetadataConverter))] public Dictionary<string, EffectResponseMetadata>? metadata; public EffectResponse() { } public EffectResponse(uint id, EffectStatus status, string? message = null) : this(id, status, 0L, message) { } [JsonConstructor] public EffectResponse(uint id, EffectStatus status, long timeRemaining, string? message = null) { base.id = id; this.status = status; this.timeRemaining = timeRemaining; this.message = message; type = ResponseType.EffectRequest; } } public class EffectResponseMetadata { public string key; public JToken? value; public EffectStatus status; public long? timeRemaining; public string? message; [JsonConstructor] public EffectResponseMetadata(string key, EffectStatus status, object? value = null, long timeRemaining = 0L, string? message = null) { this.key = key; this.value = value.IfNotNull((Func<object, JToken?>)JToken.FromObject); this.status = status; this.timeRemaining = timeRemaining; this.message = message; base..ctor(); } public static EffectResponseMetadata Success(string key, object? value, string? message = null) { return new EffectResponseMetadata(key, EffectStatus.Success, value, 0L, message); } public static EffectResponseMetadata Failure(string key) { return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L); } public static EffectResponseMetadata Failure(string key, string? message) { return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L, message); } public static EffectResponseMetadata Failure(string key, object? value, string? message = null) { return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L, message); } public static EffectResponseMetadata Retry(string key, long delay = 0L, string? message = null) { return new EffectResponseMetadata(key, EffectStatus.Retry, null, delay, message); } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum EffectStatus { Success = 0, Failure = 1, Unavailable = 2, Retry = 3, Queue = 4, Running = 5, Paused = 6, Resumed = 7, Finished = 8, Visible = 128, NotVisible = 129, Selectable = 130, NotSelectable = 131, NotReady = 255 } [Serializable] public class EffectUpdate : SimpleJSONResponse { [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum IdentifierType { Effect, Group, Category } [Obsolete] [JsonProperty(/*Could not decode attribute arguments.*/)] public string? code; [JsonProperty(/*Could not decode attribute arguments.*/)] public string[]? ids; public IdentifierType idType; public EffectStatus status; public string? message; public EffectUpdate() { } public EffectUpdate(string code, EffectStatus status, string? message = null) { ids = new string[1] { code }; idType = IdentifierType.Effect; this.status = status; this.message = message; type = ResponseType.EffectStatus; } } [Serializable] public class EmptyRequest : SimpleJSONRequest { } [Serializable] public class EmptyResponse : SimpleJSONResponse { } internal static class EnumEx { public static string ToCamelCase(this Enum value) { return value.ToString("G").ToCamelCase(); } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum GameState { Unknown = 0, Ready = 1, Error = -1, Unmodded = -2, NotFocused = -3, Loading = -4, Paused = -5, WrongMode = -6, SafeArea = -7, Cutscene = -8, BadPlayerState = -9, Menu = -10, Map = -11 } [Serializable] public class GameUpdate : SimpleJSONResponse { public GameState state; public string? message; public GameUpdate(GameState state, string? message = null) { this.state = state; this.message = message; type = ResponseType.GameUpdate; } } [Serializable] public class GenericEvent : SimpleJSONResponse { [JsonProperty(PropertyName = "internal")] public bool @internal; public string eventType; public Dictionary<string, string> data; public GenericEvent() { type = ResponseType.GenericEvent; } } internal class HexColorConverter : JsonConverter<ParameterColorValue> { private static readonly Dictionary<char, byte> CHAR_LOOKUP = new Dictionary<char, byte> { { '0', 0 }, { '1', 1 }, { '2', 2 }, { '3', 3 }, { '4', 4 }, { '5', 5 }, { '6', 6 }, { '7', 7 }, { '8', 8 }, { '9', 9 }, { 'A', 10 }, { 'B', 11 }, { 'C', 12 }, { 'D', 13 }, { 'E', 14 }, { 'F', 15 } }; public override void WriteJson(JsonWriter writer, ParameterColorValue value, JsonSerializer serializer) { serializer.Serialize(writer, (object)string.Format("#{0}{1:X2}{2:X2}{3:X2}", (value.A != byte.MaxValue) ? value.A.ToString("X2") : string.Empty, value.R, value.G, value.B)); } public override ParameterColorValue ReadJson(JsonReader reader, Type objectType, ParameterColorValue existingValue, bool hasExistingValue, JsonSerializer serializer) { string value = serializer.Deserialize<string>(reader); if (TryParse(value, out var color)) { return color; } throw new SerializationException("Unrecognized color code."); } public static bool TryParse(string value, out ParameterColorValue color) { if (value == null) { color = default(ParameterColorValue); return false; } value = value.TrimStart(new char[1] { '#' }); switch (value.Length) { case 6: { string[] array2 = Chop(value, 2); byte result2; byte red3 = (byte)(byte.TryParse(array2[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); byte green3 = (byte)(byte.TryParse(array2[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); byte blue3 = (byte)(byte.TryParse(array2[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); color = ParameterColorValue.FromArgb(red3, green3, blue3); return true; } case 8: { string[] array = Chop(value, 2); byte result; byte alpha2 = (byte)(byte.TryParse(array[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte red2 = (byte)(byte.TryParse(array[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte green2 = (byte)(byte.TryParse(array[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte blue2 = (byte)(byte.TryParse(array[3], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); color = ParameterColorValue.FromArgb(alpha2, red2, green2, blue2); return true; } case 3: { byte value3; byte red4 = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value3) ? checked((byte)(value3 * 16)) : 0); byte green4 = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value3) ? checked((byte)(value3 * 16)) : 0); byte blue4 = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value3) ? checked((byte)(value3 * 16)) : 0); color = ParameterColorValue.FromArgb(red4, green4, blue4); return true; } case 4: { byte value2; byte alpha = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value2) ? checked((byte)(value2 * 16)) : 0); byte red = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value2) ? checked((byte)(value2 * 16)) : 0); byte green = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value2) ? checked((byte)(value2 * 16)) : 0); byte blue = (byte)(CHAR_LOOKUP.TryGetValue(value[3], out value2) ? checked((byte)(value2 * 16)) : 0); color = ParameterColorValue.FromArgb(alpha, red, green, blue); return true; } default: color = default(ParameterColorValue); return false; } } private unsafe static string[] Chop(string value, int chopLength) { int length = value.Length; char* ptr = stackalloc char[chopLength]; string[] array = new string[length]; for (int i = 0; i < length; i = checked(i + chopLength)) { int j; for (j = 0; j < chopLength; j = checked(j + 1)) { int num = checked(i + j); if (num >= length) { break; } *(char*)((byte*)ptr + checked(unchecked((nint)j) * (nint)2)) = value[num]; } array[i / chopLength] = new string(ptr, 0, j); } return array; } } internal static class IEnumerableEx { public static Dictionary<K, V> ToDictionary<K, V>(this IEnumerable<KeyValuePair<K, V>> values) where K : notnull { Dictionary<K, V> dictionary = new Dictionary<K, V>(); foreach (KeyValuePair<K, V> value in values) { dictionary.Add(value.Key, value.Value); } return dictionary; } } [Serializable] public class LoginRequest : SimpleJSONRequest { public string? login; public string? password; } [Serializable] public class MessageRequest : SimpleJSONRequest { public string? message; } [Serializable] public class MessageResponse : SimpleJSONResponse { public string? message; } internal static class ObjectEx { public static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : class { return (value != null) ? selector(value) : null; } } public class ParameterColor : ParameterBase, IParameterValue { [JsonProperty(PropertyName = "value")] [JsonConverter(typeof(HexColorConverter))] public ParameterColorValue Value; [JsonIgnore] string IParameterValue.ID => ID; [JsonIgnore] string IParameterValue.Name => Name; [JsonIgnore] ParameterType IParameterValue.Type => Type; [JsonIgnore] object? IParameterValue.Value => Value; [JsonConstructor] public ParameterColor(string name, string id, ParameterColorValue value) : base(name, id, ParameterType.HexColor) { Value = value; } [JsonConstructor] public ParameterColor(string name, string id, string value) : base(name, id, ParameterType.HexColor) { if (!HexColorConverter.TryParse(value, out Value)) { throw new ArgumentException("Unknown color code.", "value"); } } } [Serializable] [DebuggerDisplay("{NameAndARGBValue}")] [TypeForwardedFrom("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public readonly struct ParameterColorValue : IEquatable<ParameterColorValue> { public static readonly ParameterColorValue Empty = default(ParameterColorValue); private const short StateARGBValueValid = 2; private const short StateValueMask = 2; private const short StateNameValid = 8; private const long NotDefinedValue = 0L; internal const int ARGBAlphaShift = 24; internal const int ARGBRedShift = 16; internal const int ARGBGreenShift = 8; internal const int ARGBBlueShift = 0; internal const uint ARGBAlphaMask = 4278190080u; internal const uint ARGBRedMask = 16711680u; internal const uint ARGBGreenMask = 65280u; internal const uint ARGBBlueMask = 255u; private readonly long value; private readonly short state; public byte R => (byte)(Value >> 16); public byte G => (byte)(Value >> 8); public byte B => (byte)Value; public byte A => (byte)(Value >> 24); public bool IsEmpty => state == 0; private long Value { get { if (((uint)state & 2u) != 0) { return value; } return 0L; } } private ParameterColorValue(long value, short state) { this.value = value; this.state = state; } private static ParameterColorValue FromArgb(uint argb) { return new ParameterColorValue(argb, 2); } public static ParameterColorValue FromArgb(int argb) { return FromArgb((uint)argb); } public static ParameterColorValue FromArgb(byte alpha, byte red, byte green, byte blue) { return FromArgb((uint)((alpha << 24) | (red << 16) | (green << 8) | blue)); } public static ParameterColorValue FromArgb(int alpha, ParameterColorValue baseColor) { return FromArgb(checked(((uint)alpha << 24) | ((uint)baseColor.Value & 0xFFFFFFu))); } public static ParameterColorValue FromArgb(byte red, byte green, byte blue) { return FromArgb(byte.MaxValue, red, green, blue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void GetRgbValues(out byte r, out byte g, out byte b) { checked { uint num = (uint)Value; r = (byte)((num & 0xFF0000) >> 16); g = (byte)((num & 0xFF00) >> 8); b = (byte)(num & 0xFFu); } } public float GetBrightness() { GetRgbValues(out var r, out var g, out var b); int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); return (float)checked(num2 + num) / 510f; } public float GetHue() { GetRgbValues(out var r, out var g, out var b); if (r == g && g == b) { return 0f; } int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); checked { float num3 = num2 - num; float num4 = ((r == num2) ? ((float)(g - b) / num3) : ((g != num2) ? ((float)(r - g) / num3 + 4f) : ((float)(b - r) / num3 + 2f))); num4 *= 60f; if (num4 < 0f) { num4 += 360f; } return num4; } } public float GetSaturation() { GetRgbValues(out var r, out var g, out var b); if (r == g && g == b) { return 0f; } int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); checked { int num3 = num2 + num; if (num3 > 255) { num3 = 510 - num2 - num; } return (float)(num2 - num) / (float)num3; } } public int ToArgb() { return (int)Value; } public override string ToString() { if (((uint)state & 2u) != 0) { return "ParameterColorValue [A=" + A + ", R=" + R + ", G=" + G + ", B=" + B + "]"; } return "ParameterColorValue [Empty]"; } public static bool operator ==(ParameterColorValue left, ParameterColorValue right) { return left.value == right.value && left.state == right.state; } public static bool operator !=(ParameterColorValue left, ParameterColorValue right) { return !(left == right); } public override bool Equals(object? obj) { return obj is ParameterColorValue other && Equals(other); } public bool Equals(ParameterColorValue other) { return this == other; } public override int GetHashCode() { long num = value; int num2 = num.GetHashCode() * 397; short num3 = state; return num2 ^ num3.GetHashCode(); } } public class ParameterValue<T> : ParameterBase, IParameterValue { [JsonProperty(PropertyName = "value")] public T? Value; [JsonIgnore] string IParameterValue.ID => ID; [JsonIgnore] string IParameterValue.Name => Name; [JsonIgnore] ParameterType IParameterValue.Type => Type; [JsonIgnore] object? IParameterValue.Value => Value; [JsonConstructor] public ParameterValue(string name, string id, T? value) : base(name, id, ParameterType.Options) { Value = value; } public override string ToString() { return Name; } } [Serializable] public class PlayerInfo : SimpleJSONRequest { public JObject? player; public PlayerInfo() { type = RequestType.Start; } } [Serializable] [JsonConverter(typeof(Converter))] public class RequestParameters : IReadOnlyList<string>, IEnumerable<string>, IEnumerable, IReadOnlyCollection<string>, IReadOnlyDictionary<string, IParameterValue>, IEnumerable<KeyValuePair<string, IParameterValue>>, IReadOnlyCollection<KeyValuePair<string, IParameterValue>> { private class Converter : JsonConverter<RequestParameters> { public override void WriteJson(JsonWriter writer, RequestParameters? value, JsonSerializer serializer) { serializer.Serialize(writer, (object)value?._parameters); } public override RequestParameters? ReadJson(JsonReader reader, Type objectType, RequestParameters? existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); List<IParameterValue> list = new List<IParameterValue>(); foreach (KeyValuePair<string, JToken> item in val) { string key = item.Key; string name = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"name"]); switch (Extensions.Value<ParameterBase.ParameterType>((IEnumerable<JToken>)item.Value[(object)"type"])) { case ParameterBase.ParameterType.Options: { string value2 = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]); list.Add(new ParameterValue<string>(name, key, value2)); break; } case ParameterBase.ParameterType.HexColor: { string value = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]); if (HexColorConverter.TryParse(value, out var color)) { list.Add(new ParameterColor(name, key, color)); } break; } default: throw new SerializationException(); } } return new RequestParameters(list); } } private readonly Dictionary<string, IParameterValue> _parameters; private readonly List<string> _parameter_list; int IReadOnlyCollection<string>.Count => _parameters.Count; int IReadOnlyCollection<KeyValuePair<string, IParameterValue>>.Count => _parameters.Count; public string this[int index] => _parameter_list[index]; public IParameterValue this[string key] => _parameters[key]; public IEnumerable<string> Keys => _parameters.Keys; public IEnumerable<IParameterValue> Values => _parameters.Values; public int Count => _parameters.Count; private RequestParameters() { _parameters = new Dictionary<string, IParameterValue>(); _parameter_list = new List<string>(); } public RequestParameters(IEnumerable<IParameterValue> list) { list = list.ToArray(); _parameters = list.ToDictionary((IParameterValue d) => d.ID); _parameter_list = list.Select((IParameterValue v) => v.Value.ToString()).ToList(); } public RequestParameters(IEnumerable<KeyValuePair<string, IParameterValue>> parameters) { _parameters = parameters.ToDictionary(); _parameter_list = _parameters.Values.Select((IParameterValue p) => p.Value.ToString()).ToList(); } IEnumerator<KeyValuePair<string, IParameterValue>> IEnumerable<KeyValuePair<string, IParameterValue>>.GetEnumerator() { return _parameters.GetEnumerator(); } IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _parameters.Values.Select((IParameterValue v) => v.Value?.ToString()).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } public bool ContainsKey(string key) { return _parameters.ContainsKey(key); } public bool TryGetValue(string key, out IParameterValue value) { return _parameters.TryGetValue(key, out value); } public IEnumerable<string> Where(Func<string, bool> predicate) { return Enumerable.Where(this, predicate); } public IEnumerable<TResult> Select<TResult>(Func<string, TResult> selector) { return Enumerable.Select(this, selector); } public IEnumerable<TResult> SelectMany<TResult>(Func<string, IEnumerable<TResult>> selector) { return Enumerable.SelectMany(this, selector); } public IEnumerable<TResult> SelectMany<TResult>(Func<string, int, IEnumerable<TResult>> selector) { return Enumerable.SelectMany(this, selector); } public string First() { return this.First<string>(); } public string First(Func<string, bool> predicate) { return Enumerable.First(this, predicate); } public string? FirstOrDefault() { return this.FirstOrDefault<string>(); } public string FirstOrDefault(string defaultValue) { return this.FirstOrDefault<string>() ?? defaultValue; } public string? FirstOrDefault(Func<string, bool> predicate) { return Enumerable.FirstOrDefault(this, predicate); } public string FirstOrDefault(Func<string, bool> predicate, string defaultValue) { return Enumerable.FirstOrDefault(this, predicate) ?? defaultValue; } public bool Any() { return this.Any<string>(); } public bool Any(Func<string, bool> predicate) { return Enumerable.Any(this, predicate); } } public interface IParameterValue { string ID { get; } string Name { get; } ParameterBase.ParameterType Type { get; } object? Value { get; } } public abstract class ParameterBase { [JsonConverter(typeof(AnnotatedEnumConverter<ParameterType>))] public enum ParameterType { [AnnotatedEnumConverter<ParameterType>.JsonValue("options")] Options, [AnnotatedEnumConverter<ParameterType>.JsonValue("hex-color")] HexColor } [JsonIgnore] public readonly string ID; [JsonProperty(PropertyName = "title")] public readonly string Name; [JsonProperty(PropertyName = "type")] public readonly ParameterType Type; protected ParameterBase(string name, string id, ParameterType type) { ID = id; Name = name; Type = type; } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum RequestType : byte { Test = 0, Start = 1, Stop = 2, GenericEvent = 16, RpcResponse = 208, PlayerInfo = 224, Login = 240, GameUpdate = 253, KeepAlive = byte.MaxValue } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum ResponseType : byte { EffectRequest = 0, EffectStatus = 1, GenericEvent = 16, LoadEvent = 24, SaveEvent = 25, RpcRequest = 208, Login = 240, LoginSuccess = 241, GameUpdate = 253, Disconnect = 254, KeepAlive = byte.MaxValue } [Serializable] public class RpcRequest : SimpleJSONResponse { public string? method; public object?[]? args; } [Serializable] public class RpcResponse : SimpleJSONRequest { public object? value; public RpcResponse() { type = RequestType.RpcResponse; } } public abstract class SimpleJSONMessage { public static readonly JsonSerializerSettings JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, MissingMemberHandling = (MissingMemberHandling)0, Formatting = (Formatting)0 }; public static readonly JsonSerializer JSON_SERIALIZER = new JsonSerializer { NullValueHandling = JSON_SERIALIZER_SETTINGS.NullValueHandling, MissingMemberHandling = JSON_SERIALIZER_SETTINGS.MissingMemberHandling, Formatting = JSON_SERIALIZER_SETTINGS.Formatting }; private static int _next_id = 0; public static uint NextID { get { uint result; while ((result = (uint)Interlocked.Increment(ref _next_id)) == 0) { } return result; } } public abstract uint ID { get; } public abstract bool IsKeepAlive { get; } } [Serializable] public class SimpleJSONRequest : SimpleJSONMessage { public uint id = SimpleJSONMessage.NextID; public RequestType type; [JsonIgnore] public override uint ID => id; [JsonIgnore] public override bool IsKeepAlive => type == RequestType.KeepAlive; public static SimpleJSONRequest Parse(string json) { return Parse(JObject.Parse(json)); } public static SimpleJSONRequest Parse(JObject j) { switch ((RequestType)(object)CamelCaseStringEnumConverter.ReadJToken(j.GetValue("type"), typeof(RequestType))) { case RequestType.Test: case RequestType.Start: return ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.Stop: return ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.RpcResponse: return ((JToken)j).ToObject<RpcResponse>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.PlayerInfo: return ((JToken)j).ToObject<PlayerInfo>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.Login: return ((JToken)j).ToObject<MessageRequest>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.GameUpdate: return ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER); case RequestType.KeepAlive: return ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER); default: throw new SerializationException("Message type was missing or unknown."); } } } [Serializable] public class SimpleJSONResponse : SimpleJSONMessage { public uint id; public ResponseType type; [JsonIgnore] public override uint ID => id; [JsonIgnore] public override bool IsKeepAlive => type == ResponseType.KeepAlive; [JsonIgnore] public static SimpleJSONResponse KeepAlive { get; } = new EmptyResponse { type = ResponseType.KeepAlive }; public static SimpleJSONResponse Parse(string json) { return Parse(JObject.Parse(json)); } public static SimpleJSONResponse Parse(JObject j) { return (ResponseType)(object)CamelCaseStringEnumConverter.ReadJToken(j.GetValue("type"), typeof(ResponseType)) switch { ResponseType.EffectRequest => ((JToken)j).ToObject<EffectResponse>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.EffectStatus => ((JToken)j).ToObject<EffectUpdate>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.RpcRequest => ((JToken)j).ToObject<RpcRequest>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.GenericEvent => ((JToken)j).ToObject<GenericEvent>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.Login => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.LoginSuccess => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.GameUpdate => ((JToken)j).ToObject<GameUpdate>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.Disconnect => ((JToken)j).ToObject<MessageResponse>(SimpleJSONMessage.JSON_SERIALIZER), ResponseType.KeepAlive => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), _ => throw new SerializationException("Message type was missing or unknown."), }; } } internal static class StringEx { public static string ToCamelCase(this string input) { bool flag = false; string text = ""; checked { for (int i = 0; i < input.Length; i++) { if (char.IsUpper(input[i])) { if (flag) { text += input.Substring(i); break; } text += char.ToLower(input[i]); } else { flag = true; text = ((i <= 1 || !char.IsUpper(input[i - 1]) || !char.IsUpper(input[i - 2])) ? (text + input[i]) : (text.Substring(0, text.Length - 1) + char.ToUpper(input[i - 1]) + input[i])); } } return text; } } } }
BepInEx/plugins/CrowdControl.Client.WebSocket.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using CrowdControl.Client.WebSocket.Actions; using CrowdControl.Client.WebSocket.Data; using CrowdControl.Client.WebSocket.Metadata; using CrowdControl.Common; using CrowdControl.Common.Converters; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using WebSocketSharp.CustomHeaders; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("© 2026 Warp World, Inc.")] [assembly: AssemblyDescription("This package provides integration with the Crowd Control platform, allowing developers to easily add interactive features to their games.")] [assembly: AssemblyFileVersion("5.0.9747.21244")] [assembly: AssemblyInformationalVersion("5.0.9747.21244+81d40af50b7a7b5f88fa786c64a5ebf940b85e5d")] [assembly: AssemblyProduct("CrowdControl.Client.WebSocket")] [assembly: AssemblyTitle("CrowdControl.Client.WebSocket")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.0.9747.21244")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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 CrowdControl.Client.WebSocket { public class ClientSocket : IDisposable { private readonly WebSocket m_ws; private readonly HttpClient m_http = new HttpClient(); private readonly BlockingCollection<ServerMessage> m_inbound = new BlockingCollection<ServerMessage>(new ConcurrentQueue<ServerMessage>()); private readonly BlockingCollection<string> m_outbound = new BlockingCollection<string>(new ConcurrentQueue<string>()); private readonly Thread m_dispatchThread; private readonly Thread m_writerThread; private DateTimeOffset m_lastInboundMessage = DateTimeOffset.UtcNow; private ApplicationAuthCodeRedeemed m_lastApplicationAuthCodeRedeemed; private string? m_jwt; private string? m_authCodeVerifier; private User? m_localUser; private readonly List<string> m_subscribedTopics = new List<string>(); private string m_sessionID; private static readonly SITimeSpan PING_TIMEOUT = SITimeSpan.op_Implicit(10.0); private static readonly TimeSpan PING_INTERVAL = TimeSpan.FromMinutes(5.0); private static readonly TimeSpan TOKEN_REFRESH_TIME = TimeSpan.FromMinutes(30.0); private static readonly TimeSpan TOKEN_REFRESH_MARGIN = TimeSpan.FromHours(2.0); private static readonly TimeSpan RECONNECT_TIME = TimeSpan.FromSeconds(5.0); private static readonly TimeSpan THREAD_SHUTDOWN_TIMEOUT = TimeSpan.FromSeconds(2.0); private static readonly TimeSpan INBOUND_STALL_TIMEOUT = TimeSpan.FromMinutes(11.0); private static readonly ServerMessage EMPTY_PONG = new ServerMessage("direct", "pong", new Pong()); private Timer? m_tokenRefreshTimer; private Timer? m_reconnectTimer; private Timer? m_pingTimer; public const string CUSTOM_EFFECTS_WRITE_SCOPE = "custom-effects:write"; public const string CUSTOM_EFFECTS_READ_SCOPE = "custom-effects:read"; public const int MAX_CUSTOM_EFFECTS = 75; public bool Connected => (int)m_ws.ReadyState == 1; public string GameID { get; } public string ApplicationID { get; } public bool LogSocketTraffic { get; set; } public bool IsDisposed { get; private set; } public bool AutoReconnect { get; set; } public bool IsActiveSession => Connected && !string.IsNullOrEmpty(m_sessionID) && IsTokenValid(); public IReadOnlyList<string> Scopes => m_localUser?.app.scopes ?? Array.Empty<string>(); public bool CanWriteCustomEffects => IsTokenValid() && HasScope("custom-effects:write"); public event Action<ApplicationAuthCode>? ApplicationAuthCodeReceived; public event Action<ApplicationAuthCodeRedeemed>? ApplicationAuthCodeRedeemedReceived; public event Action<ApplicationAuthCodeError>? ApplicationAuthCodeErrorReceived; public event Action<string>? JwtTokenReceived; public event Action? SessionReady; public event Action? SessionEnded; public event Action<Pong>? PongReceived; public event Action<EffectRequest>? EffectRequestReceived; public event Action<EffectRequest, EffectResponse>? EffectResponseSent; public event Action<EffectReport>? EffectReportSent; public Task<bool> CheckConnection() { return Connected ? Ping() : Task.FromResult(result: false); } ~ClientSocket() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing, bool stopSession = true) { if (IsDisposed) { return; } IsDisposed = true; if (!disposing) { return; } if (stopSession) { try { TaskEx.Forget((Task)StopSession()); } catch { } } try { m_ws.OnOpen -= OnOpen; } catch { } try { m_ws.OnClose -= OnClose; } catch { } try { m_ws.OnError -= OnError; } catch { } try { m_ws.OnMessage -= OnMessage; } catch { } try { m_tokenRefreshTimer?.Change(-1, -1); } catch { } try { m_tokenRefreshTimer?.Dispose(); } catch { } try { m_tokenRefreshTimer = null; } catch { } try { m_reconnectTimer?.Change(-1, -1); } catch { } try { m_reconnectTimer?.Dispose(); } catch { } try { m_reconnectTimer = null; } catch { } try { m_pingTimer?.Change(-1, -1); } catch { } try { m_pingTimer?.Dispose(); } catch { } try { m_pingTimer = null; } catch { } try { m_inbound.CompleteAdding(); } catch { } try { m_outbound.CompleteAdding(); } catch { } try { if (Thread.CurrentThread != m_dispatchThread) { m_dispatchThread.Join(THREAD_SHUTDOWN_TIMEOUT); } } catch { } try { if (Thread.CurrentThread != m_writerThread) { m_writerThread.Join(THREAD_SHUTDOWN_TIMEOUT); } } catch { } try { if (Connected) { m_ws.Close((CloseStatusCode)1000); } else { WebSocket ws = m_ws; if (ws != null) { ws.Close(); } } } catch { } GC.SuppressFinalize(this); } public ClientSocket(string gameID, string applicationID, string? userToken = null) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown GameID = gameID; ApplicationID = applicationID; if (!string.IsNullOrWhiteSpace(userToken)) { if (TryGetJwtContents(userToken ?? string.Empty, out User user)) { if (user.exp < DateTimeOffset.UtcNow) { Log.Error((object)"The provided token is expired. Token will be ignored.", false); } else { m_jwt = userToken; m_localUser = user; Log.Debug((object)"User information decoded from the provided token successfully."); } } else { Log.Error((object)"Failed to decode user information from the provided token. Token will be ignored.", false); } } ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; WebSocket val = new WebSocket("wss://pubsub.crowdcontrol.live/", Array.Empty<string>()); val.CustomHeaders = new KeyValuePair<string, string>[2] { new KeyValuePair<string, string>("User-Agent", GameID + "/1.0"), new KeyValuePair<string, string>("X-GameID", GameID) }; m_ws = val; m_ws.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; m_ws.OnOpen += OnOpen; m_ws.OnClose += OnClose; m_ws.OnError += OnError; m_ws.OnMessage += OnMessage; m_http.DefaultRequestHeaders.Accept.ParseAdd("application/json"); m_http.DefaultRequestHeaders.AcceptCharset.ParseAdd("utf-8"); m_http.DefaultRequestHeaders.UserAgent.ParseAdd(GameID + "/1.0"); m_http.DefaultRequestHeaders.Add("X-GameID", GameID); m_dispatchThread = new Thread(DispatchLoop) { IsBackground = true, Name = "CrowdControl Dispatch" }; m_dispatchThread.Start(); m_writerThread = new Thread(WriteLoop) { IsBackground = true, Name = "CrowdControl Writer" }; m_writerThread.Start(); m_tokenRefreshTimer = new Timer(RefreshToken, null, TOKEN_REFRESH_TIME, TOKEN_REFRESH_TIME); m_reconnectTimer = new Timer(RestartSessionIfNeeded, null, RECONNECT_TIME, RECONNECT_TIME); m_pingTimer = new Timer(SendKeepalivePing, null, PING_INTERVAL, PING_INTERVAL); } private void RefreshToken(object? _) { TaskEx.Forget(RefreshToken()); } public async Task RefreshToken() { string jwtString = m_jwt; User jwt; if (string.IsNullOrWhiteSpace(jwtString)) { Log.Debug((object)"Token refresh skipped: no token available."); } else if (!TryGetJwtContents(jwtString, out jwt)) { Log.Debug((object)"Token refresh skipped: failed to decode token contents."); } else if (jwt.exp > DateTimeOffset.UtcNow + TOKEN_REFRESH_MARGIN) { Log.Debug((object)"Token refresh skipped: token not yet near expiry."); } else if (await ExtendToken().ConfigureAwait(continueOnCapturedContext: false)) { Log.Debug((object)"Token refreshed successfully."); } else { Log.Error((object)"Token refresh failed.", false); } } public bool IsTokenValid() { return IsTokenValid(m_jwt); } public static bool IsTokenValid(string? token) { if (string.IsNullOrWhiteSpace(token)) { Log.Debug((object)"Token validity check: no token available."); return false; } if (!TryGetJwtContents(token, out User user)) { Log.Debug((object)"Token validity check: failed to decode token contents."); return false; } if (user.exp < DateTimeOffset.UtcNow) { Log.Debug((object)"Token validity check: token is expired."); return false; } Log.Debug((object)"Token validity check: token is valid."); return true; } private void OnOpen(object? sender, EventArgs e) { Log.Debug((object)("[socket] Connection opened. " + DescribeSocketState())); } private void OnClose(object? sender, CloseEventArgs e) { string text = $"[socket] Connection closed. Code={e.Code} ({DescribeCloseCode(e.Code)}), " + string.Format("WasClean={0}, Reason=\"{1}\", ", e.WasClean, string.IsNullOrEmpty(e.Reason) ? "<none>" : e.Reason) + "LastInbound=" + FormatAge(m_lastInboundMessage) + " ago"; if (e.WasClean) { Log.Debug((object)text); } else { Log.Message((object)text, (LogLevel)1, false); } } private void OnError(object? sender, ErrorEventArgs e) { string text = "[socket] Transport error: " + e.Message + ". " + DescribeSocketState(); if (e.Exception != null) { Log.Error(e.Exception, text, false); } else { Log.Error((object)text, false); } } private string DescribeSocketState() { //IL_001a: 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) string[] array = new string[5]; WebSocket ws = m_ws; array[0] = string.Format("ReadyState={0}, ActiveSession={1}, ", ((ws != null) ? ((object)ws.ReadyState/*cast due to .constrained prefix*/).ToString() : null) ?? "<none>", IsActiveSession); array[1] = $"InboundQueue={m_inbound.Count}, OutboundQueue={m_outbound.Count}, "; array[2] = "LastInbound="; array[3] = FormatAge(m_lastInboundMessage); array[4] = " ago"; return string.Concat(array); } private static string FormatAge(DateTimeOffset since) { TimeSpan timeSpan = DateTimeOffset.UtcNow - since; return (timeSpan.TotalSeconds < 90.0) ? $"{timeSpan.TotalSeconds:F1}s" : $"{timeSpan.TotalMinutes:F1}m"; } private static string DescribeCloseCode(ushort code) { if (1 == 0) { } string result = code switch { 1000 => "Normal", 1001 => "Away", 1002 => "ProtocolError", 1003 => "UnsupportedData", 1005 => "NoStatus", 1006 => "Abnormal - closed without a close frame", 1007 => "InvalidData", 1008 => "PolicyViolation", 1009 => "TooBig", 1010 => "MandatoryExtension", 1011 => "ServerError", 1012 => "ServiceRestart", 1013 => "TryAgainLater", 1015 => "TlsHandshakeFailure", _ => "Unknown", }; if (1 == 0) { } return result; } private void OnMessage(object? sender, MessageEventArgs e) { m_lastInboundMessage = DateTimeOffset.UtcNow; string text = e.Data?.Trim() ?? string.Empty; if (LogSocketTraffic) { Log.Debug((object)("[socket] <<< " + text)); } if (text.Length == 0) { return; } ServerMessage serverMessage2; try { if (1 == 0) { } ServerMessage serverMessage = ((!(text == "pong")) ? JsonConvert.DeserializeObject<ServerMessage>(text) : EMPTY_PONG); if (1 == 0) { } serverMessage2 = serverMessage; } catch (Exception ex) { Log.Error(ex, "Failed to deserialize incoming message.", false); return; } Type type = serverMessage2?.GetType(); string text2 = ((type == null) ? "null" : (type.Name.Split('`')[0] + (type.IsGenericType ? ("<" + string.Join(",", from t in type.GetGenericArguments() select t.Name) + ">") : ""))); Log.Debug((object)("Message deserialized: Type=" + text2)); if (serverMessage2?.Payload == null) { Log.Debug((object)"Message could not be deserialized or had no payload; ignoring."); return; } if (serverMessage2.Payload is Pong pong) { EventHandlerEx.InvokeSafe<Pong>(this.PongReceived, pong); return; } try { m_inbound.Add(serverMessage2); } catch (Exception ex2) { Log.Error(ex2, "Failed to queue incoming message for dispatch.", false); } } private void DispatchLoop() { try { foreach (ServerMessage item in m_inbound.GetConsumingEnumerable()) { try { Dispatch(item); } catch (Exception ex) { Log.Error(ex, "Exception thrown while dispatching an incoming message.", false); } } } catch (ObjectDisposedException) { } catch (InvalidOperationException) { } } private void Dispatch(ServerMessage message) { object payload = message.Payload; object obj = payload; if (!(obj is ApplicationAuthCode applicationAuthCode)) { if (!(obj is ApplicationAuthCodeRedeemed applicationAuthCodeRedeemed)) { if (!(obj is ApplicationAuthCodeError applicationAuthCodeError)) { if (!(obj is GameSessionStop gameSessionStop)) { if (!(obj is SubscriptionResult subscriptionResult)) { if (!(obj is Pong pong)) { EffectRequest val = (EffectRequest)((obj is EffectRequest) ? obj : null); if (val != null) { Log.Debug((object)$"Route: Effect request received: {((CrowdControlBlock)val).ID} (Effect: {val.EffectID})"); EventHandlerEx.InvokeSafe<EffectRequest>(this.EffectRequestReceived, val); } } else { EventHandlerEx.InvokeSafe<Pong>(this.PongReceived, pong); } } else { IListEx.UnionWith<string>((IList<string>)m_subscribedTopics, (IEnumerable<string>)subscriptionResult.Success); } return; } Log.Debug((object)("Route: Session was stopped remotely: " + gameSessionStop.GameSessionID)); TaskEx.Forget(Task.Run(delegate { Action? action = this.SessionEnded; if (action != null) { EventHandlerEx.InvokeSafe(action); } })); Dispose(disposing: true, stopSession: false); } else { Log.Debug((object)("Route: Auth code error received: " + applicationAuthCodeError.Message)); EventHandlerEx.InvokeSafe<ApplicationAuthCodeError>(this.ApplicationAuthCodeErrorReceived, applicationAuthCodeError); } } else { Log.Debug((object)("Route: Auth code redeemed: " + applicationAuthCodeRedeemed.Code)); EventHandlerEx.InvokeSafe<ApplicationAuthCodeRedeemed>(this.ApplicationAuthCodeRedeemedReceived, applicationAuthCodeRedeemed); m_lastApplicationAuthCodeRedeemed = applicationAuthCodeRedeemed; } } else { Log.Debug((object)("Route: Auth code received: " + applicationAuthCode.Code)); EventHandlerEx.InvokeSafe<ApplicationAuthCode>(this.ApplicationAuthCodeReceived, applicationAuthCode); } } private void SendKeepalivePing(object? _) { if (!IsDisposed && Connected) { TaskEx.Forget(SendKeepalivePing()); } } private async Task SendKeepalivePing() { if (!(await Ping().ConfigureAwait(continueOnCapturedContext: false)) && !IsDisposed) { Log.Error((object)$"Keepalive ping was not answered within {((TimeSpan)PING_TIMEOUT).TotalSeconds:F0}s; reconnecting. {DescribeSocketState()}", false); await ForceReconnect().ConfigureAwait(continueOnCapturedContext: false); } } private async Task ForceReconnect() { if (IsDisposed) { return; } try { if (Connected) { m_ws.Close((CloseStatusCode)1000); } else { m_ws.Close(); } } catch (Exception ex) { Log.Error(ex, "Exception thrown while closing a stalled connection.", false); } m_lastInboundMessage = DateTimeOffset.UtcNow; try { Connect(); if (!Connected) { Log.Error((object)"Reconnection attempt failed; the reconnect timer will retry.", false); } else if (await RestartSession().ConfigureAwait(continueOnCapturedContext: false)) { Log.Debug((object)"Session restarted successfully after reconnection."); } else { Log.Error((object)"Session restart failed after reconnection.", false); } } catch (Exception ex2) { Log.Error(ex2, "Exception thrown while reconnecting a stalled connection.", false); } } public void Connect() { Log.Message((object)$"CrowdControl client {typeof(ClientSocket).Assembly.GetName().Version} connecting...", false); m_ws.Connect(); Log.Debug((object)("WebSocket connection " + (Connected ? "established" : "failed") + ".")); } public void Disconnect() { Dispose(); } public static bool TryGetJwtContents(string token, [MaybeNullWhen(false)] out User user) { string[] array = token.Split('.'); if (array.Length != 3) { Log.Error((object)"Invalid token format received.", false); user = null; return false; } try { string text = array[1]; int num = text.Length % 4; if (num > 0) { text += new string('=', checked(4 - num)); } byte[] bytes = Convert.FromBase64String(text); string text2 = Encoding.UTF8.GetString(bytes); user = JsonConvert.DeserializeObject<User>(text2); Log.Debug((object)"User information decoded from token successfully."); return true; } catch (Exception ex) { Log.Error(ex, "Failed to decode user information from token.", false); user = null; return false; } } public Task<ApplicationAuthCode> GetAuthCode() { GenerateAuthCode generateAuthCode = new GenerateAuthCode(ApplicationID, qrCode: true); m_authCodeVerifier = generateAuthCode.CodeVerifier; string json = generateAuthCode.WrapJson(); TaskCompletionSource<ApplicationAuthCode> tcs = new TaskCompletionSource<ApplicationAuthCode>(TaskCreationOptions.RunContinuationsAsynchronously); Action<ApplicationAuthCode> captureCode = null; captureCode = delegate(ApplicationAuthCode c) { Log.Debug((object)"Auth code received."); tcs.TrySetResult(c); try { ApplicationAuthCodeReceived -= captureCode; } catch { } }; ApplicationAuthCodeReceived += captureCode; Log.Debug((object)"Requesting auth code..."); EnqueueSend(json); return tcs.Task; } public async Task<bool> ExtendToken() { Log.Debug((object)"Extending token..."); if (m_localUser == null) { Log.Error((object)"Cannot extend token: no local user information available.", false); return false; } var payload = new { m_localUser.jti }; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://openapi.crowdcontrol.live/auth/token/extend"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(JsonConvert.SerializeObject((object)payload), Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to renew auth code: {0} - {1}", arg0: response.StatusCode), false); return false; } Log.Debug((object)"Token extended successfully."); return ProcessAuthResponse(await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false)); } public async Task<bool> RedeemAuthCode(string code) { Log.Debug((object)"Redeeming auth code..."); string codeVerifier = m_authCodeVerifier; if (string.IsNullOrWhiteSpace(codeVerifier)) { Log.Error((object)"Cannot redeem auth code: no PKCE verifier is available for the current sign-in attempt.", false); return false; } var payload = new { appID = ApplicationID, code = code, codeVerifier = codeVerifier }; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://openapi.crowdcontrol.live/auth/application/token"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(JsonConvert.SerializeObject((object)payload), Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to redeem auth code: {0} - {1}", arg0: response.StatusCode), false); return false; } Log.Debug((object)"Auth code redeemed successfully."); return ProcessAuthResponse(await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false)); } private static bool TryParseJsonResponse(string responseBody, string context, out JObject? result) { //IL_0039: Expected O, but got Unknown result = null; if (string.IsNullOrWhiteSpace(responseBody)) { Log.Error((object)("Empty response body received for " + context + ". Expected a JSON object."), false); return false; } try { result = JObject.Parse(responseBody); return true; } catch (JsonException ex) { JsonException ex2 = ex; Log.Error((Exception)(object)ex2, "Malformed response body received for " + context + ".", false); return false; } } private bool ProcessAuthResponse(string responseBody) { if (!TryParseJsonResponse(responseBody, "auth code", out JObject result)) { return false; } JToken obj = result["token"]; string text = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null); if (string.IsNullOrEmpty(text)) { Log.Error((object)"Auth code response did not contain a token.", false); return false; } m_jwt = text; if (TryGetJwtContents(text, out m_localUser)) { EventHandlerEx.InvokeSafe<string>(this.JwtTokenReceived, text); return true; } return false; } public bool HasScope(string scope) { return HasScope(m_localUser, scope); } public static bool HasScope(string? token, string scope) { User user; return !string.IsNullOrWhiteSpace(token) && TryGetJwtContents(token, out user) && HasScope(user, scope); } private static bool HasScope(User? user, string scope) { string[] array = user?.app.scopes; if (array == null) { return false; } string[] array2 = array; foreach (string a in array2) { if (string.Equals(a, scope, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private bool CheckCustomEffectsWriteAccess(string action) { if (string.IsNullOrWhiteSpace(m_jwt)) { Log.Error((object)("Cannot " + action + " custom effects: no application token available. Please ensure the client socket is initialized and authenticated before modifying custom effects."), false); return false; } if (!HasScope("custom-effects:write")) { Log.Error((object)("Cannot " + action + " custom effects: the current token does not grant the 'custom-effects:write' scope. Uploading custom effects is a development-time tool and requires a developer token issued by Crowd Control. Shipping builds should publish their effects in the game pack menu instead."), false); return false; } return true; } public string? GetInteractLink() { return (m_localUser != null) ? ("https://interact.crowdcontrol.live/#/" + m_localUser.profileType + "/" + m_localUser.originID) : null; } public Task<bool> SubscribeTopic(params string[] topic) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0057: Expected O, but got Unknown //IL_005d: Expected O, but got Unknown JObject val = new JObject { ["action"] = JToken.op_Implicit("subscribe") }; JObject val2 = new JObject { ["token"] = JToken.op_Implicit(m_jwt) }; val2["topics"] = (JToken)new JArray((object[])topic); val["data"] = (JToken)val2; return SendRaw(val); } public Task<bool> SubscribeTopic(IEnumerable<string> topic) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_004f: Expected O, but got Unknown //IL_0055: Expected O, but got Unknown //IL_005b: Expected O, but got Unknown return SendRaw(new JObject { ["action"] = JToken.op_Implicit("subscribe"), ["data"] = (JToken)new JObject { ["token"] = JToken.op_Implicit(m_jwt), ["topics"] = (JToken)new JArray((object)topic) } }); } public void RestartSessionIfNeeded(object _) { TaskEx.Forget(RestartSessionIfNeeded()); } public async Task RestartSessionIfNeeded() { if (!AutoReconnect || IsDisposed) { return; } if (Connected) { if (IsActiveSession && DateTimeOffset.UtcNow - m_lastInboundMessage > INBOUND_STALL_TIMEOUT) { Log.Error((object)$"No traffic received in {INBOUND_STALL_TIMEOUT.TotalMinutes:F0} minutes; reconnecting. {DescribeSocketState()}", false); await ForceReconnect().ConfigureAwait(continueOnCapturedContext: false); } return; } Log.Debug((object)"Attempting to reconnect..."); try { Log.Debug((object)"WebSocket not connected; attempting to restart session..."); Connect(); if (Connected) { Log.Debug((object)"Reconnection successful; resubscribing to session events..."); if (await RestartSession().ConfigureAwait(continueOnCapturedContext: false)) { Log.Debug((object)"Session resubscribed successfully after reconnection."); } else { Log.Error((object)"Session resubscribe failed after reconnection.", false); } } else { Log.Error((object)"Reconnection attempt failed.", false); } } catch (Exception ex) { Log.Error(ex, "Exception occurred during reconnection attempt.", false); } } public async Task<bool> RestartSession() { if (string.IsNullOrEmpty(m_sessionID)) { Log.Error((object)"Cannot restart session: no session ID available.", false); return false; } if (!(await SubscribeTopic("pub/self").ConfigureAwait(continueOnCapturedContext: false))) { Log.Error((object)"Subscribing to effect topic failed.", false); return false; } Log.Debug((object)"Game session restarted successfully."); return true; } public async Task<bool> StartSession(bool forceNew) { Log.Debug((object)"Starting game session..."); if (string.IsNullOrWhiteSpace(GameID)) { Log.Error((object)"Cannot start session: no game ID specified. Please ensure the client socket is initialized with a valid game ID before starting a session.", false); return false; } if (string.IsNullOrWhiteSpace(m_jwt)) { Log.Error((object)"Cannot start session: no application token available. Please ensure the client socket is initialized with a valid game ID before starting a session.", false); return false; } var payload = new { gamePackID = GameID, forceNewSession = forceNew }; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://openapi.crowdcontrol.live/game-session/start"); request.Headers.Authorization = new AuthenticationHeaderValue("cc-auth-token", m_jwt); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(JsonConvert.SerializeObject((object)payload), Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to start session: {0} - {1}", arg0: response.StatusCode), false); return false; } if (!TryParseJsonResponse(await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), $"start session ({response.StatusCode})", out JObject jsonResponse)) { return false; } JToken obj = jsonResponse["gameSessionID"]; string sessionID = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null); if (string.IsNullOrEmpty(sessionID)) { Log.Error((object)"Start session response did not contain a session ID.", false); return false; } m_sessionID = sessionID; if (!(await SubscribeTopic("pub/self").ConfigureAwait(continueOnCapturedContext: false))) { Log.Error((object)"Subscribing to effect topic failed.", false); return false; } Action? action = this.SessionReady; if (action != null) { EventHandlerEx.InvokeSafe(action); } Log.Debug((object)"Game session started successfully."); return true; } public async Task<bool> StopSession() { Log.Debug((object)"Stopping game session..."); if (string.IsNullOrWhiteSpace(m_jwt)) { Log.Error((object)"Cannot stop session: no application token available. Please ensure the client socket is initialized with a valid game ID before stopping a session.", false); return false; } var payload = new { gameSessionID = m_sessionID }; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://openapi.crowdcontrol.live/game-session/stop"); request.Headers.Authorization = new AuthenticationHeaderValue("cc-auth-token", m_jwt); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(JsonConvert.SerializeObject((object)payload), Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to stop session: {0} - {1}", arg0: response.StatusCode), false); return false; } TaskEx.Forget(Task.Run(delegate { Action? action = this.SessionEnded; if (action != null) { EventHandlerEx.InvokeSafe(action); } })); return true; } public async Task<bool> LoadCustomEffects(IEnumerable<IEffect> effects, CustomEffects.OperationMode mode) { Log.Debug((object)"Loading custom effects..."); if (!CheckCustomEffectsWriteAccess("load")) { return false; } Dictionary<string, JObject> effectSet = effects.ToDictionary((IEffect e) => e.EffectID, (IEffect e) => e.ToJObject()); if (effectSet.Count == 0) { Log.Debug((object)"No custom effects to load."); return true; } if (effectSet.Count > 75) { Log.Error((object)$"Cannot load custom effects: {effectSet.Count} effects were supplied but the service accepts at most {75} custom effects per game pack.", false); return false; } CustomEffects payload = new CustomEffects { GamePackID = GameID, Operations = new CustomEffects.Operation[1] { new CustomEffects.Operation { Mode = mode, Effects = effectSet } } }; string json = JsonConvert.SerializeObject((object)payload); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, "https://openapi.crowdcontrol.live/menu/custom-effects"); request.Headers.Authorization = new AuthenticationHeaderValue("cc-auth-token", m_jwt); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to update custom effects: {0} - {1}", arg0: response.StatusCode), false); return false; } Log.Debug((object)"Custom effects updated successfully."); return true; } public Task<bool> DeleteCustomEffects(IEnumerable<IEffect> effects) { return DeleteCustomEffects(effects.SelectMany((IEffect e) => e.IDs)); } public Task<bool> DeleteAllCustomEffects() { return DeleteCustomEffects((IEnumerable<string>?)null); } public async Task<bool> DeleteCustomEffects(IEnumerable<string>? effects) { Log.Debug((object)"Removing custom effects..."); if (!CheckCustomEffectsWriteAccess("remove")) { return false; } List<string> effectIDs = effects?.ToList(); if (effectIDs != null && effectIDs.Count == 0) { Log.Debug((object)"No custom effects to remove."); return true; } JObject payload = new JObject { ["gamePackID"] = JToken.op_Implicit(GameID) }; if (effectIDs != null) { payload["effectIDs"] = (JToken)(object)JArray.FromObject((object)effectIDs); } string json = ((JToken)payload).ToString((Formatting)0); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://openapi.crowdcontrol.live/menu/custom-effects/delete"); request.Headers.Authorization = new AuthenticationHeaderValue("cc-auth-token", m_jwt); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await m_http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { Log.Error((object)string.Format(arg1: await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), format: "Failed to remove custom effects: {0} - {1}", arg0: response.StatusCode), false); return false; } Log.Debug((object)"Custom effects removed successfully."); return true; } public async Task<bool> Ping() { JObject pingMessage = new JObject { ["action"] = JToken.op_Implicit("ping") }; TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously); Action<Pong> receivePong = delegate { tcs.TrySetResult(result: true); }; PongReceived += receivePong; try { if (!(await SendRaw(pingMessage).ConfigureAwait(continueOnCapturedContext: false))) { return false; } return await Task.WhenAny(new Task[2] { tcs.Task, Task.Delay((TimeSpan)PING_TIMEOUT) }).ConfigureAwait(continueOnCapturedContext: false) == tcs.Task && tcs.Task.IsCompletedSuccessfully && tcs.Task.Result; } finally { PongReceived -= receivePong; } } public Task<bool> Send(string method, JObject payload) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00b3: Expected O, but got Unknown //IL_00b9: Expected O, but got Unknown //IL_00bf: Expected O, but got Unknown JObject val = new JObject { ["action"] = JToken.op_Implicit("rpc") }; JObject val2 = new JObject { ["token"] = JToken.op_Implicit(m_jwt) }; JObject val3 = new JObject { ["type"] = JToken.op_Implicit("call"), ["id"] = JToken.op_Implicit(Guid.NewGuid().ToString()), ["method"] = JToken.op_Implicit(method) }; JArray val4 = new JArray(); val4.Add((JToken)(object)payload); val3["args"] = (JToken)val4; val2["call"] = (JToken)val3; val["data"] = (JToken)val2; return SendRaw(val); } public Task<bool> Send(string method, JArray payload) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00a7: Expected O, but got Unknown //IL_00ad: Expected O, but got Unknown //IL_00b3: Expected O, but got Unknown return SendRaw(new JObject { ["action"] = JToken.op_Implicit("rpc"), ["data"] = (JToken)new JObject { ["token"] = JToken.op_Implicit(m_jwt), ["call"] = (JToken)new JObject { ["type"] = JToken.op_Implicit("call"), ["id"] = JToken.op_Implicit(Guid.NewGuid().ToString()), ["method"] = JToken.op_Implicit(method), ["args"] = (JToken)(object)payload } } }); } public Task<bool> SendRaw(MessageData message) { return SendRaw(message.Wrap()); } public Task<bool> SendRaw(LocalMessage message) { return Task.FromResult(EnqueueSend(JsonConvert.SerializeObject((object)message, (Formatting)0))); } public Task<bool> SendRaw(JObject message) { return Task.FromResult(EnqueueSend(JsonConvert.SerializeObject((object)message, (Formatting)0))); } private bool EnqueueSend(string json) { try { m_outbound.Add(json); return true; } catch (Exception ex) { Log.Error(ex, "Failed to queue message for sending over WebSocket.", false); return false; } } private void WriteLoop() { try { foreach (string item in m_outbound.GetConsumingEnumerable()) { if (LogSocketTraffic) { Log.Debug((object)("[socket] >>> " + item)); } try { m_ws.Send(item); } catch (Exception ex) { Log.Error(ex, "Failed to send message over WebSocket. " + DescribeSocketState(), false); } } } catch (ObjectDisposedException) { } catch (InvalidOperationException) { } } public Task<bool> Call(string method, params object[] args) { return SendRaw((MessageData)new RpcMessage(m_jwt, new Call(method, args))); } public Task<bool> Call(string method, IEnumerable<object> args) { return SendRaw((MessageData)new RpcMessage(m_jwt, new Call(method, args))); } public void Respond(EffectRequest request, EffectStatus status, string? message = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Respond(request, status, null, null, message); } public void Respond(EffectRequest request, EffectResponse response) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) Respond(request, response.Status, response.StandardError, response.Message); } public void Respond(EffectRequest request, EffectStatus status, StandardErrors? messageID, string? message = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Respond(request, status, null, messageID, message); } public void Respond(EffectRequest request, EffectStatus status, SITimeSpan? timeRemaining, string? message = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Respond(request, status, timeRemaining, null, message); } public void Respond(EffectRequest request, EffectStatus status, SITimeSpan? timeRemaining, StandardErrors? messageID, string? message = null) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(message) && messageID.HasValue) { message = StandardErrorsEx.GetFriendlyMessage(messageID.Value, Array.Empty<object>()); } EffectResponse val = new EffectResponse(((CrowdControlBlock)request).ID, status, timeRemaining, message, (Enum)(object)messageID, (ErrorSource?)null, (bool?)null); EventHandlerEx.InvokeSafe<EffectRequest, EffectResponse>(this.EffectResponseSent, request, val); Send("effectResponse", JObjectEx.RemovePropertiesExcept(JObject.FromObject((object)val), new string[6] { "id", "request", "status", "message", "stamp", "timeRemaining" })); } public void MetadataChanged(IDictionary<string, object?> metadata) { object[] array = new object[2] { GameID, metadata }; Send("packMetadataChanged", JArray.FromObject((object)array)); } public void MetadataChanged(string key, object? value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown JObject val = new JObject(); val[key] = (JToken)((value != null) ? ((object)JToken.FromObject(value)) : ((object)JValue.CreateNull())); object[] array = new object[2] { GameID, val }; Send("packMetadataChanged", JArray.FromObject((object)array)); } private void Report(string effectID, EffectStatus status) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Report(new string[1] { effectID }, status); } private void Report(string[] effectIDs, EffectStatus status) { //IL_0003: 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_000b: Expected O, but got Unknown EffectReport val = new EffectReport((IEnumerable<string>)effectIDs, (IdentifierType)0, status, (string)null); EventHandlerEx.InvokeSafe<EffectReport>(this.EffectReportSent, val); Send("effectReport", JObject.FromObject((object)val)); } private void SubscribeToTopics(params string[] topics) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0040: Expected O, but got Unknown JObject val = new JObject { ["action"] = JToken.op_Implicit("subscribe"), ["data"] = (JToken)new JObject { ["topics"] = (JToken)(object)JArray.FromObject((object)topics) } }; EnqueueSend(((JToken)val).ToString((Formatting)0)); } private void SubscribeToTopics(IEnumerable<string> topics) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0040: Expected O, but got Unknown JObject val = new JObject { ["action"] = JToken.op_Implicit("subscribe"), ["data"] = (JToken)new JObject { ["topics"] = (JToken)(object)JArray.FromObject((object)topics) } }; EnqueueSend(((JToken)val).ToString((Formatting)0)); } } public class CrowdControl : IBehavior, IDisposable { internal readonly ClientSocket ClientSocket; public bool ContentLoaded { get; private set; } public string GameID { get; } public string ApplicationID { get; } public bool Connected => ClientSocket.Connected; public IEffectLoader EffectLoader { get; } public IMetadataLoader MetadataLoader { get; } public Scheduler Scheduler { get; } public EffectType AllowedTypes { get; set; } = (EffectType)0; public IGameStateManager GameStateManager { get; } public bool IsActiveSession => ClientSocket?.IsActiveSession ?? false; public bool IsDisposed { get; private set; } private TaskScheduler m_taskScheduler { get; set; } public TaskFactory TaskFactory { get; } public bool AutoReconnect { get { return ClientSocket?.AutoReconnect ?? false; } set { if (ClientSocket != null) { ClientSocket.AutoReconnect = value; } } } public bool LogSocketTraffic { get { return ClientSocket?.LogSocketTraffic ?? false; } set { if (ClientSocket != null) { ClientSocket.LogSocketTraffic = value; } } } public IReadOnlyList<string> Scopes => ClientSocket.Scopes; public bool CanWriteCustomEffects => ClientSocket.CanWriteCustomEffects; public event Action<EffectRequest>? EffectRequestReceived; public event Action<EffectRequest, EffectResponse>? EffectResponseSent; public event Action<EffectReport>? EffectReportSent; public event Action? SessionReady; public event Action? SessionEnded; public event Action<string>? JwtTokenReceived; public event Action? Disposed; public event Action<ApplicationAuthCode> AuthCodeReceived { add { ClientSocket.ApplicationAuthCodeReceived += value; } remove { try { ClientSocket.ApplicationAuthCodeReceived -= value; } catch { } } } public event Action<ApplicationAuthCodeRedeemed> AuthCodeRedeemedReceived { add { ClientSocket.ApplicationAuthCodeRedeemedReceived += value; } remove { try { ClientSocket.ApplicationAuthCodeRedeemedReceived -= value; } catch { } } } public event Action<ApplicationAuthCodeError> AuthCodeErrorReceived { add { ClientSocket.ApplicationAuthCodeErrorReceived += value; } remove { try { ClientSocket.ApplicationAuthCodeErrorReceived -= value; } catch { } } } ~CrowdControl() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (!IsDisposed) { IsDisposed = true; if (disposing) { Disconnect(); ((IBehavior)this).UnloadContentIfNeeded(); } GC.SuppressFinalize(this); Action? action = this.Disposed; if (action != null) { EventHandlerEx.InvokeSafe(action); } } } public CrowdControl(IGameStateManager gameStateManager, IEffectLoader effectLoader, IMetadataLoader metadataLoader, TaskScheduler? taskScheduler, string gameID, string applicationID, string? jwt = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameID = gameID; ApplicationID = applicationID; ClientSocket = new ClientSocket(gameID, applicationID, jwt); ClientSocket.EffectRequestReceived += OnEffectRequestReceived; ClientSocket.EffectResponseSent += delegate(EffectRequest request, EffectResponse response) { EventHandlerEx.InvokeSafe<EffectRequest, EffectResponse>(this.EffectResponseSent, request, response); }; ClientSocket.EffectReportSent += delegate(EffectReport r) { EventHandlerEx.InvokeSafe<EffectReport>(this.EffectReportSent, r); }; ClientSocket.ApplicationAuthCodeRedeemedReceived += OnApplicationAuthCodeRedeemedReceived; ClientSocket.SessionReady += delegate { EventHandlerEx.InvokeSafe(this.SessionReady); }; ClientSocket.SessionEnded += delegate { EventHandlerEx.InvokeSafe(this.SessionEnded); }; ClientSocket.JwtTokenReceived += delegate(string t) { EventHandlerEx.InvokeSafe<string>(this.JwtTokenReceived, t); }; EffectLoader = effectLoader ?? throw new ArgumentNullException("effectLoader"); MetadataLoader = metadataLoader ?? throw new ArgumentNullException("metadataLoader"); m_taskScheduler = taskScheduler ?? TaskScheduler.Default; TaskFactory = new TaskFactory(m_taskScheduler); Scheduler = new Scheduler(this, ClientSocket); GameStateManager = gameStateManager ?? throw new ArgumentNullException("gameStateManager"); } public bool IsTokenValid() { return ClientSocket.IsTokenValid(); } public static bool IsTokenValid(string? token) { return global::CrowdControl.Client.WebSocket.ClientSocket.IsTokenValid(token); } public Task<bool> StartSession(bool startNew) { return ClientSocket.StartSession(startNew); } public Task<bool> StopSession() { return ClientSocket.StopSession(); } public Task RefreshToken() { return ClientSocket?.RefreshToken() ?? Task.CompletedTask; } private async void OnApplicationAuthCodeRedeemedReceived(ApplicationAuthCodeRedeemed authCode) { try { bool flag = await ClientSocket.RedeemAuthCode(authCode.Code).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await ClientSocket.StartSession(forceNew: true).ConfigureAwait(continueOnCapturedContext: false); } if (flag) { Action? action = this.SessionReady; if (action != null) { EventHandlerEx.InvokeSafe(action); } } } catch (Exception ex) { Exception ex2 = ex; Log.Error(ex2, false); } } public void Connect() { ClientSocket.Connect(); } public void Disconnect() { ClientSocket.Disconnect(); } public Task<bool> Ping() { return ClientSocket.Ping(); } private void OnEffectRequestReceived(EffectRequest request) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (!ContentLoaded) { Log.Debug((object)"Received effect request but content is not loaded."); ClientSocket.Respond(request, (EffectStatus)32, (StandardErrors)20480); return; } if (request.Effect == null) { Log.Debug((object)"Received effect request with null effect."); ClientSocket.Respond(request, (EffectStatus)32, (StandardErrors)4096, "Effect is null."); return; } if (!((Enum)AllowedTypes).HasFlag((Enum)(object)request.Effect.EffectType)) { Log.Debug((object)$"The effect request type \"{request.Effect.EffectType}\" is not handled by this client. Ignoring..."); return; } if (request.Effect?.ID == null) { Log.Debug((object)"Received effect request with null or missing effect ID."); ClientSocket.Respond(request, (EffectStatus)32, (StandardErrors)4096, "Effect ID is null or missing."); return; } if (!EffectLoader.Effects.TryGetValue(request.Effect.ID, out IEffect _)) { Log.Debug((object)("Received request for unknown effect ID: " + request.Effect.ID)); ClientSocket.Respond(request, (EffectStatus)33, (StandardErrors)4097); return; } EventHandlerEx.InvokeSafe<EffectRequest>(this.EffectRequestReceived, request); Log.Debug((object)("Starting effect: " + request.Effect.ID)); try { Scheduler.ProcessRequest(request); } catch (Exception arg) { Log.Error((object)$"Exception thrown while queueing effect '{request.Effect.ID}': {arg}", false); ClientSocket.Respond(request, (EffectStatus)32, (StandardErrors)1); } } public void LoadContent() { ContentLoaded = true; } public void UnloadContent() { ContentLoaded = false; EffectLoader.Unload(); } public virtual void Draw(SITimeSpan gameTime, SITimeSpan deltaTime) { } public virtual void Update(SITimeSpan gameTime, SITimeSpan deltaTime) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Scheduler.Tick(deltaTime); } public Task<ApplicationAuthCode> GetAuthCode() { return ClientSocket.GetAuthCode(); } public string? GetInteractLink() { if (ClientSocket == null) { Log.Error((object)"Cannot get interact link when client socket is not initialized.", false); return null; } if (!IsActiveSession) { Log.Error((object)"Cannot get interact link when there is no active session.", false); return null; } return ClientSocket.GetInteractLink(); } public bool HasScope(string scope) { return ClientSocket.HasScope(scope); } public static bool HasScope(string? token, string scope) { return global::CrowdControl.Client.WebSocket.ClientSocket.HasScope(token, scope); } public Task<bool> LoadCustomEffects(IEnumerable<IEffect> effects, CustomEffects.OperationMode mode) { return ClientSocket.LoadCustomEffects(effects, mode); } public Task<bool> DeleteCustomEffects(IEnumerable<IEffect> effects) { return ClientSocket.DeleteCustomEffects(effects); } public Task<bool> DeleteCustomEffects(IEnumerable<string>? effects) { return ClientSocket.DeleteCustomEffects(effects); } public Task<bool> DeleteAllCustomEffects() { return ClientSocket.DeleteAllCustomEffects(); } public bool CloneEffect(string sourceEffectID, params string[] destEffectIDs) { return EffectLoader.CloneEffect(sourceEffectID, destEffectIDs); } public void Respond(EffectRequest request, EffectStatus status, string? message = null) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ClientSocket.Respond(request, status, message); } public void Respond(EffectRequest request, EffectStatus status, StandardErrors? messageID, string? message = null) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ClientSocket.Respond(request, status, messageID, message); } public void Respond(EffectRequest request, EffectStatus status, SITimeSpan? timeRemaining, string? message = null) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ClientSocket.Respond(request, status, timeRemaining, message); } public void Respond(EffectRequest request, EffectStatus status, SITimeSpan? timeRemaining, StandardErrors? messageID, string? message = null) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ClientSocket.Respond(request, status, timeRemaining, messageID, message); } public void UpdateMetadata(IDictionary<string, object?> metadata) { ClientSocket.MetadataChanged(metadata); } public void UpdateMetadata(string key, object? value) { ClientSocket.MetadataChanged(key, value); } public Task<bool> ShowEffects(params string[] codes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport((IEnumerable<string>)codes, (IdentifierType)0, (EffectStatus)98, (string)null)); } public Task<bool> ShowEffects(IEnumerable<string> codes, string? message = null) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport(codes, (IdentifierType)0, (EffectStatus)98, message)); } public Task<bool> ShowAllEffects(string? message = null) { return ShowEffects(EffectLoader.Effects.Keys, message); } public Task<bool> HideEffects(params string[] codes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport((IEnumerable<string>)codes, (IdentifierType)0, (EffectStatus)99, (string)null)); } public Task<bool> HideEffects(IEnumerable<string> codes, string? message = null) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport(codes, (IdentifierType)0, (EffectStatus)99, message)); } public Task<bool> HideAllEffects(string? message = null) { return HideEffects(EffectLoader.Effects.Keys, message); } public Task<bool> EnableEffects(params string[] codes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport((IEnumerable<string>)codes, (IdentifierType)0, (EffectStatus)96, (string)null)); } public Task<bool> EnableEffects(IEnumerable<string> codes, string? message = null) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport(codes, (IdentifierType)0, (EffectStatus)96, message)); } public Task<bool> EnableAllEffects(string? message = null) { return EnableEffects(EffectLoader.Effects.Keys, message); } public Task<bool> DisableEffects(params string[] codes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport((IEnumerable<string>)codes, (IdentifierType)0, (EffectStatus)97, (string)null)); } public Task<bool> DisableEffects(IEnumerable<string> codes, string? message = null) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return ClientSocket.Call("effectReport", (object)new EffectReport(codes, (IdentifierType)0, (EffectStatus)97, message)); } public Task<bool> DisableAllEffects(string? message = null) { return DisableEffects(EffectLoader.Effects.Keys, message); } } [Serializable] public class EffectResponse { [JsonProperty(PropertyName = "message")] public string? Message; [JsonProperty(PropertyName = "standardError")] public StandardErrors? StandardError; [JsonProperty(PropertyName = "status")] public EffectStatus Status { get; } public EffectResponse(EffectStatus status, string? message = null) { //IL_0009: 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) Status = status; Message = message; } public EffectResponse(EffectStatus status, StandardErrors error) { //IL_0009: 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_0010: Unknown result type (might be due to invalid IL or missing references) Status = status; StandardError = error; } public static implicit operator EffectResponse(EffectStatus status) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return new EffectResponse(status); } public static implicit operator EffectResponse(StandardErrors error) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return new EffectResponse((EffectStatus)32, error); } public static implicit operator EffectResponse((EffectStatus status, string message) tuple) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new EffectResponse(tuple.status, tuple.message); } public static implicit operator EffectResponse((EffectStatus status, StandardErrors error) tuple) { //IL_0001: 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) return new EffectResponse(tuple.status, tuple.error); } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum GameState { Unknown = 0, Error = -1, Unmodded = -2, BadGameSettings = -3, WrongVersion = -4, NotFocused = -5, Loading = -6, InLevel = 1, [Obsolete("Use InLevel instead. This state is redundant and does not provide any additional information about the game state.")] Ready = 1, TitleScreen = -17, Credits = -18, Menu = -13, Paused = -7, WrongMode = -8, SafeArea = -9, StartingArea = -19, Dialogue = -20, Cutscene = -11, BadPlayerState = -12, InputLocked = -21, Map = -14, UntimedArea = -10, InCombat = -15, NotInCombat = -16, PipelineBusy = -128, NotReady = int.MinValue } internal interface IBehavior { bool ContentLoaded { get; } void LoadContent(); void UnloadContent(); void LoadContentIfNeeded() { if (!ContentLoaded) { LoadContent(); } } void UnloadContentIfNeeded() { if (ContentLoaded) { UnloadContent(); } } void Update(SITimeSpan gameTime, SITimeSpan deltaTime); void Draw(SITimeSpan gameTime, SITimeSpan deltaTime); } public interface IGameStateManager { bool IsReady(EffectRequest? request = null) { return GetGameState() == GameState.InLevel; } GameState GetGameState(); } public sealed class TestGameStateManager : IGameStateManager { public GameState GameState { get; set; } public TestGameStateManager(GameState gameState = GameState.InLevel) { GameState = gameState; } public GameState GetGameState() { return GameState; } } public class Scheduler { private class RequestState { private IEnumerator? m_enumerator; public EffectRequest Request { get; } public IEffect Effect { get; } public TimedEffectState? TimedEffectState { get; } public DateTimeOffset DueTime { get; } public bool MoveNext(SITimeSpan deltaTime) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (m_enumerator != null) { if (m_enumerator.MoveNext()) { return true; } (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; } switch (TimedEffectState?.State) { case global::CrowdControl.Client.WebSocket.Actions.TimedEffectState.EffectState.NotStarted: if (m_enumerator == null) { m_enumerator = TimedEffectState.Start(); } m_enumerator.MoveNext(); return true; case global::CrowdControl.Client.WebSocket.Actions.TimedEffectState.EffectState.Running: case global::CrowdControl.Client.WebSocket.Actions.TimedEffectState.EffectState.Paused: if (m_enumerator == null) { m_enumerator = TimedEffectState.Tick(deltaTime); } m_enumerator.MoveNext(); return true; default: return false; } } public void Pause() { Log.Debug((object)$"Attempting to pause effect {Effect.EffectID} with state {TimedEffectState?.State}"); (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if (valueOrDefault == global::CrowdControl.Client.WebSocket.Actions.TimedEffectState.EffectState.Running) { m_enumerator = TimedEffectState.Pause(); } } } public void Resume() { Log.Debug((object)$"Attempting to resume effect {Effect.EffectID} with state {TimedEffectState?.State}"); (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if (valueOrDefault == global::CrowdControl.Client.WebSocket.Actions.TimedEffectState.EffectState.Paused) { m_enumerator = TimedEffectState.Resume(); } } } public void Stop() { Log.Debug((object)$"Attempting to stop effect {Effect.EffectID} with state {TimedEffectState?.State}"); (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 1u) { m_enumerator = TimedEffectState.Stop(); } } } public RequestState(Scheduler scheduler, EffectRequest request, IEffect effect, DateTimeOffset? dueTime = null) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) RequestState requestState = this; Request = request; Effect = effect; DueTime = dueTime ?? DateTimeOffset.MinValue; if (Effect.IsTimed) { TimedEffectState = new TimedEffectState(effect, request, request.Duration, (EffectResponse response) => scheduler.TryHandleTemporaryFailure(requestState, response)); } } } private const int MAX_REQUESTS_PER_TICK = 64; private readonly CrowdControl m_crowdControl; private readonly ClientSocket m_clientSocket; private readonly ConcurrentQueue<RequestState> m_requestQueue = new ConcurrentQueue<RequestState>(); private readonly ConcurrentQueue<RequestState> m_retryQueue = new ConcurrentQueue<RequestState>(); private readonly ConcurrentDictionary<Guid, RequestState> m_runningEffects = new ConcurrentDictionary<Guid, RequestState>(); private readonly object m_admissionLock = new object(); private readonly Dictionary<string, uint> m_pendingRequestsByEffect = new Dictionary<string, uint>(); public Scheduler(CrowdControl crowdControl, ClientSocket clientSocket) { m_crowdControl = crowdControl; m_clientSocket = clientSocket; } public bool IsRunning(string id) { foreach (TimedEffectState item in m_runningEffects.Values.Select((RequestState p) => p.TimedEffectState).OfType<TimedEffectState>()) { if (item.Effect.IDs.Contains(id)) { return true; } } return false; } public void ProcessRequest(EffectRequest? request) { if (request == null) { Log.Error((object)"Cannot process a null effect request.", false); return; } string effectID = request.EffectID; if (!m_crowdControl.EffectLoader.Effects.TryGetValue(effectID, out IEffect value)) { Log.Error((object)$"Effect not found for request {((CrowdControlBlock)request).ID}: {effectID}", false); m_clientSocket.Respond(request, (EffectStatus)33, (StandardErrors)4097); } else { TryEnqueue(new RequestState(this, request, value)); } } public void Enqueue(EffectRequest request, IEffect effect) { if (request == null) { throw new ArgumentNullException("request"); } if (effect == null) { throw new ArgumentNullException("effect"); } TryEnqueue(new RequestState(this, request, effect)); } private bool TryEnqueue(RequestState requestState, bool retry = false) { bool flag; lock (m_admissionLock) { EffectRequest request = requestState.Request; m_pendingRequestsByEffect.TryGetValue(request.EffectID, out var value); uint? num = request.Effect?.QueueMax; if (!request.IgnoreMaxQueueLength && num.HasValue && value >= num.Value) { flag = false; } else { if (retry) { m_retryQueue.Enqueue(requestState); } else { m_requestQueue.Enqueue(requestState); } m_pendingRequestsByEffect[request.EffectID] = checked(value + 1); flag = true; } } if (flag) { return true; } Log.Debug((object)("Queue limit reached for effect " + requestState.Request.EffectID + ".")); m_clientSocket.Respond(requestState.Request, (EffectStatus)32, (StandardErrors)12545); return false; } private void ReleaseAdmission(RequestState requestState) { lock (m_admissionLock) { if (m_pendingRequestsByEffect.TryGetValue(requestState.Request.EffectID, out var value)) { if (value <= 1) { m_pendingRequestsByEffect.Remove(requestState.Request.EffectID); } else { m_pendingRequestsByEffect[requestState.Request.EffectID] = checked(value - 1); } } } } private bool TryHandleTemporaryFailure(RequestState requestState, EffectResponse response) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if ((int)response.Status != 32) { return false; } EffectRequest request = requestState.Request; uint? num = request.RetryMaxAttempts ?? request.Effect?.RetryMaxAttempts; SITimeSpan? val = request.RetryMaxTime ?? request.Effect?.RetryMaxTime; SITimeSpanRange val2 = request.RetryInterval ?? request.Effect?.RetryInterval; if (!num.HasValue && !val.HasValue && val2 == null) { return false; } if (val.HasValue && request.AttemptDuration > val.Value) { m_clientSocket.Respond(request, (EffectStatus)32, (StandardErrors)12291); return true; } if (num.HasValue && request.AttemptCount > num.Value) { m_clientSocket.Respond(request, (EffectStatus)32, (StandardErrors)12292); return true; } SITimeSpan val3 = val2?.Minimum ?? SITimeSpan.Zero; RequestState requestState2 = new RequestState(this, request, requestState.Effect, DateTimeOffset.UtcNow + val3); if (!TryEnqueue(requestState2, retry: true)) { return true; } m_clientSocket.Respond(request, (EffectStatus)50, val3, response.StandardError, response.Message); return true; } private static void BeginAttempt(EffectRequest request) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) DateTimeOffset utcNow = DateTimeOffset.UtcNow; if (request.AttemptCount == 0 || request.AttemptInitialTime == default(DateTimeOffset)) { request.AttemptInitialTime = utcNow; } request.AttemptCount = checked(request.AttemptCount + 1); request.AttemptDuration = SITimeSpan.op_Implicit(utcNow - request.AttemptInitialTime); } private void PromoteDueRetries() { int count = m_retryQueue.Count; DateTimeOffset utcNow = DateTimeOffset.UtcNow; RequestState result; while (checked(count--) > 0 && m_retryQueue.TryDequeue(out result)) { if (result.DueTime <= utcNow) { m_requestQueue.Enqueue(result); } else { m_retryQueue.Enqueue(result); } } } public bool PauseAll() { bool result = true; foreach (KeyValuePair<Guid, RequestState> runningEffect in m_runningEffects) { try { runningEffect.Value.Pause(); } catch (Exception ex) { Log.Error(ex, false); result = false; } } return result; } public bool ResumeAll() { bool result = true; foreach (KeyValuePair<Guid, RequestState> runningEffect in m_runningEffects) { try { runningEffect.Value.Resume(); } catch (Exception ex) { Log.Error(ex, false); result = false; } } return result; } public bool StopAll() { bool result = true; foreach (KeyValuePair<Guid, RequestState> runningEffect in m_runningEffects) { try { runningEffect.Value.Stop(); } catch (Exception ex) { Log.Error(ex, false); result = false; } } return result; } public void Tick(SITimeSpan deltaTime) { //IL_0160: Unknown result type (might be due to invalid IL or missing references) PromoteDueRetries(); int num = Math.Min(m_requestQueue.Count, 64); RequestState result; while (checked(num--) > 0 && m_requestQueue.TryDequeue(out result)) { ReleaseAdmission(result); if (!m_crowdControl.GameStateManager.IsReady(result.Request)) { Log.Error((object)("Game state not ready for effect " + result.Effect.EffectID + "."), false); m_clientSocket.Respond(result.Request, (EffectStatus)32, (StandardErrors)16384); continue; } BeginAttempt(result.Request); if (result.TimedEffectState != null) { m_runningEffects.TryAdd(((CrowdControlBlock)result.Request).ID, result); continue; } try { EffectResponse response = result.Effect.Start(result.Request); if (!TryHandleTemporaryFailure(result, response)) { m_clientSocket.Respond(result.Request, response); } } catch (Exception ex) { Log.Error(ex, false); EffectResponse response2 = new EffectResponse((EffectStatus)32, (StandardErrors)1); if (!TryHandleTemporaryFailure(result, response2)) { m_clientSocket.Respond(result.Request, response2); } } } ConsumeEnumerators(deltaTime); } private void ConsumeEnumerators(SITimeSpan deltaTime) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<Guid, RequestState> runningEffect in m_runningEffects) { if (!runningEffect.Value.MoveNext(deltaTime)) { m_runningEffects.TryRemove(runningEffect.Key, out RequestState _); } } } } } namespace CrowdControl.Client.WebSocket.Metadata { public interface IMetadata { string Key { get; } object? Value { get; } event Action? Updated; bool TryGetSerialized(out JToken? value); } public interface IMetadata<TValue> : IMetadata { new TValue Value { get; } } public interface IMetadataLoader { IDictionary<string, IMetadata> Metadata { get; } void Load(); void Unload(); } public abstract class MetadataBase<TValue> : IMetadata<TValue>, IMetadata { public abstract string Key { get; } public abstract TValue Value { get; } object IMetadata.Value => Value; public abstract event Action? Updated; public abstract bool TryGetSerialized(out JToken? value); } } namespace CrowdControl.Client.WebSocket.Data { public class ApplicationAuthCode { [JsonProperty("code")] public string Code { get; } [JsonProperty("url")] public string Url { get; } [JsonProperty("qrCode")] public string? QRCode { get; } [JsonConstructor] public ApplicationAuthCode(string code, string url, string? qrCode = null) { Code = code; Url = url; QRCode = qrCode; } } public class ApplicationAuthCodeError { [JsonProperty("message")] public string Message { get; } [JsonProperty("timestamp")] [JsonConverter(typeof(UnixTimestampConverter))] public DateTimeOffset? Timestamp { get; } [JsonConstructor] public ApplicationAuthCodeError(string message, [JsonConverter(typeof(UnixTimestampConverter))] DateTimeOffset? timestamp = null) { Message = message; Timestamp = timestamp; } } public class ApplicationAuthCodeRedeemed { [JsonProperty("code")] public string Code { get; } [JsonConstructor] public ApplicationAuthCodeRedeemed(string code) { Code = code; } } public class Call { [JsonProperty("type")] public string Type { get; } = "call"; [JsonProperty("id")] public string Id { get; } = Guid.NewGuid().ToString(); [JsonProperty("method")] public string Method { get; } [JsonProperty("args")] public IEnumerable<object?> Args { get; } public Call(string method, object?[]? args) { Method = method; Args = args ?? Array.Empty<string>(); } public Call(string method, IEnumerable<object?>? args) { Method = method; Args = args ?? Array.Empty<string>(); } } public class CustomEffects { [JsonConverter(typeof(OperationModeConverter))] public enum OperationMode { Merge, ReplaceAll, ReplacePartial } private class OperationModeConverter : JsonConverter<OperationMode> { public override OperationMode ReadJson(JsonReader reader, Type objectType, OperationMode existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) string text = reader.Value as string; if (1 == 0) { } OperationMode result = text switch { "merge" => OperationMode.Merge, "replace-all" => OperationMode.ReplaceAll, "replace-partial" => OperationMode.ReplacePartial, _ => throw new JsonSerializationException("Invalid operation mode: " + text), }; if (1 == 0) { } return result; } public override void WriteJson(JsonWriter writer, OperationMode value, JsonSerializer serializer) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } string text = value switch { OperationMode.Merge => "merge", OperationMode.ReplaceAll => "replace-all", OperationMode.ReplacePartial => "replace-partial", _ => throw new JsonSerializationException($"Invalid operation mode: {value}"), }; if (1 == 0) { } string text2 = text; writer.WriteValue(text2); } } public class Operation { [JsonProperty("mode")] public OperationMode Mode { get; set; } [JsonProperty("effects")] public Dictionary<string, JObject> Effects { get; set; } } [JsonProperty("gamePackID")] public string GamePackID { get; set; } [JsonProperty("operations")] public Operation[] Operations { get; set; } } public class GamePack { [JsonProperty("gamePackID")] public string GamePackID { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("platform")] public string Platform { get; set; } } public class GameSessionStop { [JsonProperty("gameSessionID")] public string GameSessionID { get; } [JsonConstructor] public GameSessionStop(string gameSessionID) { GameSessionID = gameSessionID; } } public class GenerateAuthCode : MessageData { [JsonProperty("appID")] public string AppID { get; } [JsonIgnore] internal string CodeVerifier { get; } [JsonProperty("codeChallenge")] public string CodeChallenge { get; } [JsonProperty("codeChallengeMethod")] public string CodeChallengeMethod => "S256"; [JsonProperty(/*Could not decode attribute arguments.*/)] public string[]? Scopes { get; } [JsonProperty(/*Could not decode attribute arguments.*/)] public string[]? Packs { get; } [JsonProperty("qrCode")] public bool QrCode { get; } public GenerateAuthCode(string appID, IEnumerable<string>? scopes = null, IEnumerable<string>? packs = null, bool qrCode = false) { AppID = appID; Scopes = scopes?.ToArray(); Packs = packs?.ToArray(); QrCode = qrCode; byte[] array = new byte[32]; using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) { randomNumberGenerator.GetBytes(array); } CodeVerifier = CreateBase64Url(array); using SHA256 sHA = SHA256.Create(); CodeChallenge = CreateBase64Url(sHA.ComputeHash(Encoding.ASCII.GetBytes(CodeVerifier))); } public GenerateAuthCode(string appID, bool qrCode = false) : this(appID, null, null, qrCode) { } private static string CreateBase64Url(byte[] bytes) { return Convert.ToBase64String(bytes).TrimEnd('=').Replace('+', '-') .Replace('/', '_'); } public override LocalMessage Wrap() { return new LocalMessage("generate-auth-code", this); } } public class LocalMessage { [JsonProperty("action")] public string Action { get; } [JsonProperty("data")] public MessageData Data { get; } public LocalMessage(string action, MessageData data) { Action = action; Data = data; } } public abstract class MessageData { public abstract LocalMessage Wrap(); public string WrapJson() { return JsonConvert.SerializeObject((object)Wrap()); } } public class Pong { } public class RpcMessage : MessageData { [JsonProperty("token")] public string Token { get; } [JsonProperty("call")] public Call Call { get; } public RpcMessage(string token, Call call) { Token = token; Call = call; } public override LocalMessage Wrap() { return new LocalMessage("rpc", this); } } [JsonConverter(typeof(Converter))] public class ServerMessage { protected class Converter : JsonConverter<ServerMessage> { public override void WriteJson(JsonWriter writer, ServerMessage? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); } else { JToken.FromObject((object)value, serializer).WriteTo(writer); } } public override ServerMessage? ReadJson(JsonReader reader, Type objectType, ServerMessage? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_029b: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) JObject val = JObject.Load(reader); JToken obj = val["domain"]; string domain = ((obj != null) ? obj.ToObject<string>(serializer) : null) ?? throw new JsonSerializationException("Missing 'domain' field."); JToken obj2 = val["type"]; string text = ((obj2 != null) ? obj2.ToObject<string>(serializer) : null) ?? throw new JsonSerializationException("Missing 'type' field."); JToken val2 = val["payload"] ?? throw new JsonSerializationException("Missing 'payload' field."); switch (text) { case "application-auth-code": { ApplicationAuthCode payload3 = val2.ToObject<ApplicationAuthCode>(serializer) ?? throw new JsonSerializationException("Invalid payload for application-auth-code."); return new ServerMessage(domain, text, payload3); } case "application-auth-code-redeemed": { ApplicationAuthCodeRedeemed payload6 = val2.ToObject<ApplicationAuthCodeRedeemed>(serializer) ?? throw new JsonSerializationException("Invalid payload for application-auth-code-redeemed."); return new ServerMessage(domain, text, payload6); } case "application-auth-code-error": { ApplicationAuthCodeError payload4 = val2.ToObject<ApplicationAuthCodeError>(serializer) ?? throw new JsonSerializationException("Invalid payload for application-auth-code-error."); return new ServerMessage(domain, text, payload4); } case "subscription-result": { SubscriptionResult payload5 = val2.ToObject<SubscriptionResult>(serializer) ?? throw new JsonSerializationException("Invalid payload for subscription-result."); return new ServerMessage(domain, text, payload5); } case "game-session-stop": { GameSessionStop payload2 = val2.ToObject<GameSessionStop>(serializer) ?? throw new JsonSerializationException("Invalid payload for game-session-stop."); return new ServerMessage(domain, text, payload2); } case "game-session-menu-update": case "game-session-menu-sync": return null; case "pong": return new ServerMessage(domain, text, new object()); case "effect-request": try { EffectRequest payload = val2.ToObject<EffectRequest>(serializer) ?? throw new JsonSerializationException("Invalid payload for effect-request."); return new ServerMessage(domain, text, payload); } catch (Exception ex) { Log.Error(ex, "Failed to deserialize effect-request payload: " + ex.ToString(), false); throw new JsonSerializationException("Failed to deserialize effect-request payload."); } default: Log.Error((object)("Unknown message type: " + text), false); return null; } } } [JsonProperty("domain")] public string Domain { get; } [JsonProperty("type")] public string Type { get; } [JsonProperty("payload")] public object Payload { get; set; } public ServerMessage(string domain, string type, object payload) { Domain = domain; Type = type; Payload = payload; } } public class Subscribe : MessageData { [JsonProperty("token")] public string Token { get; } [JsonProperty("topics")] public string[] Topics { get; } public Subscribe(string token, IEnumerable<string>? topics = null) { Token = token; Topics = topics?.ToArray() ?? Array.Empty<string>(); } public override LocalMessage Wrap() { return new LocalMessage("subscribe", this); } } public class SubscriptionResult { [JsonProperty("success")] public string[] Success { get; } [JsonProperty("failure")] public string[] Failure { get; } [JsonConstructor] public SubscriptionResult(string[]? success, string[]? failure) { Success = success ?? Array.Empty<string>(); Failure = failure ?? Array.Empty<string>(); } } public class User { public struct App { public string appID; public string[] scopes; public string[] packs; } public string type; public string jti; public string ccUID; public string originID; public string profileType; public string name; public string[] roles; public App app; [JsonProperty("exp")] [JsonConverter(typeof(UnixTimestampConverter))] public DateTimeOffset exp; public string ver; } } namespace CrowdControl.Client.WebSocket.Actions { public abstract class EffectBase : IEffect { public virtual string EffectID => IDs.First(); public virtual IReadOnlyList<string> IDs { get; } = Array.Empty<string>(); public virtual SITimeSpan DefaultDuration => SITimeSpan.op_Implicit(0.0); public virtual uint MaxQuantity => 1u; public virtual ParameterList? Parameters => null; public virtual IReadOnlyList<string> Conflicts => Array.Empty<string>(); public bool IsTimed => DefaultDuration > 0.0; public bool IsCustom { get; set; } public CrowdControl CrowdControl { get; } protected EffectBase(CrowdControl crowdControl) { CrowdControl = crowdControl ?? throw new ArgumentNullException("crowdControl"); } private EffectBase(CrowdControl crowdControl, string[] newEffectIDs) : this(crowdControl) { IDs = newEffectIDs; } public abstract EffectResponse Start(EffectRequest request); public virtual EffectResponse? Tick(EffectRequest request) { return null; } public virtual EffectResponse? Pause(EffectRequest request) { return null; } public virtual EffectResponse? Resume(EffectRequest request) { return null; } public virtual EffectResponse? Stop(EffectRequest request) { return null; } public virtual JObject ToJObject() { throw new NotSupportedException("Serialization is not supported for this effect."); } } public interface IEffect { string EffectID => IDs.First(); IReadOnlyList<string> IDs { get; } SITimeSpan DefaultDuration { get; } ParameterList? Parameters { get; } uint MaxQuantity { get; } IReadOnlyList<string> Conflicts { get; } bool IsTimed { get; } bool IsCustom { get; } CrowdControl CrowdControl { get; } EffectResponse Start(EffectRequest request); EffectResponse? Tick(EffectRequest request); EffectResponse? Pause(EffectRequest request); EffectResponse? Resume(EffectRequest request); EffectResponse? Stop(EffectRequest request); JObject ToJObject(); } public interface ICloneableEffect : IEffect { ICloneableEffect Clone(params string[] newEffectIDs); } public interface IEffectLoader { IDictionary<string, IEffect> Effects { get; } bool CloneEffect(string sourceEffectID, params string[] destEffectIDs) { if (((destEffectIDs != null && destEffectIDs.Length != 0) ? 1 : 0) <= (false ? 1 : 0)) { Log.Error((object)"No destination effect IDs provided for cloning.", false); return false; } if (!Effects.TryGetValue(sourceEffectID, out IEffect value)) { Log.Error((object)("Effect '" + sourceEffectID + "' not found."), false); return false; } foreach (string text in destEffectIDs) { if (!Effects.ContainsKey(text)) { Log.Error((object)("Effect '" + text + "' already exists. Clone operation aborted."), false); return false; } } if (!(value is ICloneableEffect cloneableEffect)) { Log.Error((object)("Effect '" + sourceEffectID + "' does not support cloning."), false); return false; } ICloneableEffect value2 = cloneableEffect.Clone(destEffectIDs); bool result = true; foreach (string text2 in destEffectIDs) { if (string.IsNullOrWhiteSpace(text2)) { Log.Error((object)"Destination effect IDs cannot be null or whitespace.", false); result = false; continue; } if (!Effects.TryAdd(text2, value2)) { Log.Error((object)("Effect '" + text2 + "' already exists. Clone operation failed."), false); result = false; } Log.Debug((object)("Effect '" + sourceEffectID + "' cloned to '" + text2 + "'.")); } return result; } void Load(); void Unload(); } internal class TimedEffectState { public enum EffectState { NotStarted, Running, Paused, Finished, Errored } public readonly EffectRequest Request; public readonly SITimeSpan Duration; public readonly IEffect Effect; private readonly Func<EffectResponse, bool>? m_temporaryFailureHandler; public SITimeSpan TimeRemaining; private int m_stateLock; private static readonly IEnumerator EMPTY_ENUMERATOR = Enumerable.Empty<object>().GetEnumerator(); public CrowdControl CrowdControl => Effect.CrowdControl; public EffectState State { get; private set; } = EffectState.NotStarted; private bool TryGetLock() { return Interlocked.CompareExchange(ref m_stateLock, 1, 0) == 0; } private void ReleaseLock() { m_stateLock = 0; } public TimedEffectState(IEffect effect, EffectRequest request, SITimeSpan duration, Func<EffectResponse, bool>? temporaryFailureHandler = null) { //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_0043: 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) Effect = effect ?? throw new ArgumentNullException("effect"); Request = request ?? throw new ArgumentNullException("request"); Duration = duration; TimeRemaining = duration; m_temporaryFailureHandler = temporaryFailureHandler; } public IEnumerator Start() { Log.Debug((object)$"Starting timed effect: {Request.EffectID} with duration {Duration}"); bool locked = false; try { while (true) { bool flag; locked = (flag = TryGetLock()); if (flag) { break; } yield return null; } if (State != EffectState.NotStarted) { yield break; } try { EffectResponse response = Effect.Start(Request); if ((int)response.Status == 32 && (m_temporaryFailureHandler?.Invoke(response) ?? false)) { State = EffectState.Finished; yield break; } TimeRemaining = Duration; State = ((!EffectStatusEx.IsFailure(response.Status)) ? EffectState.Running : EffectState.Errored); CrowdControl.Respond(Request, response.Status, TimeRemaining, response.StandardError, response.Message); } catch (Exception ex) { Log.Error((object)ex.Message, false); EffectResponse response2 = new EffectResponse((EffectStatus)32, (StandardErrors)1); if (m_temporaryFailureHandler?.Invoke(response2) ?? false) { State = EffectState.Finished; yield break; } State = EffectState.Errored; CrowdControl.Respond(Request, response2.Status, response2.StandardError); } } finally { if (locked) { ReleaseLock(); } } } public IEnumerator Pause() { Log.Debug((object)$"Pausing timed effect: {Request.EffectID} with time remaining {TimeRemaining}"); bool locked = false; try { while (true) { bool flag; locked = (flag = TryGetLock()); if (flag) { break; } yield return null; } if (State == EffectState.Running) { try { EffectResponse response = Effect.Pause(Request) ?? ((EffectResponse)(EffectStatus)66); State = EffectState.Paused; CrowdControl.Respond(Request, response.Status, TimeRemaining, response.StandardError, response.Message); yield break; } catch (Exception ex) { Exception e = ex; Log.Error((object)e.Message, false); State = EffectState.Errored; CrowdControl.Respond(Request, (EffectStatus)32, (StandardErrors)1); yield break; } } } finally { if (locked) { ReleaseLock(); } } } public IEnumerator Resume() { Log.Debug((object)$"Resuming timed effect: {Request.EffectID} with time remaining {TimeRemaining}"); bool locked = false; try { while (true) { bool flag; locked = (flag = TryGetLock()); if (flag) { break; } yield return null; } if (State == EffectState.Paused) { try { EffectResponse response = Effect.Resume(Request) ?? ((EffectResponse)(EffectStatus)67); State = EffectState.Running; CrowdControl.Respond(Request, response.Status, TimeRemaining, response.StandardError, response.Message); yield break; } catch (Exception ex) { Exception e = ex; Log.Error((object)e.Message, false); State = EffectState.Errored; CrowdControl.Respond(Request, (EffectStatus)32, (StandardErrors)1); yield break; } } } finally { if (locked) { ReleaseLock(); } } } public IEnumerator Stop() { Log.Debug((object)$"Stopping timed effect: {Request.EffectID} with time remaining {TimeRemaining}"); bool locked = false; try { while (true) { bool flag; locked = (flag = TryGetLock()); if (flag) { break; } yield return null; } if (State != EffectState.Finished) { try { EffectResponse response = Effect.Stop(Request) ?? ((EffectResponse)(EffectStatus)79); State = EffectState.Finished; CrowdControl.Respond(Request, response.Status, TimeRemaining, response.StandardError, response.Message); yield break; } catch (Exception ex) { Exception e = ex; Log.Error((object)e.Message, false); State = EffectState.Errored; CrowdControl.Respond(Request, (EffectStatus)32, (StandardErrors)1); yield break; } } } finally { if (locked) { ReleaseLock(); } } } public IEnumerator Tick(SITimeSpan deltaTim
BepInEx/plugins/CrowdControl.Common.Mini.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; 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.Tasks; using CrowdControl.Common.Converters; using CrowdControl.Games; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("© 2026 Warp World, Inc.")] [assembly: AssemblyFileVersion("5.0.9747.21244")] [assembly: AssemblyInformationalVersion("5.0.9747.21244+5282282ebdf7aa9b9e1a281bb3ff1a3790068b3a")] [assembly: AssemblyProduct("CrowdControl.Common.Mini")] [assembly: AssemblyTitle("CrowdControl.Common.Mini")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.0.9747.21244")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [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] [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 CrowdControl.Games { public readonly struct ErrorMessage { public delegate string MessageSource(params object?[]? parameters); public static readonly ErrorMessage Unknown = new ErrorMessage(delegate(object?[]? @params) { if (@params == null || @params.Length == 0) { return "Unknown error."; } return (@params[0] == null) ? "Unknown error." : $"Unknown error \"{@params[0]}\"."; }); private readonly object _friendly; private readonly object _technical; public ErrorMessage(string message) { _friendly = message; _technical = message; } public ErrorMessage(MessageSource message) { _friendly = message; _technical = message; } public ErrorMessage(string friendly, string technical) { _friendly = friendly; _technical = technical; } public ErrorMessage(MessageSource friendly, string technical) { _friendly = friendly; _technical = technical; } public ErrorMessage(string friendly, MessageSource technical) { _friendly = friendly; _technical = technical; } public ErrorMessage(MessageSource friendly, MessageSource technical) { _friendly = friendly; _technical = technical; } private ErrorMessage(object friendly, object technical) { _friendly = friendly; _technical = technical; } public string Friendly(params object?[] @params) { return (_friendly as string) ?? (_friendly as MessageSource)?.Invoke(@params) ?? Unknown.Friendly(@params); } public string Technical(params object?[] @params) { return (_technical as string) ?? (_technical as MessageSource)?.Invoke(@params) ?? Unknown.Technical(@params); } public ErrorMessage WithFriendly(string message) { return new ErrorMessage(message, _technical); } public ErrorMessage WithFriendly(MessageSource message) { return new ErrorMessage(message, _technical); } public ErrorMessage WithTechnical(string message) { return new ErrorMessage(_friendly, message); } public ErrorMessage WithTechnical(MessageSource message) { return new ErrorMessage(_friendly, message); } } } namespace CrowdControl.Common { [JsonConverter(typeof(CamelCaseStringEnumConverter<Morality>))] public enum Morality { ExtremelyHarmful = -90, VeryHarmful = -60, Harmful = -30, SlightlyHarmful = -10, Neutral = 0, SlightlyHelpful = 10, Helpful = 30, VeryHelpful = 60, ExtremelyHelpful = 90 } [JsonConverter(typeof(CamelCaseStringEnumConverter<Orderliness>))] public enum Orderliness { ExtremelyChaotic = -90, VeryChaotic = -60, Chaotic = -30, SlightlyChaotic = -10, Neutral = 0, SlightlyControlled = 10, Controlled = 30, VeryControlled = 60, ExtremelyControlled = 90 } public static class AlignmentEx { public static float FloatValue(this Orderliness orderliness) { return (float)orderliness / 100f; } public static float FloatValue(this Morality morality) { return (float)morality / 100f; } } [Serializable] [JsonConverter(typeof(Converter))] public readonly struct Alignment { private class Converter : JsonConverter<Alignment> { public override void WriteJson(JsonWriter writer, Alignment value, JsonSerializer serializer) { writer.WriteStartObject(); writer.WritePropertyName("orderliness"); serializer.Serialize(writer, (object)value.Orderliness.FloatValue()); writer.WritePropertyName("morality"); serializer.Serialize(writer, (object)value.Morality.FloatValue()); writer.WriteEndObject(); } public override Alignment ReadJson(JsonReader reader, Type objectType, Alignment existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); JToken obj = val["orderliness"]; Orderliness orderliness = ((obj != null) ? obj.ToObject<Orderliness>(serializer) : Orderliness.Neutral); JToken obj2 = val["morality"]; Morality morality = ((obj2 != null) ? obj2.ToObject<Morality>(serializer) : Morality.Neutral); return new Alignment(orderliness, morality); } } public readonly Orderliness Orderliness; public readonly Morality Morality; public Alignment(Orderliness orderliness) : this(orderliness, Morality.Neutral) { } public Alignment(Morality morality) : this(Orderliness.Neutral, morality) { } public Alignment(Orderliness orderliness, Morality morality) { Orderliness = orderliness; Morality = morality; } public void Deconstruct(out Orderliness orderliness, out Morality morality) { orderliness = Orderliness; morality = Morality; } public static Alignment operator +(Alignment alignment, Orderliness orderliness) { return new Alignment(orderliness, alignment.Morality); } public static Alignment operator +(Alignment alignment, Morality morality) { return new Alignment(alignment.Orderliness, morality); } public static implicit operator Alignment(Orderliness orderliness) { return new Alignment(orderliness); } public static implicit operator Alignment(Morality morality) { return new Alignment(morality); } } [JsonConverter(typeof(CamelCaseStringEnumConverter<BlockType>))] public enum BlockType : byte { EffectRequest = 16, EffectResponse = 17, EffectReport = 18, DataRequest = 32, DataResponse = 33, GenericEvent = 48, Rpc = 64, MenuLoad = 209, GameSelection = 225, SessionState = 226, SessionAttach = 227, ConnectorStatus = 228, KeepAlive = 240, Command = 241, Shutdown = 254 } public class ColorTextWriter : TextWriter { private readonly TextWriter original; private readonly ConsoleColor color; public override Encoding Encoding => original.Encoding; public ColorTextWriter(TextWriter original, ConsoleColor color) { this.original = original; this.color = color; } public override void Write(char value) { Console.ForegroundColor = color; original.Write(value); Console.ResetColor(); } public override void Write(string? value) { if (value == null) { value = string.Empty; } Console.ForegroundColor = color; original.Write(value); Console.ResetColor(); } public override void WriteLine(string? value) { if (value == null) { value = string.Empty; } Console.ForegroundColor = color; original.WriteLine(value); Console.ResetColor(); } } [Serializable] public abstract class CrowdControlBlock : IEquatable<CrowdControlBlock> { public static Func<Guid> IDSource = Guid.NewGuid; [JsonProperty(PropertyName = "id")] public Guid ID = IDSource(); [JsonProperty(PropertyName = "stamp")] [JsonConverter(typeof(UnixTimestampConverter))] public DateTimeOffset Stamp = DateTimeOffset.UtcNow; [JsonProperty(PropertyName = "type")] public BlockType BlockType; public event Action? Sent; public void InvokeSent() { this.Sent?.Invoke(); } protected CrowdControlBlock(BlockType type) { BlockType = type; } public static CrowdControlBlock Deserialize(string json) { return Deserialize(JToken.Parse(json)); } public static CrowdControlBlock Deserialize(string json, BlockType type) { return Deserialize(JToken.Parse(json), type); } public static CrowdControlBlock Deserialize(JToken token) { return Deserialize(token, (BlockType)Extensions.Value<byte>((IEnumerable<JToken>)token[(object)"type"])); } public static CrowdControlBlock Deserialize(JToken token, BlockType type) { if (1 == 0) { } CrowdControlBlock result = type switch { BlockType.EffectRequest => token.ToObject<EffectRequest>(), BlockType.EffectResponse => token.ToObject<EffectResponse>(), BlockType.EffectReport => token.ToObject<EffectReport>(), BlockType.DataRequest => token.ToObject<DataRequest>(), BlockType.DataResponse => token.ToObject<DataResponse>(), BlockType.GenericEvent => token.ToObject<GenericEventBlock>(), _ => throw new ArgumentOutOfRangeException(), }; if (1 == 0) { } return result; } public bool Equals(CrowdControlBlock? other) { if (other == null) { return false; } if (this == other) { return true; } return ID.Equals(other.ID); } public override bool Equals(object? obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (!TypeEx.IsAssignableTo(obj.GetType(), typeof(CrowdControlBlock))) { return false; } return Equals((CrowdControlBlock)obj); } public override int GetHashCode() { return ID.GetHashCode(); } } [Serializable] public class DataRequest : CrowdControlBlock { [JsonProperty(PropertyName = "key")] public string Key; [JsonProperty(PropertyName = "followUpTo")] public Guid? FollowUpTo { get; } [JsonProperty(PropertyName = "followUpIndex")] public uint? FollowUpIndex { get; } [JsonProperty(PropertyName = "attemptCount")] public uint AttemptCount { get; set; } [JsonProperty(PropertyName = "attemptDuration")] public SITimeSpan AttemptDuration { get; set; } [JsonProperty(PropertyName = "retryMaxAttempts")] public uint? RetryMaxAttempts { get; set; } [JsonProperty(PropertyName = "retryMaxTime")] public SITimeSpan? RetryMaxTime { get; set; } [JsonProperty(PropertyName = "retryInterval")] public SITimeSpanRange? RetryInterval { get; set; } [JsonProperty(PropertyName = "aggressiveRetry")] public bool AggressiveRetry { get; set; } [JsonIgnore] public bool LocalTest { get; set; } public DataRequest(string key) : base(BlockType.DataRequest) { Key = key; } private DataRequest(string key, Guid followUpTo, uint followUpIndex) : base(BlockType.GenericEvent) { Key = key; FollowUpTo = followUpTo; FollowUpIndex = followUpIndex; } public DataRequest GetFollowUp(uint index) { DataRequest dataRequest = new DataRequest(Key, ID, index); dataRequest.ID = CrowdControlBlock.IDSource(); dataRequest.AttemptCount = 0u; dataRequest.AttemptDuration = SITimeSpan.Zero; dataRequest.LocalTest = LocalTest; dataRequest.RetryInterval = RetryInterval; dataRequest.RetryMaxAttempts = RetryMaxAttempts; dataRequest.RetryMaxTime = RetryMaxTime; return dataRequest; } } [Serializable] public class DataResponse : ResponseBlock { [JsonProperty(PropertyName = "key")] public string Key; [JsonProperty(PropertyName = "value")] public JToken? Value; [JsonProperty(PropertyName = "status")] public EffectStatus Status; [JsonProperty(/*Could not decode attribute arguments.*/)] public SITimeSpan? TimeRemaining; protected DataResponse(BlockType type) : base(type) { } public DataResponse(string key, EffectStatus status, object? value = null, SITimeSpan? timeRemaining = null, string? message = "", Enum? messageID = null, ErrorSource? errorSource = null, bool? abnormal = null) : base(BlockType.DataResponse) { Status = status; Key = key; value = Filter(value); Value = value.IfNotNull((Func<object, JToken?>)JToken.FromObject); TimeRemaining = timeRemaining; Message = message ?? string.Empty; ErrorSource = errorSource.GetValueOrDefault(); MessageID = messageID?.ToCamelCase(); } public DataResponse(DataRequest request, EffectStatus status, object? value = null, SITimeSpan? timeRemaining = null, string? message = "", Enum? messageID = null, ErrorSource? errorSource = null, bool? abnormal = null) : base(BlockType.DataResponse) { Request = request.ID; Status = status; Key = request.Key; value = Filter(value); Value = value.IfNotNull((Func<object, JToken?>)JToken.FromObject); TimeRemaining = timeRemaining; Message = message ?? string.Empty; MessageID = messageID?.ToCamelCase(); } protected static object? Filter(object? value) { if (value is string text) { return text.Replace("\"", string.Empty); } return value; } public static DataResponse SuccessIfDefined(string key, object? value, string failMessage = "") { if (value == null) { return FailTemporary(key, failMessage); } if (value is string value2 && string.IsNullOrWhiteSpace(value2)) { return FailTemporary(key, failMessage); } return Success(key, value); } public static DataResponse Success(string key, object? value) { return new DataResponse(key, EffectStatus.Success, value); } public static DataResponse Success<TValue>(string key, ReadOnlySpan<TValue> value) { return new DataResponse<TValue>(key, EffectStatus.Success, value); } public static DataResponse FailTemporary(string key, string message = "") { return new DataResponse(key, EffectStatus.FailTemporary, null, null, message); } public static DataResponse FailPermanent(string key, string message = "") { return new DataResponse(key, EffectStatus.FailPermanent, null, null, message); } public static DataResponse DelayEstimated(string key, SITimeSpan delay = default(SITimeSpan), string message = "") { return new DataResponse(key, EffectStatus.DelayEstimated, null, null, message); } } public class DataResponse<T> : DataResponse { public DataResponse(string key, EffectStatus status, ReadOnlySpan<T> value = default(ReadOnlySpan<T>), SITimeSpan? timeRemaining = null, string? message = "", Enum? messageID = null) : base(BlockType.DataResponse) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) Status = status; Key = key; Value = (JToken?)new JArray(); ReadOnlySpan<T> readOnlySpan = value; for (int i = 0; i < readOnlySpan.Length; i++) { T val = readOnlySpan[i]; ((JContainer)(JArray)Value).Add(DataResponse.Filter(val)); } TimeRemaining = timeRemaining; Message = message ?? string.Empty; MessageID = messageID?.ToCamelCase(); } public DataResponse(DataRequest request, EffectStatus status, ReadOnlySpan<T> value = default(ReadOnlySpan<T>), SITimeSpan? timeRemaining = null, string? message = "", Enum? messageID = null) : base(BlockType.DataResponse) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) Request = request.ID; Status = status; Key = request.Key; Value = (JToken?)new JArray(); ReadOnlySpan<T> readOnlySpan = value; for (int i = 0; i < readOnlySpan.Length; i++) { T val = readOnlySpan[i]; ((JContainer)(JArray)Value).Add(DataResponse.Filter(val)); } TimeRemaining = timeRemaining; Message = message ?? string.Empty; MessageID = messageID?.ToCamelCase(); } } [Serializable] [JsonConverter(typeof(Converter))] public class Effect : IEquatable<Effect> { private class Converter : JsonConverter<Effect> { public override bool CanWrite => false; public override Effect? ReadJson(JsonReader reader, Type objectType, Effect? existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); if (val["id"] == null && val["effectID"] != null) { val["id"] = val["effectID"]; } Effect effect = new Effect(); try { string value = ((JToken)val).Value<string>((object)"type"); EffectType result; if (string.IsNullOrWhiteSpace(value)) { effect.EffectType = EffectType.Unknown; } else if (Enum.TryParse<EffectType>(value, ignoreCase: true, out result)) { effect.EffectType = result; } else { effect.EffectType = EffectType.Unknown; } val.Remove("type"); } catch (Exception ex) { Log.Error(ex); effect.EffectType = EffectType.Unknown; } try { serializer.Populate(((JToken)val).CreateReader(), (object)effect); } catch (Exception ex2) { Log.Error(ex2, "Incomplete effect deserialization, attempting recovery. (WHEN REPORTING, PLEASE INCLUDE THE RPC REQUEST THAT PRODUCED THIS ERROR!)"); JToken obj = val["id"]; effect.ID = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null) ?? string.Empty; } return effect; } public override void WriteJson(JsonWriter writer, Effect? value, JsonSerializer serializer) { throw new NotImplementedException(); } } [JsonProperty(PropertyName = "id")] public string ID; [JsonProperty(PropertyName = "name")] public string Name; [JsonProperty(PropertyName = "sortName")] public string? SortName; [JsonProperty(PropertyName = "quantity")] public QuantityRange Quantity = 1; [JsonIgnore] public uint DefaultQuantity; [JsonProperty(PropertyName = "duration")] public SITimeSpan? Duration; [JsonProperty(PropertyName = "isDurationEditable")] public bool IsDurationEditable = true; [JsonProperty(PropertyName = "description")] public string? Description; [JsonProperty(PropertyName = "note")] public string? Note; [JsonProperty(PropertyName = "startMessage")] public string? StartMessage; [JsonProperty(PropertyName = "endMessage")] public string? EndMessage; [JsonProperty(PropertyName = "category")] public List<string>? Category; [JsonProperty(PropertyName = "group")] public List<string>? Group; [JsonProperty(PropertyName = "tags")] public List<string>? Tags; [JsonProperty(PropertyName = "metadata")] public List<string>? Metadata; [JsonProperty(PropertyName = "image")] public string? Image; [JsonProperty(PropertyName = "queueWarning")] public uint? QueueWarning; [JsonProperty(PropertyName = "queueMax")] public uint? QueueMax; [JsonProperty(PropertyName = "viewerCooldown")] public SITimeSpan? ViewerCooldown; [JsonProperty(PropertyName = "sessionCooldown")] public SITimeSpan? SessionCooldown; [JsonProperty(PropertyName = "price")] public uint Price; [JsonProperty(PropertyName = "parameters")] public ParameterList? Parameters; [JsonProperty(PropertyName = "responseTimeout")] public SITimeSpan? ResponseTimeout; [JsonProperty(PropertyName = "retryMaxAttempts")] public uint? RetryMaxAttempts; [JsonProperty(PropertyName = "retryMaxTime")] public SITimeSpan? RetryMaxTime; [JsonProperty(PropertyName = "retryInterval")] public SITimeSpanRange? RetryInterval; [JsonProperty(PropertyName = "errorOverride")] public string? ErrorOverride; [JsonProperty(PropertyName = "inactive")] public bool Inactive; [JsonProperty(PropertyName = "hidden")] public bool Disabled; [JsonProperty(PropertyName = "alignment")] public Alignment? Alignment; [JsonProperty(PropertyName = "noPooling")] public bool? NoPooling; [JsonProperty(PropertyName = "scaleGroups")] public List<string>? ScaleGroups; [JsonProperty(PropertyName = "type")] public EffectType EffectType; private const string DURATION_S = "\\(\\s*(\\d+)\\s*(seconds?|minutes?|secs?|mins?|m|s)\\s*\\)"; public static readonly Regex DURATION = new Regex("\\(\\s*(\\d+)\\s*(seconds?|minutes?|secs?|mins?|m|s)\\s*\\)"); private static readonly Regex SANITIZE = new Regex("(?i)\\(\\s*(\\d+)\\s*(seconds?|minutes?|secs?|mins?|m|s)\\s*\\)"); private static readonly SITimeSpan ONE_MINUTE = SITimeSpan.FromMinutes(1.0); private string m_displayName; [JsonIgnore] public bool HasQuantity => !Quantity.IsOne; [JsonIgnore] public bool HasDuration => Duration != (double?)null && Duration != SITimeSpan.Zero; [JsonProperty(PropertyName = "scaleFactor")] public float ScaleFactor { get; set; } [JsonProperty(PropertyName = "scaleDecayTime")] public SITimeSpan ScaleDecayTime { get; set; } [JsonIgnore] public string DisplayName { get { return m_displayName ?? GetDisplayName(Name, Duration); } set { m_displayName = value; } } public override string ToString() { return Name + ((!Quantity.IsOne) ? $" [{Quantity}]" : string.Empty); } public string ResolveName(IEnumerable<IParameterValue> parameters) { return Name + " " + (parameters.Any() ? ("(" + string.Join('/', parameters.Select((IParameterValue p) => p.Name)) + ")") : string.Empty); } public static string GetDisplayName(string name, SITimeSpan? duration) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } if (!duration.HasValue) { return name; } if (duration.Value >= ONE_MINUTE) { string text = duration.Value.TotalMinutes.ToString("F1", CultureInfo.InvariantCulture).Replace(".0", string.Empty); text = "(" + text + " minute" + (string.Equals(text, "1") ? string.Empty : "s") + ")"; return SANITIZE.Replace(name, string.Empty).Trim() + " " + text; } if (duration.Value > SITimeSpan.Zero) { string text = duration.Value.TotalSeconds.ToString("N0", CultureInfo.InvariantCulture); text = "(" + text + " second" + (string.Equals(text, "1") ? string.Empty : "s") + ")"; return SANITIZE.Replace(name, string.Empty).Trim() + " " + text; } return SANITIZE.Replace(name, string.Empty).Trim(); } public static string SanitizeID(string input) { if (string.IsNullOrWhiteSpace(input)) { return "_"; } string input2 = Regex.Replace(input, "[^\\w\\s]", ""); input2 = Regex.Replace(input2, "_", " "); string[] array = input2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return "_"; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(array[0].ToLower()); for (int i = 1; i < array.Length; i = checked(i + 1)) { stringBuilder.Append(CultureInfo.InvariantCulture.TextInfo.ToTitleCase(array[i].ToLower())); } string text = stringBuilder.ToString(); if (char.IsDigit(text[0])) { text = "_" + text; } return text; } [JsonConstructor] internal Effect() { } public Effect(string name, string id) { Name = name; ID = id; } public bool Equals(Effect? other) { if (other == null) { return false; } if (this == other) { return true; } return string.Equals(ID, other.ID, StringComparison.InvariantCultureIgnoreCase); } public override bool Equals(object? obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (obj.GetType() != typeof(Effect)) { return false; } return Equals((Effect)obj); } public override int GetHashCode() { return ID.GetHashCode(); } } [Serializable] public class EffectReport : CrowdControlBlock { [JsonConverter(typeof(CamelCaseStringEnumConverter<EffectReportType>))] public enum EffectReportType { Game, Video, Audio, Image, Live } [JsonProperty(/*Could not decode attribute arguments.*/)] public string[]? IDs; [JsonProperty(PropertyName = "message")] public string? Message; [JsonProperty(PropertyName = "messageID")] public string? MessageID; [JsonProperty(PropertyName = "identifierType")] public IdentifierType IDType { get; } [JsonProperty(PropertyName = "effectType")] public EffectReportType EffectType { get; } [JsonProperty(PropertyName = "status")] public EffectStatus Status { get; } public override string ToString() { return string.Join('/', IDs) + " - " + Status.ToString() + (string.IsNullOrWhiteSpace(Message) ? string.Empty : (" - " + Message)); } public EffectReport(string effect, EffectStatus status, string? message = null, Enum? messageID = null) : base(BlockType.EffectReport) { IDs = new string[1] { effect }; IDType = IdentifierType.Effect; Status = status; Message = message; MessageID = messageID?.ToCamelCase(); } public EffectReport(IEnumerable<string>? ids, IdentifierType idType, EffectStatus status, string? message = null) : base(BlockType.EffectReport) { IDs = ids?.ToArray(); IDType = idType; Status = status; Message = message; } } [Serializable] [JsonConverter(typeof(EffectRequestConverter))] public class EffectRequest : CrowdControlBlock { [JsonProperty(PropertyName = "effectID")] public readonly string EffectID; [JsonProperty(PropertyName = "effect")] public readonly Effect? Effect; [JsonProperty(PropertyName = "quantity")] public uint Quantity; [JsonProperty(PropertyName = "repeat")] [DefaultValue(1)] public uint Repeat = 1u; [JsonProperty(PropertyName = "repeatDelay")] public SITimeSpan RepeatDelay = 1.0; [JsonProperty(PropertyName = "parameters")] public ParameterResults? Parameters; [JsonProperty(PropertyName = "viewers")] public List<UserRecord>? Viewers; [JsonProperty(PropertyName = "duration")] public SITimeSpan Duration; [JsonProperty(PropertyName = "target")] public UserRecord? Target; [JsonProperty(PropertyName = "origin")] public UserRecord? Origin; [JsonProperty(PropertyName = "attemptCount")] public uint AttemptCount; [JsonProperty(PropertyName = "attemptDuration")] public SITimeSpan AttemptDuration; [JsonProperty(PropertyName = "attemptInitialTime")] [JsonConverter(typeof(UnixTimestampConverter))] public DateTimeOffset AttemptInitialTime; [JsonProperty(PropertyName = "free")] public bool Free; [JsonProperty(PropertyName = "ignoreStateChecks")] public bool IgnoreStateChecks; [JsonProperty(PropertyName = "skipPipelineDelay")] public bool SkipPipelineDelay; [JsonIgnore] public bool Queued; [JsonProperty(PropertyName = "args")] public Dictionary<string, object>? Arguments; [JsonProperty(PropertyName = "priority")] public bool Priority; [JsonProperty(PropertyName = "anonymous")] public bool Anonymous; [JsonProperty(PropertyName = "cost")] public long Cost; [JsonProperty(PropertyName = "responseTimeout")] public SITimeSpan? ResponseTimeout; [JsonProperty(PropertyName = "errorOverride")] public string? ErrorOverride; [JsonProperty(PropertyName = "sourceDetails")] [JsonConverter(typeof(IEffectSourceDetails.Converter))] public IEffectSourceDetails? SourceDetails; [JsonProperty(PropertyName = "followUpTo")] public Guid? FollowUpTo { get; } [JsonProperty(PropertyName = "followUpIndex")] public uint? FollowUpIndex { get; } [JsonIgnore] public bool LocalTest { get; set; } [JsonProperty(PropertyName = "admin")] public bool Admin { get; set; } [JsonProperty(PropertyName = "ignoreMaxQueueLength")] public bool IgnoreMaxQueueLength { get; set; } [JsonProperty(PropertyName = "retryMaxAttempts")] public uint? RetryMaxAttempts { get; set; } [JsonProperty(PropertyName = "retryMaxTime")] public SITimeSpan? RetryMaxTime { get; set; } [JsonProperty(PropertyName = "retryInterval")] public SITimeSpanRange? RetryInterval { get; set; } [JsonProperty(PropertyName = "aggressiveRetry")] public bool AggressiveRetry { get; set; } [JsonIgnore] public string DisplayViewer => ViewerName(); [JsonIgnore] public string DisplayViewerPortable => ViewerNamePortable(); public string ViewerName() { if ((Viewers?.Count ?? 0) != 1) { return fallback(); } return Viewers[0]?.Name ?? fallback(); string fallback() { return Anonymous ? "a ghost" : "the crowd"; } } public string ViewerNamePortable() { if ((Viewers?.Count ?? 0) != 1) { return fallback(); } return Viewers[0]?.PortableName ?? fallback(); string fallback() { return Anonymous ? "a ghost" : "the crowd"; } } public EffectRequest(string effectID) : base(BlockType.EffectRequest) { EffectID = effectID; } public EffectRequest(Effect effect) : this(effect.ID) { Effect = effect; } private EffectRequest(Effect effect, Guid followUpTo, uint followUpIndex) : this(effect) { FollowUpTo = followUpTo; FollowUpIndex = followUpIndex; } public EffectRequest GetFollowUp(uint index) { EffectRequest effectRequest = new EffectRequest(Effect, ID, index); effectRequest.ID = CrowdControlBlock.IDSource(); effectRequest.Admin = Admin; effectRequest.Anonymous = Anonymous; effectRequest.Cost = Cost; effectRequest.Duration = Duration; effectRequest.ErrorOverride = ErrorOverride; effectRequest.Free = Free; effectRequest.IgnoreMaxQueueLength = IgnoreMaxQueueLength; effectRequest.IgnoreStateChecks = IgnoreStateChecks; effectRequest.LocalTest = LocalTest; effectRequest.Origin = Origin?.Clone(); effectRequest.Parameters = Parameters?.Clone(); effectRequest.Priority = Priority; effectRequest.Quantity = Quantity; effectRequest.ResponseTimeout = ResponseTimeout; effectRequest.RetryInterval = RetryInterval; effectRequest.RetryMaxAttempts = RetryMaxAttempts; effectRequest.RetryMaxTime = RetryMaxTime; effectRequest.SourceDetails = SourceDetails?.Clone(); effectRequest.Target = Target?.Clone(); effectRequest.Viewers = Viewers?.Select((UserRecord v) => v.Clone()).ToList(); return effectRequest; } } [Serializable] public class EffectResponse : ResponseBlock { private class MetadataConverter : JsonConverter<Dictionary<string, DataResponse>?> { public override void WriteJson(JsonWriter writer, Dictionary<string, DataResponse>? value, JsonSerializer serializer) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (value == null) { serializer.Serialize(writer, (object)null); return; } JObject val = new JObject(); JToken jToken = default(JToken); foreach (KeyValuePair<string, DataResponse> item in value) { JObject val2 = JObject.FromObject((object)item.Value); if (val2.TryGetValue("message", ref jToken) && jToken.TryGetValue<string>(out string value2) && string.IsNullOrWhiteSpace(value2)) { val2.Remove("message"); } val2.Remove("id"); val2.Remove("key"); val2.Remove("stamp"); val2.Remove("type"); val[item.Key] = (JToken)(object)val2; } serializer.Serialize(writer, (object)val); } public override Dictionary<string, DataResponse>? ReadJson(JsonReader reader, Type objectType, Dictionary<string, DataResponse>? existingValue, bool hasExistingValue, JsonSerializer serializer) { throw new NotImplementedException(); } } [JsonProperty(/*Could not decode attribute arguments.*/)] public SITimeSpan TimeRemaining = SITimeSpan.Zero; [JsonProperty(PropertyName = "metadata")] [JsonConverter(typeof(MetadataConverter))] public Dictionary<string, DataResponse>? Metadata; [JsonProperty(PropertyName = "modified")] public string[]? Modified; [JsonIgnore] public bool Success => (Status & EffectStatus.Success) == EffectStatus.Success; [JsonProperty(PropertyName = "status")] public EffectStatus Status { get; } [JsonIgnore] public DateTimeOffset DueTime => DateTimeOffset.UtcNow + TimeRemaining; public override string ToString() { return string.Format("{0} - {1}", Request, Status.ToString() + (string.IsNullOrWhiteSpace(Message) ? string.Empty : (" - " + Message)) + (((Status & EffectStatus.DelayUnknown) == EffectStatus.DelayUnknown) ? (" - " + DueTime.ToUniversalTime().ToString("O")) : string.Empty)); } public EffectResponse(Guid request, EffectStatus status, string? message, Enum? messageID, ErrorSource? errorSource, bool? abnormal = null) : base(BlockType.EffectResponse) { Request = request; Status = status; Message = message ?? string.Empty; MessageID = messageID?.ToCamelCase(); ErrorSource = errorSource.GetValueOrDefault(); Abnormal = abnormal; } public EffectResponse(Guid request, EffectStatus status, SITimeSpan? timeRemaining, string? message, Enum? messageID, ErrorSource? errorSource, bool? abnormal = null) : this(request, status, message, messageID, errorSource, abnormal) { TimeRemaining = timeRemaining ?? SITimeSpan.Zero; } [JsonConstructor] protected EffectResponse(Guid request, EffectStatus status, double timeRemaining, string? message, Enum? messageID, ErrorSource? errorSource, bool? abnormal = null) : this(request, status, message, messageID, errorSource, abnormal) { TimeRemaining = timeRemaining; } } public interface IEffectSourceDetails : ICloneable { internal class Converter : JsonConverter<IEffectSourceDetails?> { public static readonly Converter Instance = new Converter(); public override IEffectSourceDetails? ReadJson(JsonReader reader, Type objectType, IEffectSourceDetails? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)reader.TokenType == 11) { return null; } JObject val = JObject.Load(reader); JToken obj = val["type"]; string text = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null); if (1 == 0) { } IEffectSourceDetails result = text switch { "twitch-channel-reward" => ((JToken)val).ToObject<TwitchChannelRewardSourceDetails>(), "stream-labs-donation" => ((JToken)val).ToObject<StreamLabsDonationSourceDetails>(), "event-hype-train" => ((JToken)val).ToObject<HypeTrainSourceDetails>(), "tiktok-gift" => ((JToken)val).ToObject<TikTokGiftSourceDetails>(), "tiktok-like" => ((JToken)val).ToObject<TikTokLikeSourceDetails>(), "tiktok-follow" => ((JToken)val).ToObject<TikTokFollowSourceDetails>(), "tiktok-share" => ((JToken)val).ToObject<TikTokShareSourceDetails>(), "pulsoid-trigger" => ((JToken)val).ToObject<PulsoidTriggerSourceDetails>(), "crowd-control-test" => ((JToken)val).ToObject<CrowdControlTestSourceDetails>(), "crowd-control-chaos-mode" => ((JToken)val).ToObject<CrowdControlChaosModeSourceDetails>(), "crowd-control-retry" => ((JToken)val).ToObject<CrowdControlRetrySourceDetails>(), _ => null, }; if (1 == 0) { } return result; } public override void WriteJson(JsonWriter writer, IEffectSourceDetails? value, JsonSerializer serializer) { serializer.Serialize(writer, (object)((value == null) ? null : JObject.FromObject((object)value))); } } [JsonProperty("type")] string Type { get; } object ICloneable.Clone() { return Clone(); } new IEffectSourceDetails Clone(); } public class TwitchChannelRewardSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "twitch-channel-reward"; [JsonProperty("rewardID")] public string RewardID { get; set; } [JsonProperty("redemptionID")] public string RedemptionID { get; set; } [JsonProperty("twitchID")] public string TwitchID { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("cost")] public int Cost { get; set; } IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public TwitchChannelRewardSourceDetails Clone() { return new TwitchChannelRewardSourceDetails { RewardID = RewardID, RedemptionID = RedemptionID, TwitchID = TwitchID, Name = Name, Cost = Cost }; } } public class StreamLabsDonationSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "stream-labs-donation"; [JsonProperty("donationID")] public string DonationID { get; set; } [JsonProperty("cost")] public string Cost { get; set; } [JsonProperty("currency")] public string Currency { get; set; } [JsonProperty("name")] public string? Name { get; set; } [JsonProperty("message")] public string? Message { get; set; } IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public StreamLabsDonationSourceDetails Clone() { return new StreamLabsDonationSourceDetails { DonationID = DonationID, Cost = Cost, Currency = Currency, Name = Name, Message = Message }; } } public class HypeTrainSourceDetails : IEffectSourceDetails, ICloneable { public class Contribution { [JsonProperty("user_id")] public string UserID { get; set; } [JsonProperty("user_login")] public string UserLogin { get; set; } [JsonProperty("user_name")] public string UserName { get; set; } [JsonProperty("type")] public string Type { get; set; } [JsonProperty("total")] public int Total { get; set; } } [JsonProperty("type")] public string Type => "event-hype-train"; [JsonProperty("total")] public int Total { get; set; } [JsonProperty("progress")] public int Progress { get; set; } [JsonProperty("goal")] public int Goal { get; set; } [JsonProperty("top_contributions")] public List<Contribution> TopContributions { get; set; } [JsonProperty("last_contribution")] public Contribution LastContribution { get; set; } [JsonProperty("level")] public int Level { get; set; } IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public HypeTrainSourceDetails Clone() { return new HypeTrainSourceDetails { Total = Total, Progress = Progress, Goal = Goal, TopContributions = TopContributions.Select((Contribution c) => new Contribution { UserID = c.UserID, UserLogin = c.UserLogin, UserName = c.UserName, Type = c.Type, Total = c.Total }).ToList(), LastContribution = new Contribution { UserID = LastContribution.UserID, UserLogin = LastContribution.UserLogin, UserName = LastContribution.UserName, Type = LastContribution.Type, Total = LastContribution.Total }, Level = Level }; } } public abstract class TikTokSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public abstract string Type { get; } [JsonProperty("cost")] public int Cost { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("userID")] public string UserID { get; set; } IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public abstract IEffectSourceDetails Clone(); } public class TikTokGiftSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-gift"; [JsonProperty("giftID")] public int GiftID { get; set; } [JsonProperty("giftName")] public string GiftName { get; set; } [JsonProperty("transactionID")] public string? TransactionID { get; set; } public override IEffectSourceDetails Clone() { return new TikTokGiftSourceDetails { Cost = base.Cost, Name = base.Name, UserID = base.UserID, GiftID = GiftID, GiftName = GiftName, TransactionID = TransactionID }; } } public class TikTokLikeSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-like"; public override IEffectSourceDetails Clone() { return new TikTokLikeSourceDetails { Cost = base.Cost, Name = base.Name, UserID = base.UserID }; } } public class TikTokFollowSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-follow"; public override IEffectSourceDetails Clone() { return new TikTokFollowSourceDetails { Cost = base.Cost, Name = base.Name, UserID = base.UserID }; } } public class TikTokShareSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-share"; public override IEffectSourceDetails Clone() { return new TikTokShareSourceDetails { Cost = base.Cost, Name = base.Name, UserID = base.UserID }; } } public class PulsoidTriggerSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "pulsoid-trigger"; [JsonProperty("heartRate")] public int HeartRate { get; set; } [JsonProperty("uuid")] public Guid Uuid { get; set; } [JsonProperty("triggerType")] public string TriggerType { get; set; } [JsonProperty("targetHeartRate")] public int TargetHeartRate { get; set; } [JsonProperty("holdTime")] public int HoldTime { get; set; } [JsonProperty("cooldown")] public int Cooldown { get; set; } IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public PulsoidTriggerSourceDetails Clone() { return new PulsoidTriggerSourceDetails { HeartRate = HeartRate, Uuid = Uuid, TriggerType = TriggerType, TargetHeartRate = TargetHeartRate, HoldTime = HoldTime, Cooldown = Cooldown }; } } public class CrowdControlTestSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "crowd-control-test"; IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public CrowdControlTestSourceDetails Clone() { return new CrowdControlTestSourceDetails(); } } public class CrowdControlChaosModeSourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "crowd-control-chaos-mode"; IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public CrowdControlChaosModeSourceDetails Clone() { return new CrowdControlChaosModeSourceDetails(); } } public class CrowdControlRetrySourceDetails : IEffectSourceDetails, ICloneable { [JsonProperty("type")] public string Type => "crowd-control-retry"; IEffectSourceDetails IEffectSourceDetails.Clone() { return Clone(); } public CrowdControlRetrySourceDetails Clone() { return new CrowdControlRetrySourceDetails(); } } [JsonConverter(typeof(CamelCaseStringEnumConverter<EffectStatus>))] public enum EffectStatus : byte { Unknown = 0, Created = 1, [Description("Pending Request")] PendingRequest = 2, [Description("Request Sent")] RequestSent = 3, [Description("Request Locally Scheduled")] LocalScheduled = 4, [Description("Request Remotely Scheduled")] RemoteScheduled = 5, Success = 16, [Description("Delayed Success")] SuccessDelayed = 17, [Description("Final Success")] SuccessFinal = 18, [Description("Bid War Success")] SuccessBidWar = 20, [Description("Temporary Failure")] FailTemporary = 32, [Description("Permanent Failure")] FailPermanent = 33, [Description("Bid War Failure")] FailBidWar = 36, [Description("Unknown Delay")] DelayUnknown = 48, [Description("Exact Delay")] DelayExact = 49, [Description("Estimated Delay")] DelayEstimated = 50, [Description("Extended Delay")] DelayExtended = 51, [Description("Bid War Delay")] DelayBidWar = 52, [Description("Timed Effect Begin")] TimedBegin = 64, [Description("Timed Effect End")] TimedEnd = 65, [Description("Timed Effect Pause")] TimedPause = 66, [Description("Timed Effect Resume")] TimedResume = 67, [Description("Timed Effect Unclean Abort")] TimedAborted = 78, [Description("Timed Effect Canceled")] TimedCanceled = 79, [Description("Connector Able to Perform")] ConnectorAble = 80, [Description("Connetor Unable to Perform")] ConnectorUnable = 81, [Description("Connetor Able to Perform Using Unsafe Methodology")] ConnectorRisky = 82, [Description("Available for Order")] MenuAvailable = 96, [Description("Unavailable for Order")] MenuUnavailable = 97, [Description("Visible on Menu")] MenuVisible = 98, [Description("Hidden on Menu")] MenuHidden = 99, [Description("Bid War Reset")] BidWarReset = 100, [Description("Exception Report")] ExceptionReport = 240 } public static class EffectStatusEx { public static bool IsSetup(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == 0; } public static bool IsSuccess(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.Success; } public static bool IsFailure(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.FailTemporary; } public static bool IsDelay(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.DelayUnknown; } public static bool IsTimedUpdate(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.TimedBegin; } public static bool IsConnectorStatus(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.ConnectorAble; } public static bool IsEffectStatic(this EffectStatus value) { return (value & EffectStatus.ExceptionReport) == EffectStatus.MenuAvailable; } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] [Flags] public enum EffectType : uint { Game = 0u, Video = 1u, Audio = 2u, Image = 4u, Live = 8u, StreamerBot = 0x10u, Unknown = 0x80000000u } [JsonConverter(typeof(CamelCaseStringEnumConverter<ErrorSource>))] public enum ErrorSource { Unknown, Connector, [Description("Pack Core")] PackCore, [Description("Game Pack")] GamePack, Game, RPC, Session, User, External } public static class EnumEx { private static readonly ConcurrentDictionary<Type, MethodInfo?> m_getAttributeMethods = new ConcurrentDictionary<Type, MethodInfo>(); public static bool TryGetAttribute<T>(this Enum enumValue, out T? value) { MemberInfo[] member = enumValue.GetType().GetMember(enumValue.ToString()); if (member.Length == 0) { value = default(T); return false; } object[] customAttributes = member[0].GetCustomAttributes(typeof(T), inherit: false); if (customAttributes.Length == 0) { value = default(T); return false; } value = (T)customAttributes[0]; return true; } public static bool TryGetDescription(this Enum enumValue, out string? value) { if (!enumValue.TryGetAttribute<DescriptionAttribute>(out DescriptionAttribute value2)) { value = null; return false; } value = value2?.Description; return value != null; } public static string GetFriendlyName(this Enum enumValue) { if (enumValue.TryGetDescription(out string value)) { return value; } return Enum.GetName(enumValue.GetType(), enumValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IReadOnlyList<string> GetNames<T>() where T : unmanaged, Enum { return EnumEx<T>.Names; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IReadOnlyList<T> GetValues<T>() where T : unmanaged, Enum { return EnumEx<T>.Values; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string? GetName<T>(T value) where T : unmanaged, Enum { return EnumEx<T>.GetName(value); } public static string? GetNameSlow<T>(this T value, bool includeObsolete = true) where T : unmanaged, Enum { foreach (T value2 in EnumEx<T>.Values) { if ((includeObsolete || !value.IsObsolete()) && object.Equals(value2, value)) { return EnumEx<T>.GetName(value2); } } return null; } public static IEnumerable<T> GetFlags<T>(this T value, bool includeZero = false) where T : unmanaged, Enum { foreach (T val in Enum.GetValues(typeof(T))) { ulong lv = Convert.ToUInt64(val); if ((includeZero || lv != 0) && (lv & Convert.ToUInt64(value)) == lv) { yield return val; } } } public static bool IsObsolete<T>(string name) where T : unmanaged, Enum { return typeof(T).GetCustomAttribute<ObsoleteAttribute>() != null; } public static bool IsObsolete<T>(this T value) where T : unmanaged, Enum { string name = EnumEx<T>.GetName(value) ?? throw new ArgumentException("Unknown enumeration value.", "value"); return IsObsolete<T>(name); } public static string ToCamelCase(this Enum value) { return value.ToString("G").ToCamelCase(); } public static TAttribute? GetAttribute<TEnum, TAttribute>(this TEnum enumVal) where TEnum : unmanaged, Enum where TAttribute : Attribute { return EnumEx<TEnum>.GetAttribute<TAttribute>(enumVal); } } public static class EnumEx<T> where T : unmanaged, Enum { private static class AttributeCache<TAttribute> where TAttribute : Attribute { private static readonly ConcurrentDictionary<T, TAttribute?> _cache = new ConcurrentDictionary<T, TAttribute>(); public static TAttribute? GetAttribute(T value) { if (_cache.TryGetValue(value, out TAttribute value2)) { return value2; } MemberInfo[] memberInfo = EnumEx<T>.GetMemberInfo(value); if (memberInfo == null) { return _cache[value] = null; } for (int i = 0; i < memberInfo.Length; i = checked(i + 1)) { object[] customAttributes = memberInfo[i].GetCustomAttributes(typeof(TAttribute), inherit: false); if (customAttributes.Length != 0) { return _cache[value] = (TAttribute)customAttributes[0]; } } return _cache[value] = null; } } private static readonly ConcurrentDictionary<T, MemberInfo[]> _enumMemberInfoCache = new ConcurrentDictionary<T, MemberInfo[]>(); private static readonly ConcurrentDictionary<T, string?> _enumStringCache = new ConcurrentDictionary<T, string>(); private static readonly ConcurrentDictionary<string, T> _stringEnumCache = new ConcurrentDictionary<string, T>(); public static IReadOnlyList<string> Names { get; } = Enum.GetNames(typeof(T)); public static IReadOnlyList<T> Values { get; } = (T[])Enum.GetValues(typeof(T)); public static IReadOnlyList<T> DistinctValues { get; } = Values.Distinct().ToList(); public static int Count { get; } = Values.Count; public static T MinValue { get; } = Values.Min(); public static T MaxValue { get; } = Values.Max(); public static string? GetName(T value) { return _enumStringCache.GetOrAdd(value, (T e) => Enum.GetName(typeof(T), e)); } public static T Parse(string value) { return _stringEnumCache.GetOrAdd(value, (string v) => (T)Enum.Parse(typeof(T), v)); } public static bool TryParse(string? value, out T result) { return TryParse(value, ignoreCase: true, out result); } public static bool TryParse(string? value, bool ignoreCase, out T result) { return TryParse(value, ignoreCase, tryDescription: false, out result); } public static bool TryParse(string? value, bool ignoreCase, bool tryDescription, out T result) { if (!string.IsNullOrWhiteSpace(value)) { if (_stringEnumCache.TryGetValue(value, out result)) { return true; } if (Enum.TryParse<T>(value, ignoreCase, out result)) { _stringEnumCache[value] = result; return true; } StringComparison comparisonType = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); if (tryDescription) { foreach (T value2 in Values) { if (!string.Equals(value, value2.ToString(), comparisonType)) { continue; } _stringEnumCache[value] = result; return true; } } } result = default(T); return false; } public static bool TryConvert(long value, out T result) { return TryConvert((ulong)value, out result); } public static bool TryConvert(ulong value, out T result) { for (int i = 0; i < Values.Count; i = checked(i + 1)) { T val = Values[i]; if (value == Convert.ToUInt64(val)) { result = val; return true; } } result = default(T); return false; } public static MemberInfo[]? GetMemberInfo(T value) { string name = GetName(value); if (string.IsNullOrWhiteSpace(name)) { return null; } return _enumMemberInfoCache.GetOrAdd(value, (T v) => typeof(T).GetMember(name)); } public static TAttribute? GetAttribute<TAttribute>(T value) where TAttribute : Attribute { return AttributeCache<TAttribute>.GetAttribute(value); } } public static class EventHandlerEx { public static void InvokeSafe(this EventHandler? eventHandler, object sender, EventArgs e) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(sender, e); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } public static void InvokeSafe<T>(this EventHandler<T>? eventHandler, object sender, T e) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(sender, e); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } public static void InvokeSafe(this Action? eventHandler) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } public static void InvokeSafe<T1>(this Action<T1>? eventHandler, T1 p1) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(p1); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } public static void InvokeSafe<T1, T2>(this Action<T1, T2>? eventHandler, T1 p1, T2 p2) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(p1, p2); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } public static void InvokeSafe<T1, T2, T3>(this Action<T1, T2, T3>? eventHandler, T1 p1, T2 p2, T3 p3) { if (eventHandler == null) { return; } try { Delegate[] invocationList = eventHandler.GetInvocationList(); foreach (Delegate obj in invocationList) { try { obj.DynamicInvoke(p1, p2, p3); } catch (Exception ex) { Log.Error(ex); } } } catch (Exception ex2) { Log.Error(ex2); } } } public static class IEnumerableEx { private static readonly Random _rng = new Random(); public static IEnumerable<IEnumerable<T>> ConcatMany<T>(this IEnumerable<IEnumerable<T>> collection, IEnumerable<IEnumerable<T>> toJoin) { foreach (IEnumerable<T> c1 in collection) { if (!toJoin.Any()) { yield return c1; continue; } foreach (IEnumerable<T> c2 in toJoin) { yield return c1.Concat(c2); } } } public static IEnumerable<IEnumerable<T>> ConcatMany<T>(this IEnumerable<T> collection, IEnumerable<IEnumerable<T>> toJoin) { if (!toJoin.Any()) { yield return collection; yield break; } foreach (IEnumerable<T> c2 in toJoin) { yield return collection.Concat(c2); } } public static IEnumerable<IEnumerable<T>> ConcatMany<T>(this IEnumerable<IEnumerable<T>> collection, IEnumerable<T> toJoin) { return collection.Select((IEnumerable<T> c1) => c1.Concat(toJoin)); } public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T>? collection) { return collection ?? Array.Empty<T>(); } public static IEnumerable<IEnumerable<T>> WhereAny<T>(this IEnumerable<IEnumerable<T>> collection, Func<T, bool> predicate) { return collection.Where((IEnumerable<T> x) => x.Any(predicate)); } public static IEnumerable<IEnumerable<T>> WhereAll<T>(this IEnumerable<IEnumerable<T>> collection, Func<T, bool> predicate) { return collection.Where((IEnumerable<T> x) => x.All(predicate)); } public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> source, TSource value) { return source.Where((TSource v) => !object.Equals(v, value)); } public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> set) { return set.All(source.Contains<TSource>); } public static IEnumerable<TSource> WhereNot<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { return source.Where((TSource value) => !predicate(value)); } public static bool ContainsSequence<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> sequence, IEqualityComparer<TSource>? comparer = null) { if (source == null) { throw new ArgumentNullException("source"); } int num = source.Count(); int num2 = sequence.Count(); checked { for (int i = 0; i <= num - num2; i++) { if (source.Skip(i).Take(num2).SequenceEqual(sequence, comparer)) { return true; } } return false; } } public static T TakeRandom<T>(this IEnumerable<T> source) { int maxValue = source.Count(); maxValue = _rng.Next(0, maxValue); int num = 0; foreach (T item in source) { if (num == maxValue) { return item; } num = checked(num + 1); } throw new ArgumentException("The collection was empty.", "source"); } public static IEnumerable<IEnumerable<T>> CrossProduct<T>(this IEnumerable<IEnumerable<T>> source) { return source.Aggregate(new IEnumerable<T>[1] { Enumerable.Empty<T>() }, (IEnumerable<IEnumerable<T>> acc, IEnumerable<T> src) => src.SelectMany((T x) => acc.Select((IEnumerable<T> a) => a.Concat(new T[1] { x })))); } public static K CrossProduct<T, K>(this IEnumerable<IEnumerable<T>> source, Func<IEnumerable<IEnumerable<T>>, K> joiner) { return joiner(source.CrossProduct()); } public static int IndexOfKey<K, V>(this IEnumerable<KeyValuePair<K, V>> enumerable, K key) { int num = 0; foreach (KeyValuePair<K, V> item in enumerable) { if (item.Key.Equals(key)) { return num; } num = checked(num + 1); } return -1; } public static Dictionary<K, V> ToDictionary<K, V>(this IEnumerable<KeyValuePair<K, V>> values) where K : notnull { Dictionary<K, V> dictionary = new Dictionary<K, V>(); foreach (KeyValuePair<K, V> value in values) { dictionary.Add(value.Key, value.Value); } return dictionary; } public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } HashSet<TKey> knownKeys = new HashSet<TKey>(comparer); foreach (TSource element in source) { if (knownKeys.Add(keySelector(element))) { yield return element; } } } public static byte GetChecksum(this Span<byte> array) { byte b = 0; for (int i = 0; i < array.Length; i = checked(i + 1)) { b += array[i]; } return b; } public static bool Overlaps<T>(this IEnumerable<T> arr, IEnumerable<T> other) { return arr.Intersect(other).Any(); } public static bool Overlaps<T>(this IEnumerable<T> arr, IEnumerable<T> other, IEqualityComparer<T> comparer) { return arr.Intersect(other, comparer).Any(); } public static int IndexOf<T>(this IEnumerable<T> sequence, Predicate<T> predicate) { int num = 0; foreach (T item in sequence) { if (predicate(item)) { return num; } num = checked(num + 1); } return -1; } } public static class IListEx { private static readonly Random RNG = new Random(); public static void CompactNotNullElements<TValue>(this IList<TValue?> arr) { checked { int num = arr.Count - 1; for (int i = 0; i < num; i++) { int index = i; TValue val = arr[index]; if (val == null) { TValue val2 = (arr[index] = arr[i + 1]); } } } } public static void Add<K>(this IList<(K, Action)> list, [DisallowNull] K value, Delegate action) { list.Add((value, (Action)action)); } public static void Shuffle<TValue>(this IList<TValue> list) { int num = list.Count; checked { while (num > 1) { num--; int index = RNG.Next(num + 1); TValue value = list[index]; list[index] = list[num]; list[num] = value; } } } public static TValue TakeRandom<TValue>(this IList<TValue> list) { if (list.Count <= 0) { throw new ArgumentException("The collection was empty.", "list"); } return list[RNG.Next(list.Count)]; } public static TValue[] WithoutNullElements<TValue>(this IList<TValue?> arr) { return arr.Where<TValue>((TValue e) => e != null).ToArray(); } public static string ToHexString(this IList<byte> bytes) { char[] array = new char[checked(bytes.Count * 2)]; for (int i = 0; i < bytes.Count; i = checked(i + 1)) { int num = bytes[i] >> 4; array[checked(i * 2)] = (char)checked((ushort)(55 + num + ((num - 10 >> 31) & -7))); num = bytes[i] & 0xF; array[checked(i * 2 + 1)] = (char)checked((ushort)(55 + num + ((num - 10 >> 31) & -7))); } return new string(array); } public static void Reverse(this IList<byte> bytes) { for (int i = 0; i < bytes.Count / 2; i = checked(i + 1)) { int index = checked(bytes.Count - 1 - i); byte value = bytes[i]; bytes[i] = bytes[index]; bytes[index] = value; } } public static void UnionWith<TValue>(this IList<TValue> list, IEnumerable<TValue> other) { if (list.Count < 16) { foreach (TValue item in other) { if (!list.Contains(item)) { list.Add(item); } } return; } HashSet<TValue> hashSet = null; int num = 0; foreach (TValue item2 in other) { if (hashSet != null) { if (hashSet.Add(item2)) { list.Add(item2); } continue; } if (!list.Contains(item2)) { list.Add(item2); continue; } num = checked(num + 1); if (num >= 16) { hashSet = new HashSet<TValue>(list); } } } } public static class JObjectEx { [DebuggerStepThrough] public static JObject RemovePropertiesExcept(this JObject jObject, params string[] propertiesToKeep) { foreach (string item in from p in jObject.Properties().ToArray() where !propertiesToKeep.Contains(p.Name) select p.Name) { jObject.Remove(item); } return jObject; } } public static class JTokenEx { [DebuggerStepThrough] public static bool IsNull(this JToken? jToken) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (jToken == null) { return true; } if ((int)jToken.Type == 10) { return true; } return false; } [DebuggerStepThrough] public static JObject? ToJObject(this JToken? jToken) { if (jToken.IsNull()) { return null; } return JObject.FromObject((object)jToken); } public static TValue? GetValueSafe<TValue>(this JToken? token) { if (token == null) { return default(TValue); } token.TryGetValue<TValue>(out TValue value); return value; } public static bool TryGetValueSafe<TValue>(this JToken? token, out TValue? value) { if (token == null) { value = default(TValue); return false; } return token.TryGetValue<TValue>(out value); } [DebuggerStepThrough] public static bool TryGetValue<T>(this JToken jToken, out T? value) { try { bool flag = TypeEx.IsAssignableTo(typeof(T), typeof(IEnumerable)); bool flag2 = jToken is JArray; if (flag && flag2) { value = jToken.ToObject<T>(); return true; } if (!flag && !flag2) { value = Extensions.Value<T>((IEnumerable<JToken>)jToken); return true; } } catch { } value = default(T); return false; } [DebuggerStepThrough] public static bool TryGetValue<T>(this JToken jToken, object key, out T? value) { try { bool flag = TypeEx.IsAssignableTo(typeof(T), typeof(IEnumerable)); bool flag2 = jToken is JArray; if (flag && flag2) { value = jToken[key].ToObject<T>(); return true; } if (!flag && !flag2) { value = jToken.Value<T>(key); return true; } } catch { } value = default(T); return false; } } public static class ObjectEx { public class FieldNotFoundException : Exception { public Type Type { get; } public string FieldName { get; } public FieldNotFoundException(Type type, string fieldName) : base("Cannot find field " + fieldName + " in type " + type.FullName + ".") { Type = type; FieldName = fieldName; } } public class PropertyNotFoundException : Exception { public Type Type { get; } public string PropertyName { get; } public PropertyNotFoundException(Type type, string propertyName) : base("Cannot find property " + propertyName + " in type " + type.FullName + ".") { Type = type; PropertyName = propertyName; } } public class MethodNotFoundException : Exception { public Type Type { get; } public string MethodName { get; } public MethodNotFoundException(Type type, string methodName) : base("Cannot find method " + methodName + " in type " + type.FullName + ".") { Type = type; MethodName = methodName; } } private const BindingFlags BINDING_FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; private static readonly ConcurrentDictionary<Type, ConcurrentDictionary<string, FieldInfo?>> _classFields = new ConcurrentDictionary<Type, ConcurrentDictionary<string, FieldInfo>>(); private static readonly ConcurrentDictionary<Type, ConcurrentDictionary<string, PropertyInfo?>> _classProperties = new ConcurrentDictionary<Type, ConcurrentDictionary<string, PropertyInfo>>(); public static int GetUnmanagedSize(this object? value) { if (value == null) { return 0; } Type type = value.GetType(); Type underlyingType = Nullable.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } if (type.IsEnum) { type = Enum.GetUnderlyingType(type); } if (type.IsArray) { type = type.GetElementType(); return checked(Marshal.SizeOf(type) * ((Array)value).Length); } return Marshal.SizeOf(type); } [return: NotNullIfNotNull("value")] public static object? CastTo(this object? value, Type toType) { Type fromType = value?.GetType(); if (fromType == null) { return null; } if (TypeEx.IsAssignableTo(fromType, toType)) { return value; } IEnumerable<MethodInfo> source = from m in fromType.GetMethods(BindingFlags.Static | BindingFlags.Public).Concat(toType.GetMethods(BindingFlags.Static | BindingFlags.Public)).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = ((name == "op_Implicit" || name == "op_Explicit") ? true : false); return flag && m.ReturnType == toType; }) where m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == fromType select m; MethodInfo methodInfo = source.FirstOrDefault(); if (methodInfo == null) { throw new InvalidCastException(); } return methodInfo.Invoke(null, new object[1] { value }); } [return: NotNullIfNotNull("value")] public static TTo? CastTo<TTo>(this object? value) { if (value == null) { return default(TTo); } if (value is TTo result) { return result; } Type fromType = value?.GetType(); if (fromType == null) { return default(TTo); } Type toType = typeof(TTo); IEnumerable<MethodInfo> source = from m in fromType.GetMethods(BindingFlags.Static | BindingFlags.Public).Concat(toType.GetMethods(BindingFlags.Static | BindingFlags.Public)).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = ((name == "op_Implicit" || name == "op_Explicit") ? true : false); return flag && m.ReturnType == toType; }) where m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == fromType select m; MethodInfo methodInfo = source.FirstOrDefault(); if (methodInfo == null) { throw new InvalidCastException(); } return (TTo)methodInfo.Invoke(null, new object[1] { value }); } [return: NotNullIfNotNull("value")] public static TTo CastTo<TTo, TFrom>(this TFrom value) where TFrom : struct { if ((object)value is TTo result) { return result; } Type fromType = value.GetType(); Type toType = typeof(TTo); IEnumerable<MethodInfo> source = from m in fromType.GetMethods(BindingFlags.Static | BindingFlags.Public).Concat(toType.GetMethods(BindingFlags.Static | BindingFlags.Public)).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = ((name == "op_Implicit" || name == "op_Explicit") ? true : false); return flag && m.ReturnType == toType; }) where m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == fromType select m; MethodInfo methodInfo = source.FirstOrDefault(); if (methodInfo == null) { throw new InvalidCastException(); } return (TTo)methodInfo.Invoke(null, new object[1] { value }); } public static T FieldCopy<T>(this ref T parent) where T : struct { T child = (T)RuntimeHelpers.GetUninitializedObject(typeof(T)); FieldCopy(ref parent, ref child); return child; } public static T FieldCopy<T>(this T parent) where T : class { T val = (T)RuntimeHelpers.GetUninitializedObject(typeof(T)); parent.FieldCopy(val); return val; } public static TChild FieldCopy<TParent, TChild>(this TParent parent) where TParent : class where TChild : TParent, new() { TChild val = new TChild(); parent.FieldCopy<TParent, TChild>(val); return val; } public static void FieldCopy<TParent, TChild>(this ref TParent parent, ref TChild child) where TParent : struct where TChild : struct { PropertyInfo[] properties = parent.GetType().GetProperties(); PropertyInfo[] properties2 = child.GetType().GetProperties(); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { PropertyInfo[] array2 = properties2; foreach (PropertyInfo propertyInfo2 in array2) { if (propertyInfo.Name == propertyInfo2.Name && propertyInfo.PropertyType == propertyInfo2.PropertyType) { propertyInfo2.SetValue(child, propertyInfo.GetValue(parent)); break; } } } } public static void FieldCopy<TParent, TChild>(this TParent parent, TChild child) where TParent : class where TChild : TParent { PropertyInfo[] properties = parent.GetType().GetProperties(); PropertyInfo[] properties2 = child.GetType().GetProperties(); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { PropertyInfo[] array2 = properties2; foreach (PropertyInfo propertyInfo2 in array2) { if (propertyInfo.Name == propertyInfo2.Name && propertyInfo.PropertyType == propertyInfo2.PropertyType) { propertyInfo2.SetValue(child, propertyInfo.GetValue(parent)); break; } } } } public static bool IsObsolete<T>(string name) where T : Enum { ObsoleteAttribute[] array = (ObsoleteAttribute[])typeof(T).GetField(name)?.GetCustomAttributes(typeof(ObsoleteAttribute), inherit: false); return array != null && array.Length > 0; } public static FieldInfo? GetField(this object obj, string fieldName) { if (obj == null) { throw new NullReferenceException(); } Type objType = obj.GetType(); ConcurrentDictionary<string, FieldInfo> orAdd = _classFields.GetOrAdd(objType, (Type _) => new ConcurrentDictionary<string, FieldInfo>()); return orAdd.GetOrAdd(fieldName, delegate { FieldInfo fieldInfo = null; while (objType != null && fieldInfo == null) { fieldInfo = objType.GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); objType = objType.BaseType; } return fieldInfo; }); } public static object GetFieldValue(this object obj, string fieldName) { FieldInfo field = obj.GetField(fieldName); if (field == null) { throw new FieldNotFoundException(obj.GetType(), fieldName); } return field.GetValue(obj); } public static void SetFieldValue(this object obj, string fieldName, object value) { FieldInfo field = obj.GetField(fieldName); if (field == null) { throw new FieldNotFoundException(obj.GetType(), fieldName); } field.SetValue(obj, value); } public static PropertyInfo? GetProperty(this object obj, string propertyName) { if (obj == null) { throw new NullReferenceException(); } Type objType = obj.GetType(); ConcurrentDictionary<string, PropertyInfo> orAdd = _classProperties.GetOrAdd(objType, (Type _) => new ConcurrentDictionary<string, PropertyInfo>()); return orAdd.GetOrAdd(propertyName, (string _) => objType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)); } public static object GetPropertyValue(this object obj, string propertyName) { PropertyInfo property = obj.GetProperty(propertyName); if (property == null) { throw new PropertyNotFoundException(obj.GetType(), propertyName); } return property.GetValue(obj); } public static void SetPropertyValue(this object obj, string propertyName, object value) { PropertyInfo property = obj.GetProperty(propertyName); if (property == null) { throw new PropertyNotFoundException(obj.GetType(), propertyName); } try { property.SetValue(obj, value); } catch (ArgumentException) { obj.SetFieldValue("<" + propertyName + ">k__BackingField", value); } } public static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : class { return (value != null) ? selector(value) : null; } public static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : struct { return (value != null) ? selector(value) : ((T2?)null); } public static IEnumerable<Type?> GetTypes(this IEnumerable<object?> objects) { return objects.Select((object obj) => obj?.GetType()); } public static Type?[] GetTypes(this IList<object?> objects) { Type[] array = new Type[objects.Count]; for (int i = 0; i < objects.Count; i = checked(i + 1)) { array[i] = objects[i]?.GetType(); } return array; } } public static class StringEx { public unsafe static string Repeat(this string source, int repetitions) { int length = source.Length; int num; char* ptr; checked { num = length * repetitions + 1; ptr = stackalloc char[num]; for (int i = 0; i < repetitions; i++) { for (int j = 0; j < length; j++) { unchecked { *(char*)((byte*)ptr + checked(unchecked((nint)checked(j + i * length)) * (nint)2)) = source[j]; } } } } *(short*)((byte*)ptr + checked(unchecked((nint)checked(num - 1)) * (nint)2)) = 0; return new string(ptr); } public static string Until(this string text, string stopAt) { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } int num = text.IndexOf(stopAt, StringComparison.Ordinal); return (num > 0) ? text.Substring(0, num) : text; } public static string Until(this string text, char stopAt) { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } int num = text.IndexOf(stopAt.ToString(), StringComparison.Ordinal); return (num > 0) ? text.Substring(0, num) : text; } public static bool Equals(StringComparison comparisonType, params string[] values) { int num = values.Length; if (num == 0) { throw new ArgumentException("At least one element must be specified.", "values"); } int length = values[0].Length; string a = values[0]; checked { for (int i = 1; i < num; i++) { if (values[i].Length != length) { return false; } } for (int i = 1; i < num; i++) { if (!string.Equals(a, values[i], comparisonType)) { return false; } } return true; } } public unsafe static string[] Chop(this string value, int chopLength) { int length = value.Length; char* ptr = stackalloc char[chopLength]; string[] array = new string[length]; for (int i = 0; i < length; i = checked(i + chopLength)) { int j; for (j = 0; j < chopLength; j = checked(j + 1)) { int num = checked(i + j); if (num >= length) { break; } *(char*)((byte*)ptr + checked(unchecked((nint)j) * (nint)2)) = value[num]; } array[i / chopLength] = new string(ptr, 0, j); } return array; } public static string ToCamelCase(this string input) { bool flag = false; string text = ""; checked { for (int i = 0; i < input.Length; i++) { if (char.IsUpper(input[i])) { if (flag) { text += input.Substring(i); break; } text += char.ToLower(input[i]); } else { flag = true; text = ((i <= 1 || !char.IsUpper(input[i - 1]) || !char.IsUpper(input[i - 2])) ? (text + input[i]) : (text.Substring(0, text.Length - 1) + char.ToUpper(input[i - 1]) + input[i])); } } return text; } } public static bool IsNumeric(this string value) { long result; return long.TryParse(value, out result) && result >= 0; } public static string Truncate(this string value, int maxLength) { if (string.IsNullOrEmpty(value)) { return value; } return (value.Length <= maxLength) ? value : value.Substring(0, maxLength); } public static string? CoalesceEmpty(this string? first, string? second) { return string.IsNullOrWhiteSpace(first) ? second : first; } public static string Collapse(ref string? first, ref string? second) { if (first == null) { first = second ?? (second = string.Empty); } else if (second == null) { second = first; } return first; } public static string Replace(this string source, char[] separators, string newVal) { return string.Join(newVal, source.Split(separators, StringSplitOptions.RemoveEmptyEntries)); } public static bool IsAlphaNumeric(this string str, bool allowSpaces = false) { Regex regex = new Regex(allowSpaces ? "[^a-zA-Z0-9\\s]" : "[^a-zA-Z0-9]"); return regex.IsMatch(str); } public static string MakeAlphaNumeric(this string str, bool allowSpaces = false) { Regex regex = new Regex(allowSpaces ? "[^a-zA-Z0-9\\s]" : "[^a-zA-Z0-9]"); return regex.Replace(str, string.Empty); } public static string ReplaceRange(this string str, int startIndex, int length, string replacement) { return str.Remove(startIndex, length).Insert(startIndex, replacement); } public static string TrimStart(this string source, string trimString) { return (!source.StartsWith(trimString)) ? source : source.Remove(0, trimString.Length); } public static string TrimEnd(this string source, string trimString) { return (!source.EndsWith(trimString)) ? source : source.Remove(source.LastIndexOf(trimString)); } public static byte[] HexToBytes(this string hex) { if (hex.Length % 2 == 1) { throw new Exception("The input value cannot have an odd number of digits"); } byte[] array = new byte[hex.Length >> 1]; checked { for (int i = 0; i < hex.Length >> 1; i++) { array[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + GetHexVal(hex[(i << 1) + 1])); } return array; } } public static int GetHexVal(char hex) { return checked(hex - ((hex < ':') ? 48 : ((hex < 'a') ? 55 : 87))); } } public static class TaskEx { public static async void Forget(this Task task) { try { await task.ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { Exception ex2 = ex; Log.Error(ex2); } } public static async void Forget(this Task task, bool silent) { try { await task.ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { Exception ex2 = ex; if (!silent) { Log.Error(ex2); } } } public static Task<R> Then<R, TResult>(this Task<TResult> self, Func<TResult, R> f) { return self.ContinueWith((Task<TResult> t) => f(t.Result), TaskContinuationOptions.OnlyOnRanToCompletion); } public static Task Then(this Task self, Action f) { return self.ContinueWith(delegate { f(); }, TaskContinuationOptions.OnlyOnRanToCompletion); } public static Task Then(this Task self, Action<Task> f) { return self.ContinueWith(f, TaskContinuationOptions.OnlyOnRanToCompletion); } public static Task Catch(this Task self, Action<Exception> f) { return self.ContinueWith(delegate(Task t) { if (t.IsFaulted) { f(t.Exception); } }); } public static void Done(this Task self) { self.ContinueWith(delegate { }).Wait(); } } public static class TypeEx { private static readonly Dictionary<Type, Type[]> INTERFACE_CACHE = new Dictionary<Type, Type[]>(); private static readonly ConcurrentDictionary<Type, MethodInfo?> _invokeMethodCache = new ConcurrentDictionary<Type, MethodInfo>(); public static bool IsAssignableTo(this Type sourceType, Type targetType) { if (targetType == null) { throw new ArgumentNullException("targetType"); } return targetType.IsAssignableFrom(sourceType); } public static bool ImplementsInterface(this Type toCheck, Type interfaceType) { if (toCheck == null) { throw new ArgumentNullException("toCheck"); } if (interfaceType == null) { throw new ArgumentNullException("interfaceType"); } if (!INTERFACE_CACHE.TryGetValue(toCheck, out Type[] value)) { value = toCheck.GetInterfaces(); INTERFACE_CACHE[toCheck] = value; } if (interfaceType.IsOpenGeneric()) { Type[] array = value; foreach (Type toCheck2 in array) { if (toCheck2.InheritsOpenGeneric(interfaceType)) { return true; } } return false; } return value.Contains(interfaceType); } public static bool IsOpenGeneric(this Type toCheck) { return toCheck.IsGenericType && toCheck.GetGenericTypeDefinition() == toCheck; } public static bool InheritsOpenGeneric(this Type toCheck, Type generic) { while (true) { Type[] interfaces = toCheck.GetInterfaces(); Type[] array = interfaces; foreach (Type type in array) { if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) { return true; } } if (toCheck.IsGenericType && toCheck.GetGenericTypeDefinition() == generic) { return true; } Type baseType = toCheck.BaseType; if (baseType == null) { break; } toCheck = baseType; } return false; } public static bool IsAssignableToGenericType(this Type givenType, Type genericType) { Type[] interfaces = givenType.GetInterfaces(); Type[] array = interfaces; foreach (Type type in array) { if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType) { return true; } } if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) { return true; } Type baseType = givenType.BaseType; if (baseType == null) { return false; } return baseType.IsAssignableToGenericType(genericType); } public static bool IsAssignableToWithConversion(this Type fromType, Type toType) { return IsAssignableTo(fromType, toType) || fromType.HasConversionOperatorTo(toType); } public static bool HasConversionOperatorTo(this Type fromType, Type toType) { return fromType.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = ((name == "op_Implicit" || name == "op_Explicit") ? true : false); return flag && m.ReturnType == toType; }).Any((MethodInfo m) => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == fromType) || toType.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = ((name == "op_Implicit" || name == "op_Explicit") ? true : false); return flag && m.ReturnType == toType; }).Any((MethodInfo m) => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == fromType); } public static T Preconstruct<T>(Action<T> preconstructor, params object[] constructorParameters) { T val = (T)FormatterServices.GetUninitializedObject(typeof(T)); ConstructorInfo constructor = val.GetType().GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, constructorParameters); if (constructor == null) { throw new MissingMethodException("A constructor that matched the supplied parameters was not found."); } preconstructor(val); constructor.Invoke(val, constructorParameters); return val; } public static ConstructorInfo? GetConstructor(this Type type, object?[] parameters) { return type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, parameters); } public static ConstructorInfo? GetConstructor(this Type type, BindingFlags bindingAttr, object?[] parameters) { ConstructorInfo[] constructors = type.GetConstructors(bindingAttr); foreach (ConstructorInfo constructorInfo in constructors) { ParameterInfo[] parameters2 = constructorInfo.GetParameters(); if (parameters2.Length != parameters.Length) { continue; } int num = 0; while (true) { if (num < parameters2.Length) { Type parameterType = parameters2[num].ParameterType; object obj = parameters[num]; if (obj == null) { if (parameterType.IsValueType && Nullable.GetUnderlyingType(parameterType) == null) { break; } } else if (!parameterType.IsInstanceOfType(obj)) { break; } num = checked(num + 1); continue; } return constructorInfo; } } return null; } public static string GetSimpleName(this Type type) { if (type == typeof(int)) { return "int"; } if (type == typeof(short)) { return "short"; } if (type == typeof(byte)) { return "byte"; } if (type == typeof(bool)) { return "bool"; } if (type == typeof(long)) { return "long"; } if (type == typeof(float)) { return "float"; } if (type == typeof(double)) { return "double"; } if (type == typeof(decimal)) { return "decimal"; } if (type == typeof(string)) { return "string"; } if (type.IsGenericType) { return type.Name.Remove(type.Name.IndexOf('`')); } return type.Name; } public static bool IsNumeric(this Type type) { TypeCode typeCode = Type.GetTypeCode(type); if (1 == 0) { } bool result = typeCode switch { TypeCode.Byte => true, TypeCode.SByte => true, TypeCode.UInt16 => true, TypeCode.Int16 => true, TypeCode.UInt32 => true, TypeCode.Int32 => true, TypeCode.UInt64 => true, TypeCode.Int64 => true, TypeCode.Decimal => true, TypeCode.Single => true, TypeCode.Double => true, _ => false, }; if (1 == 0) { } return result; } public static bool IsIntegral(this Type type) { TypeCode typeCode = Type.GetTypeCode(type); if (1 == 0) { } bool result = typeCode switch { TypeCode.Byte => true, TypeCode.SByte => true, TypeCode.UInt16 => true, TypeCode.Int16 => true, TypeCode.UInt32 => true, TypeCode.Int32 => true, TypeCode.UInt64 => true, TypeCode.Int64 => true, _ => false, }; if (1 == 0) { } return result; } public static bool IsSignedIntegral(this Type type) { TypeCode typeCode = Type.GetTypeCode(type); if (1 == 0) { } bool result = typeCode switch { TypeCode.SByte => true, TypeCode.Int16 => true, TypeCode.Int32 => true, TypeCode.Int64 => true, _ => false, }; if (1 == 0) { } return result; } public static bool IsUnsignedIntegral(this Type type) { TypeCode typeCode = Type.GetTypeCode(type); if (1 == 0) { } bool result = typeCode switch { TypeCode.Byte => true, TypeCode.UInt16 => true, TypeCode.UInt32 => true, TypeCode.UInt64 => true, _ => false, }; if (1 == 0) { } return result; } public static bool IsFloatingPoint(this Type type) { TypeCode typeCode = Type.GetTypeCode(type); if (1 == 0) { } bool result = typeCode switch { TypeCode.Single => true, TypeCode.Double => true, TypeCode.Decimal => true, _ => false, }; if (1 == 0) { } return result; } public static bool IsNullable(this Type type) { if (!type.IsValueType) { return true; } if (Nullable.GetUnderlyingType(type) != null) { return true; } return false; } public static T? GetCustomAttribute<T>(this Type type) where T : Attribute { return (T)type.GetCustomAttribute(typeof(T)); } public static IEnumerable<MethodInfo> GetMethodsWithAttribute<T>(this Type type) where T : Attribute { return from t in type.GetMethods() where t.GetCustomAttribute<T>() != null select t; } private static MethodInfo? GetCachedStaticMethod(Type type, string methodName) { return _invokeMethodCache.GetOrAdd(type, (Type _) => type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); } public static object? InvokeStaticMethod(this Type type, string methodName, params object?[] parameters) { MethodInfo cachedStaticMethod = GetCachedStaticMethod(type, methodName); if (cachedStaticMethod == null) { throw new MissingMethodException(type.FullName, methodName); } return cachedStaticMethod.Invoke(null, parameters); } public static TResult InvokeStaticMethod<TResult>(this Type type, string methodName) { MethodInfo cachedStaticMethod = GetCachedStaticMethod(type, methodName); if (cachedStaticMethod == null) { throw new MissingMethodException(type.FullName, methodName); } return (TResult)cachedStaticMethod.Invoke(null, Array.Empty<object>()); } public static TResult InvokeStaticMethod<T1, TResult>(this Type type, string methodName, T1 arg1) { MethodInfo cachedStaticMethod = GetCachedStaticMethod(type, methodName); if (cachedStaticMethod == null) { throw new MissingMethodException(type.FullName, methodName); } return (TResult)cachedStaticMethod.Invoke(null, new object[1] { arg1 }); } public static bool IsReferenceOrContainsReferences(this Type type) { if (!type.IsValueType) { return true; } if (type.IsPrimitive || type.IsEnum) { return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType.IsReferenceOrContainsReferences()) { return true; } } return false; } public static bool TryFindByName(string typeName, [MaybeNullWhen(false)] out Type type) { string normalizedFull = null; string normalizedShort = null; int num = typeName.LastIndexOf('<'); checked { if (num >= 0 && typeName.EndsWith('>')) { string text = typeName.Substring(0, num); string text2 = typeName.Substring(num + 1, typeName.Length - num - 2).Trim(); int num2 = ((text2.Length == 0) ? 1 : (text2.Count((char c) => c == ',') + 1)); normalizedFull = text + "`" + num2; int num3 = text.LastIndexOf('.'); string text3 = ((num3 >= 0) ? text.Substring(num3 + 1) : text); normalizedShort = text3 + "`" + num2; } type = AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly a) => a.GetTypes()).FirstOrDefault((Type t) => t.Name == typeName || t.FullName == typeName || (normalizedShort != null && t.Name == normalizedShort) || (normalizedFull != null && t.FullName == normalizedFull)); return type != null; } } } [JsonConverter(typeof(CamelCaseStringEnumConverter<GameState>))] public enum GameState { Unknown = 0, Error = -1, Unmodded = -2, BadGameSettings = -3, WrongVersion = -4, NotFocused = -5, Loading = -6, InLevel = 1, [Obsolete("Use InLevel instead. This state is redundant and does not provide any additional information about the game state.")] Ready = 1, TitleScreen = -17, Credits = -18, Menu = -13, Paused = -7, WrongMode = -8, SafeArea = -9, StartingArea = -19, Dialogue = -20, Cutscene = -11, BadPlayerState = -12, InputLocked = -21, Map = -14, UntimedArea = -10, InCombat = -15, NotInCombat = -16, PipelineBusy = -128, NotReady = int.MinValue } [Serializable] public class GenericEventBlock : CrowdControlBlock { [JsonProperty(PropertyName = "internal")] public bool Internal; [JsonProperty(PropertyName = "eventType")] public string EventType; [JsonProperty(PropertyName = "data")] public Dictionary<string, object?>? Data; public GenericEventBlock(string eventType) : base(BlockType.GenericEvent) { EventType = eventType; Data = new Dictionary<string, object>(); } public GenericEventBlock(string eventType, bool @internal) : base(BlockType.GenericEvent) { EventType = eventType; Data = new Dictionary<string, object>(); Internal = @internal; } public GenericEventBlock(string eventType, IEnumerable<KeyValuePair<string, object?>> data) : base(BlockType.GenericEvent) { EventType = eventType; Data = new Dictionary<string, object>(data); } public GenericEventBlock(string eventType, IEnumerable<KeyValuePair<string, object?>> data, bool @internal) : base(BlockType.GenericEvent) { EventType = eventType; Data = new Dictionary<string, object>(data); Internal = @internal; } } [JsonConverter(typeof(CamelCaseStringEnumConverter<IdentifierType>))] public enum IdentifierType { Effect, Group, Category } public interface IParameterValue { string ID { get; } string Name { get; } ParameterBase.ParameterType Type { get; } object? Value { get; } } [Serializable] public class Event { [JsonProperty(PropertyName = "stamp")] [JsonConverter(typeof(UnixTimestampConverter))] public DateTimeOffset Stamp = DateTimeOffset.UtcNow; [JsonProperty(PropertyName = "tags")] public IEnumerable<string> Tags; [JsonProperty(PropertyName = "level")] public LogLevel Level; [JsonProperty(PropertyName = "message")] public string Message; [JsonProperty(PropertyName = "source")] public string Source; } public static class Log { public static readonly LogInstance Instance = new LogInstance(); internal static readonly JsonSerializerSettings JSON_SETTINGS = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1 }; public const string OUTPUT_FOLDER = "Logs"; private static string BASE_DIRECTORY = string.Empty; private static bool s_baseDirectoryResolved; private static readonly object BASE_DIRECTORY_LOCK = new object(); public static readonly ColorTextWriter StdOutErrorWriter = new ColorTextWriter(Console.Out, ConsoleColor.Red); public static bool IncludeTimestamps { get; set; } = true; public static bool ConsoleOutput { get; set; } public static bool FileOutput { get; set; } public static int SuppressionCount { get; set; } private static bool? OverrideFileOutput { get; set; } public static event Action<string, LogLevel>? OnMessage; public static event Action<Event>? EventPosted; private static string EnsureBaseDirectory() { if (s_baseDirectoryResolved) { return BASE_DIRECTORY; } lock (BASE_DIRECTORY_LOCK) { if (s_baseDirectoryResolved) { return BASE_DIRECTORY; } s_baseDirectoryResolved = true; try { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Logs"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } string[] files = Directory.GetFiles(text, "*.log"); string[] array = files; foreach (string text2 in array) { try { string text3 = Path.ChangeExtension(text2, "prev"); if (File.Exists(text3)) { File.Delete(text3); } File.Move(text2, text3); } catch { } } BASE_DIRECTORY = text; } catch { BASE_DIRECTORY = string.Empty; OverrideFileOutput = false; } } return BASE_DIRECTORY; } private static void LogToFile(string logName, params string[] entries) { if (string.IsNullOrWhiteSpace(logName)) { return; } string text = EnsureBaseDirectory(); if (string.IsNullOrEmpty(text)) { return; } string path = Path.Combine(text, logName + ".log"); try { File.AppendAllLines(path, entries, Encoding.UTF8); } catch { } } public static void Debug(object? message) { Write(Console.Out, message, LogLevel.Debug); } public static void Message(object? message, bool omitTimestamp = false) { Write(Console.Out, message, LogLevel.Message, omitTimestamp); } public static void Message(object? message, LogLevel level, bool omitTimestamp = false) { Write(Console.Out, message, level, omitTimestamp); } public static void Error(object? message, bool suppress = false) { checked { if (suppress) { SuppressionCount++; Debug("An error was suppressed. Suppression count: " + SuppressionCount); } else { Write(Console.Error, message, LogLevel.Error); } } } public static void Error(Exception ex, bool suppress = false) { Error((object?)ex, suppress); } public static void Error(Exception ex, string message, bool suppress = false) { Error(message + Environment.NewLine + ex, suppress); } internal static void Write(TextWriter writer, object? message, LogLevel level, bool omitTimestamp = false) { string text = message?.ToString()?.Replace("\0", Environment.NewLine).Trim() ?? "(null)"; string text2 = ((!IncludeTimestamps || omitTimestamp) ? text : ($"[{DateTimeOffset.UtcNow}] " + text));
BepInEx/plugins/CrowdControl.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Logging; using BepinControl.Server; using ConnectorLib.JSON; using CrowdControl.Client.WebSocket; using CrowdControl.Client.WebSocket.Actions; using CrowdControl.Client.WebSocket.Data; using CrowdControl.Client.WebSocket.Metadata; using CrowdControl.Common; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.1.0")] [assembly: AssemblyInformationalVersion("2.0.1+9e4089c29e31c35db327e9a55e66d60c0c377197")] [assembly: AssemblyProduct("Crowd Control")] [assembly: AssemblyTitle("Crowd Control")] [assembly: AssemblyVersion("2.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 BepinControl { public class ControlClient { public static readonly string CV_HOST = "127.0.0.1"; public static readonly int CV_PORT = 51337; private static readonly string[] CommonMetadata = new string[1] { "health" }; public static readonly Dictionary<string, EffectDelegate> Delegate = new Dictionary<string, EffectDelegate> { { "fullhealth", EffectDelegates.FullHealth }, { "lowhealth", EffectDelegates.LowHealth }, { "invincibility", EffectDelegates.Invincibility }, { "ohko", EffectDelegates.OHKO }, { "hitplayer", EffectDelegates.HitPlayer }, { "killplayer", EffectDelegates.KillPlayer }, { "infinitestamina", EffectDelegates.InfiniteStamina }, { "nostamina", EffectDelegates.NoStamina }, { "giantplayer", EffectDelegates.GiantPlayer }, { "tinyplayer", EffectDelegates.TinyPlayer }, { "fastplayer", EffectDelegates.FastPlayer }, { "slowplayer", EffectDelegates.SlowPlayer }, { "skiptoday", EffectDelegates.SkipToDay }, { "skiptonight", EffectDelegates.SkipToNight }, { "skiptoday_proxy", EffectDelegates.SkipToDay }, { "skiptonight_proxy", EffectDelegates.SkipToNight }, { "killenemy", EffectDelegates.KillNearbyEnemy }, { "killallenemies", EffectDelegates.KillAllEnemies }, { "fastenemies", EffectDelegates.FastEnemies }, { "slowenemies", EffectDelegates.SlowEnemies }, { "giantenemies", EffectDelegates.GiantEnemies }, { "tinyenemies", EffectDelegates.TinyEnemies }, { "givefoodeffect", EffectDelegates.GiveFoodEffect }, { "removefoodeffect", EffectDelegates.RemoveFoodEffect }, { "removeallfoodeffects", EffectDelegates.RemoveAllFoodEffects }, { "addstatus_wet", EffectDelegates.AddStatus }, { "addstatus_poison", EffectDelegates.AddStatus }, { "addstatus_rested", EffectDelegates.AddStatus }, { "removestatus_wet", EffectDelegates.RemoveStatus }, { "removestatus_poison", EffectDelegates.RemoveStatus }, { "removestatus_rested", EffectDelegates.RemoveStatus }, { "spawn_Greyling", EffectDelegates.Spawn }, { "spawn_Greydwarf", EffectDelegates.Spawn }, { "spawn_Skeleton", EffectDelegates.Spawn }, { "spawn_Surtling", EffectDelegates.Spawn }, { "spawn_Bat", EffectDelegates.Spawn }, { "spawn_Draugr", EffectDelegates.Spawn }, { "spawn_Troll", EffectDelegates.Spawn }, { "spawn_Abomination", EffectDelegates.Spawn }, { "spawn_StoneGolem", EffectDelegates.Spawn }, { "spawn_Fish", EffectDelegates.Spawn }, { "spawn_Boar", EffectDelegates.Spawn }, { "spawn_Hare", EffectDelegates.Spawn }, { "spawn_Deer", EffectDelegates.Spawn }, { "spawn_Wolf", EffectDelegates.Spawn }, { "spawn_Lox", EffectDelegates.Spawn }, { "give_wood", EffectDelegates.GiveItems }, { "give_stone", EffectDelegates.GiveItems }, { "give_ore", EffectDelegates.GiveItems }, { "give_food", EffectDelegates.GiveItems }, { "give_mead", EffectDelegates.GiveItems }, { "give_supplies", EffectDelegates.GiveItems }, { "give_metal", EffectDelegates.GiveItems }, { "give_seeds", EffectDelegates.GiveItems }, { "give_arrows", EffectDelegates.GiveItems }, { "give_valuables", EffectDelegates.GiveItems }, { "give_hides", EffectDelegates.GiveItems }, { "give_potions", EffectDelegates.GiveItems }, { "give_crafting", EffectDelegates.GiveItems }, { "raiseskills", EffectDelegates.RaiseSkills }, { "lowerskills", EffectDelegates.LowerSkills }, { "dropcurrentweapon", EffectDelegates.DropCurrentWeapon }, { "tpplayertorandom", EffectDelegates.TPPlayerToRandom }, { "tprandomtoplayer", EffectDelegates.TPRandomToPlayer } }; private bool paused; public bool inGame = true; public static readonly ControlClient Instance = new ControlClient(); public static readonly int RECV_BUF = 4096; public static readonly int RECV_TIME = 5000000; private static readonly EmptyResponse KEEPALIVE = new EmptyResponse { type = (ResponseType)255 }; private GameState? _last_game_state; private const float GAME_STATUS_UPDATE_INTERVAL = 1f; private float _game_status_update_timer; private IPEndPoint Endpoint { get; } private Queue<SimpleJSONRequest> Requests { get; } private bool Running { get; set; } public static Socket? Socket { get; set; } private ControlClient() { Endpoint = new IPEndPoint(IPAddress.Parse(CV_HOST), CV_PORT); Requests = new Queue<SimpleJSONRequest>(); Running = true; Socket = null; } public bool isReady() { bool result = true; try { if (!Object.op_Implicit((Object)(object)Game.instance)) { result = false; } if (Game.IsPaused()) { result = false; } if (((Character)Player.m_localPlayer).InCutscene()) { result = false; } if (((Character)Player.m_localPlayer).GetHealthPercentage() == 0f) { result = false; } } catch { return false; } return result; } public bool HideEffect(string code) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse)new EffectUpdate(code, (EffectStatus)129, (string)null)); } public bool ShowEffect(string code) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse)new EffectUpdate(code, (EffectStatus)128, (string)null)); } public bool DisableEffect(string code) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse)new EffectUpdate(code, (EffectStatus)131, (string)null)); } public bool EnableEffect(string code) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse)new EffectUpdate(code, (EffectStatus)130, (string)null)); } private void ClientLoop() { Mod.mls.LogInfo((object)"Connected to Crowd Control"); new Timer(timeUpdate, null, 0, 200); try { while (Running) { SimpleJSONRequest val = Recieve(this, Socket); if (val == null || ((SimpleJSONMessage)val).IsKeepAlive) { Thread.Sleep(0); continue; } lock (Requests) { Requests.Enqueue(val); } } } catch (Exception) { Mod.mls.LogInfo((object)"Disconnected from Crowd Control"); Socket?.Close(); } } public SimpleJSONRequest? Recieve(ControlClient client, Socket socket) { byte[] array = new byte[RECV_BUF]; string text = ""; int num = 0; do { if (!client.IsRunning()) { return null; } if (socket.Poll(RECV_TIME, SelectMode.SelectRead)) { num = socket.Receive(array); if (num < 0) { return null; } text += Encoding.ASCII.GetString(array); } else { KeepAlive(); } } while (num == 0 || (num == RECV_BUF && array[RECV_BUF - 1] != 0)); return SimpleJSONRequest.Parse(text); } public bool KeepAlive() { return Send((SimpleJSONResponse)(object)KEEPALIVE); } public bool Send(SimpleJSONResponse message) { Socket socket = Socket; if (socket == null || !socket.Connected) { return false; } byte[] bytes = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject((object)message)); byte[] array = new byte[bytes.Length + 1]; Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length); array[bytes.Length] = 0; try { return socket.Send(array) == array.Length; } catch (Exception ex) when (((ex is SocketException || ex is ObjectDisposedException) ? 1 : 0) != 0) { return false; } } public void timeUpdate(object state) { inGame = true; if (!isReady()) { inGame = false; } if (!inGame) { TimedThread.addTime(200); paused = true; } else if (paused) { paused = false; TimedThread.unPause(); TimedThread.tickTime(200); } else { TimedThread.tickTime(200); } } public bool IsRunning() { return Running; } public void NetworkLoop() { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; bool flag = false; while (Running) { if (!flag) { Mod.mls.LogInfo((object)"Attempting to connect to Crowd Control"); } try { Socket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, optionValue: true); if (Socket.BeginConnect(Endpoint, null, null).AsyncWaitHandle.WaitOne(10000, exitContext: true) && Socket.Connected) { flag = false; ClientLoop(); } else if (!flag) { flag = true; Mod.mls.LogInfo((object)"Crowd Control desktop app not running; will keep retrying quietly. This is expected when playing on a Crowd Control server."); } Socket.Close(); } catch (Exception ex) { if (!flag) { flag = true; Mod.mls.LogInfo((object)("Could not reach the Crowd Control desktop app (" + ex.GetType().Name + "); will keep retrying quietly.")); } } Thread.Sleep(10000); } } public void FixedUpdate() { _game_status_update_timer += Time.fixedDeltaTime; if (_game_status_update_timer >= 1f) { UpdateGameState(); _game_status_update_timer = 0f; } } public void RequestLoop() { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Invalid comparison between Unknown and I4 //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; while (Running) { try { SimpleJSONRequest val; lock (Requests) { if (Requests.Count == 0) { continue; } val = Requests.Dequeue(); goto IL_0050; } IL_0050: EffectRequest val2 = (EffectRequest)(object)((val is EffectRequest) ? val : null); if (val2 != null) { string code = val2.code; try { EffectDelegate value; EffectResponse val3 = (EffectResponse)((code == null) ? ((object)new EffectResponse(((SimpleJSONMessage)val2).ID, (EffectStatus)2, "No effect code was sent.")) : ((!isReady()) ? ((object)new EffectResponse(((SimpleJSONMessage)val2).ID, (EffectStatus)3, (string)null)) : ((!Delegate.TryGetValue(code, out value)) ? ((object)new EffectResponse(((SimpleJSONMessage)val2).ID, (EffectStatus)2, "Unknown effect code: " + code)) : ((object)value(this, val2))))); if (val3 != null) { Send((SimpleJSONResponse)(object)val3); } } catch (KeyNotFoundException) { Send((SimpleJSONResponse)new EffectResponse(((SimpleJSONMessage)val2).ID, (EffectStatus)2, "Request error for '" + code + "'")); } } else if ((int)val.type == 253) { UpdateGameState(force: true); } } catch (Exception) { Mod.mls.LogInfo((object)"Disconnected from Crowd Control"); Socket?.Close(); } } } public void Stop() { Running = false; } private bool UpdateGameState(bool force = false) { if (Socket == null || !Socket.Connected) { return false; } if (!Object.op_Implicit((Object)(object)Game.instance)) { return UpdateGameState((GameState)(-6), force); } if (Game.IsPaused()) { return UpdateGameState((GameState)(-5), force); } return UpdateGameState((GameState)1, force); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool UpdateGameState(GameState newState, bool force) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return UpdateGameState(newState, null, force); } private bool UpdateGameState(GameState newState, string? message = null, bool force = false) { //IL_0021: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (force || _last_game_state != (GameState?)newState) { _last_game_state = newState; return Send((SimpleJSONResponse)new GameUpdate(newState, message)); } return true; } } public delegate EffectResponse EffectDelegate(ControlClient client, EffectRequest req); public static class EffectDelegates { public static Random rng = new Random(); public static EffectResponse DropCurrentWeapon(ControlClient client, EffectRequest req) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0096: 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_009e: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) ItemData weapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (weapon != null && ((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(weapon)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); ((Humanoid)Player.m_localPlayer).DropItem(inventory, weapon, 1); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " dropped your weapon", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse GiveItems(ControlClient client, EffectRequest req) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (Gifts.Sets.TryGetValue(req.code, out (string prefab, int count)[] items)) { Mod.ActionQueue.Enqueue(delegate { try { if (Gifts.Drop(req.viewer, items)) { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " sent you a package", 0, (Sprite)null, false); } } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } }); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, ""); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)2, "Unknown gift '" + req.code + "'"); } public static EffectResponse TPPlayerToRandom(ControlClient client, EffectRequest req) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (ZNet.instance.GetPlayerList().Count != 1) { Player val = null; Player choice = null; for (int i = 0; i < 4; i++) { val = Player.GetRandomPlayer(); if ((Object)(object)val != (Object)(object)Player.m_localPlayer) { choice = val; } } if (!((Object)(object)choice == (Object)null)) { EffectStatus val2 = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) ((Character)Player.m_localPlayer).TeleportTo(((Component)choice).transform.position, Quaternion.identity, false); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " teleported you to " + ((Object)choice).name, 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val2, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse TPRandomToPlayer(ControlClient client, EffectRequest req) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (ZNet.instance.GetPlayerList().Count != 1) { Player val = null; Player choice = null; for (int i = 0; i < 4; i++) { val = Player.GetRandomPlayer(); if ((Object)(object)val != (Object)(object)Player.m_localPlayer) { choice = val; } } if (!((Object)(object)choice == (Object)null)) { EffectStatus val2 = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) ((Character)choice).TeleportTo(((Component)Player.m_localPlayer).transform.position, Quaternion.identity, false); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " teleported " + ((Object)choice).name + " to you", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val2, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse FullHealth(ControlClient client, EffectRequest req) { //IL_0036: 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_0035: Expected O, but got Unknown //IL_0078: 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_0080: Expected O, but got Unknown if (!(((Character)Player.m_localPlayer).GetHealthPercentage() > 90f)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { float maxHealth = ((Character)Player.m_localPlayer).GetMaxHealth(); ((Character)Player.m_localPlayer).SetHealth(maxHealth); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " gave you full health", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse LowHealth(ControlClient client, EffectRequest req) { //IL_0036: 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_0035: Expected O, but got Unknown //IL_0078: 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_0080: Expected O, but got Unknown if (!(((Character)Player.m_localPlayer).GetHealthPercentage() < 0.2f)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).SetHealth(1f); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " drained your health", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse Invincibility(ControlClient client, EffectRequest req) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.INVINCIBILITY)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you invincible", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.INVINCIBILITY, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse OHKO(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.INVINCIBILITY) && !TimedThread.isRunning(TimedType.OHKO)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " activated OHKO", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.OHKO, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse HitPlayer(ControlClient client, EffectRequest req) { //IL_0042: 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_0041: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown float health = ((Character)Player.m_localPlayer).GetHealth(); if (!(health <= 8f)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) HitData val2 = new HitData(); float num = Mod.rnd.Next(300, 400) / 100; val2.m_damage.m_damage = health / num; val2.m_hitType = (HitType)14; ((Character)Player.m_localPlayer).Damage(val2); ((Character)Player.m_localPlayer).Message((MessageType)1, $"{req.viewer} hit you for {Math.Floor(val2.m_damage.m_damage)}", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse KillPlayer(ControlClient client, EffectRequest req) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0058: Expected O, but got Unknown EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) HitData val2 = new HitData(); val2.m_damage.m_damage = 99999f; val2.m_hitType = (HitType)14; ((Character)Player.m_localPlayer).Damage(val2); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " killed you", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse InfiniteStamina(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.INFINITESTAMINA) && !TimedThread.isRunning(TimedType.NOSTAMINA)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " gave you infinite stamina", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.INFINITESTAMINA, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse NoStamina(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.INFINITESTAMINA) && !TimedThread.isRunning(TimedType.NOSTAMINA)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " removed your stamina", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.NOSTAMINA, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse GiantPlayer(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.GIANTPLAYER) && !TimedThread.isRunning(TimedType.TINYPLAYER)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you giant", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.GIANTPLAYER, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse TinyPlayer(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.GIANTPLAYER) && !TimedThread.isRunning(TimedType.TINYPLAYER)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you tiny", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.TINYPLAYER, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse FastPlayer(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.FASTPLAYER) && !TimedThread.isRunning(TimedType.SLOWPLAYER)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you fast", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.FASTPLAYER, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse SlowPlayer(ControlClient client, EffectRequest req) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.FASTPLAYER) && !TimedThread.isRunning(TimedType.SLOWPLAYER)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you slow", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.SLOWPLAYER, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse SkipToDay(ControlClient client, EffectRequest req) { //IL_004a: 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_0049: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown float num = (float)getProperty(Mod.envMan, "m_smoothDayFraction"); if (num >= 0.25f && num <= 0.75f) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } EffectStatus val = (EffectStatus)0; string text = ""; string code = req.code; if (code.Contains("_")) { code = code.Split('_')[1]; } try { Mod.ActionQueue.Enqueue(delegate { double timeSeconds = ZNet.instance.GetTimeSeconds(); double num2 = timeSeconds - (double)((float)Mod.envMan.m_dayLengthSec * 0.15f); int day = Mod.envMan.GetDay(num2); double num3 = Mod.envMan.GetMorningStartSec(day + 1) + 200.0; setProperty(Mod.envMan, "m_skipTime", true); setProperty(Mod.envMan, "m_skipToTime", num3); double num4 = num3 - timeSeconds; setProperty(Mod.envMan, "m_timeSkipSpeed", num4 / 12.0); if (code != "proxy") { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " skipped to day", 0, (Sprite)null, false); } }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } if (code == "proxy") { return null; } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse SkipToNight(ControlClient client, EffectRequest req) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown float num = (float)getProperty(Mod.envMan, "m_smoothDayFraction"); if (num <= 0.25f || num >= 0.75f) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } EffectStatus val = (EffectStatus)0; string text = ""; string code = req.code; if (code.Contains("_")) { code = code.Split('_')[1]; } try { Mod.ActionQueue.Enqueue(delegate { double timeSeconds = ZNet.instance.GetTimeSeconds(); double num2 = timeSeconds - (double)((float)Mod.envMan.m_dayLengthSec * 0.15f); int day = Mod.envMan.GetDay(num2); double num3 = Mod.envMan.GetMorningStartSec(day + 1) - 400.0; setProperty(Mod.envMan, "m_skipTime", true); setProperty(Mod.envMan, "m_skipToTime", num3); double num4 = num3 - timeSeconds; setProperty(Mod.envMan, "m_timeSkipSpeed", num4 / 12.0); if (code != "proxy") { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " skipped to night", 0, (Sprite)null, false); } }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } if (code == "proxy") { return null; } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse KillNearbyEnemy(ControlClient client, EffectRequest req) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown EffectStatus val = (EffectStatus)0; string text = ""; bool found = false; try { Mod.ActionQueue.Enqueue(delegate { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown List<Character> list = (from x in Character.GetAllCharacters() orderby rng.Next() select x).ToList(); string text2 = ""; foreach (Character item in list) { if (!item.IsPlayer() && !item.IsTamed() && (int)item.m_faction != 1 && !found) { HitData val2 = new HitData(); val2.m_damage.m_damage = 1E+10f; item.Damage(val2); text2 = ((Object)item).name; found = true; } } char[] array = text2.ToCharArray(); char[] source = new char[5] { 'a', 'e', 'i', 'o', 'u' }; string text3 = "a"; if (source.Contains(array[0])) { text3 = "an"; } ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " killed " + text3 + " " + text2, 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse KillAllEnemies(ControlClient client, EffectRequest req) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0058: Expected O, but got Unknown EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown foreach (Character allCharacter in Character.GetAllCharacters()) { if (!allCharacter.IsPlayer() && !allCharacter.IsTamed() && (int)allCharacter.m_faction != 1) { HitData val2 = new HitData(); val2.m_damage.m_damage = 1E+10f; allCharacter.Damage(val2); _ = ((Object)allCharacter).name; } } ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " killed all nearby enemies", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse FastEnemies(ControlClient client, EffectRequest req) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.FASTENEMIES) && !TimedThread.isRunning(TimedType.SLOWENEMIES)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made enemies fast", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.FASTENEMIES, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse SlowEnemies(ControlClient client, EffectRequest req) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.FASTENEMIES) && !TimedThread.isRunning(TimedType.SLOWENEMIES)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made enemies slow", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.SLOWENEMIES, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse GiantEnemies(ControlClient client, EffectRequest req) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.GIANTENEMIES) && !TimedThread.isRunning(TimedType.TINYENEMIES)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made enemies giant", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.GIANTENEMIES, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse TinyEnemies(ControlClient client, EffectRequest req) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown if (!TimedThread.isRunning(TimedType.GIANTENEMIES) && !TimedThread.isRunning(TimedType.TINYENEMIES)) { long num = 30L; if (req.duration > 0) { num = req.duration.Value / 1000; } try { Mod.ActionQueue.Enqueue(delegate { ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made enemies tiny", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } new Thread(new TimedThread(((SimpleJSONMessage)req).ID, TimedType.TINYENEMIES, num * 1000).Run).Start(); return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)0, num * 1000, (string)null); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse GiveFoodEffect(ControlClient client, EffectRequest req) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown List<Food> m_foods = Player.m_localPlayer.GetFoods(); if (m_foods.Count != 3) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown string[] FoodNameList = new string[39] { "BlackSoup", "BloodPudding", "Blueberries", "BoarJerky", "Bread", "Carrot", "CarrotSoup", "Cloudberry", "CookedBugMeat", "CookedChickenMeat", "CookedEgg", "CookedHareMeat", "CookedLoxMeat", "CookedWolfMeat", "DeerStew", "Eyescream", "FishAndBread", "FishCooked", "FishWraps", "Honey", "HoneyGlazedChicken", "LoxPie", "MeatPlatter", "Mushroom", "MushroomBlue", "MushroomJotunPuffs", "MushroomOmelette", "MushroomYellow", "NeckTailGrilled", "Onion", "OnionSoup", "RoyalJelly", "Salad", "Sausages", "SerpentStew", "TurnipStew", "WolfJerky", "WolfMeatSkewer", "YggdrasilPorridge" }; List<ItemDrop> list = (from x in ObjectDB.instance.GetAllItems((ItemType)2, "") where FoodNameList.Contains(((Object)x).name) select x).ToList(); ItemDrop val2 = list[Mod.rnd.Next(0, list.Count)]; ItemData itemData = val2.m_itemData; Food val3 = new Food(); val3.m_name = ((Object)val2).name; val3.m_item = itemData; val3.m_time = itemData.m_shared.m_foodBurnTime; val3.m_health = itemData.m_shared.m_food; val3.m_stamina = itemData.m_shared.m_foodStamina; val3.m_eitr = itemData.m_shared.m_foodEitr; m_foods.Add(val3); setProperty(Player.m_localPlayer, "m_foods", m_foods); callFunc(Player.m_localPlayer, "UpdateFood", new object[2] { 0f, true }); string text2 = req.viewer + " fed you "; if (itemData.m_shared.m_food > 0f) { text2 = text2 + " +" + itemData.m_shared.m_food + " $item_food_health "; } if (itemData.m_shared.m_foodStamina > 0f) { text2 = text2 + " +" + itemData.m_shared.m_foodStamina + " $item_food_stamina "; } if (itemData.m_shared.m_foodEitr > 0f) { text2 = text2 + " +" + itemData.m_shared.m_foodEitr + " $item_food_eitr "; } ((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, itemData.m_shared.m_icons[0], false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse RemoveFoodEffect(ControlClient client, EffectRequest req) { //IL_0036: 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_0035: Expected O, but got Unknown //IL_0078: 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_0080: Expected O, but got Unknown if (Player.m_localPlayer.GetFoods().Count != 0) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { Player.m_localPlayer.RemoveOneFood(); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " removed a food effect", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse RemoveAllFoodEffects(ControlClient client, EffectRequest req) { //IL_0036: 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_0035: Expected O, but got Unknown //IL_0078: 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_0080: Expected O, but got Unknown if (Player.m_localPlayer.GetFoods().Count != 0) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { Player.m_localPlayer.ClearFood(); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " removed all food effects", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse AddStatus(ControlClient client, EffectRequest req) { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown string code = req.code; code = code.Split('_')[1]; SEMan seman = ((Character)Player.m_localPlayer).GetSEMan(); if (code == "wet" && seman.HaveStatusEffect(SEMan.s_statusEffectWet)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } if (code == "rested" && seman.HaveStatusEffect(SEMan.s_statusEffectRested)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } if (code == "poison") { if (seman.HaveStatusEffect(SEMan.s_statusEffectPoison)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } if (((Character)Player.m_localPlayer).GetHealth() < 10f) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } } EffectStatus val = (EffectStatus)0; string text = ""; try { if (code == "wet") { Mod.ActionQueue.Enqueue(delegate { seman.AddStatusEffect(SEMan.s_statusEffectWet, true, 0, 0f, (short)(-1)); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you wet", 0, (Sprite)null, false); }); } if (code == "rested") { Mod.ActionQueue.Enqueue(delegate { seman.AddStatusEffect(SEMan.s_statusEffectRested, true, 0, 0f, (short)(-1)); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " made you rested", 0, (Sprite)null, false); }); } if (code == "poison") { Mod.ActionQueue.Enqueue(delegate { StatusEffect obj = seman.AddStatusEffect(SEMan.s_statusEffectPoison, false, 0, 0f, (short)(-1)); StatusEffect obj2 = ((obj is SE_Poison) ? obj : null); float num = ((Character)Player.m_localPlayer).GetHealth() / 2f; ((SE_Poison)obj2).AddDamage(num); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " poisoned you", 0, (Sprite)null, false); }); } } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse RemoveStatus(ControlClient client, EffectRequest req) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown string code = req.code; code = code.Split('_')[1]; SEMan seman = ((Character)Player.m_localPlayer).GetSEMan(); if (code == "wet" && !seman.HaveStatusEffect(SEMan.s_statusEffectWet)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } if (code == "rested" && !seman.HaveStatusEffect(SEMan.s_statusEffectRested)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } if (code == "poison" && !seman.HaveStatusEffect(SEMan.s_statusEffectPoison)) { return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } EffectStatus val = (EffectStatus)0; string text = ""; try { int statusCode = 0; if (code == "wet") { statusCode = SEMan.s_statusEffectWet; } if (code == "rested") { statusCode = SEMan.s_statusEffectRested; } if (code == "poison") { statusCode = SEMan.s_statusEffectPoison; } Mod.ActionQueue.Enqueue(delegate { List<StatusEffect> list = (List<StatusEffect>)getProperty(seman, "m_statusEffects"); HashSet<int> hashSet = (HashSet<int>)getProperty(seman, "m_statusEffectsHashSet"); int count = list.Count; for (int i = 0; i < count; i++) { StatusEffect val2 = list[i]; if (val2.NameHash() == statusCode) { val2.Stop(); list.Remove(val2); hashSet.Remove(statusCode); } } ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " removed your " + code, 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse Spawn(ControlClient client, EffectRequest req) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Expected O, but got Unknown EffectStatus val = (EffectStatus)0; string text = ""; try { Dictionary<string, (string name, int minAmount, int maxAmount, int minDistance, int maxDistance)> prefabStats = new Dictionary<string, (string, int, int, int, int)> { { "Skeleton", ("skeleton", 1, 2, 2, 6) }, { "Skeleton_Poison", ("rancid remains", 1, 2, 2, 6) }, { "Abomination", ("an abomination", 1, 2, 10, 20) }, { "Bat", ("bats", 4, 7, 3, 16) }, { "Boar", ("boars", 3, 6, 3, 16) }, { "Deer", ("deer", 7, 10, 3, 16) }, { "Draugr", ("draugr", 1, 2, 2, 6) }, { "Draugr_Elite", ("draugr elite", 1, 2, 2, 6) }, { "Greydwarf", ("greydwarf", 1, 2, 2, 6) }, { "Greydwarf_Elite", ("greydwarf brute", 1, 2, 2, 6) }, { "Greydwarf_Shaman", ("greydwarf shaman", 1, 2, 2, 6) }, { "Greyling", ("greylings", 4, 7, 3, 16) }, { "Hare", ("hares", 9, 12, 3, 16) }, { "Lox", ("a lox", 1, 2, 10, 16) }, { "StoneGolem", ("a stone golem", 1, 2, 10, 20) }, { "Surtling", ("surtlings", 3, 5, 3, 16) }, { "Troll", ("troll", 1, 2, 10, 20) }, { "Wolf", ("wolves", 2, 3, 3, 16) }, { "Fish", ("fish", 9, 12, 1, 12) } }; string choice = req.code; choice = choice.Split('_')[1]; if (choice == "Draugr") { string[] array = new string[2] { "Draugr", "Draugr_Elite" }; choice = array[Mod.rnd.Next(array.Length)]; } else if (choice == "Greydwarf") { string[] array2 = new string[3] { "Greydwarf", "Greydwarf_Elite", "Greydwarf_Shaman" }; choice = array2[Mod.rnd.Next(array2.Length)]; } else if (choice == "Skeleton") { string[] array3 = new string[2] { "Skeleton", "Skeleton_Poison" }; choice = array3[Mod.rnd.Next(array3.Length)]; } if (choice == "Fish") { Mod.ActionQueue.Enqueue(delegate { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) string[] array4 = new string[9] { "Fish1", "Fish2", "Fish3", "Fish4_cave", "Fish5", "Fish6", "Fish7", "Fish8", "Fish9" }; string text2 = ""; int num = Mod.rnd.Next(5, 9); for (int i = 0; i < num; i++) { text2 = array4[Mod.rnd.Next(array4.Length)]; GameObject prefab = ZNetScene.instance.GetPrefab(text2); float num2 = (float)Mod.rnd.Next(1, 12) - 6f; float num3 = Mod.rnd.Next(6, 10); Object.Instantiate<GameObject>(prefab, ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * num2 + Vector3.up * num3, Quaternion.identity); } ((Character)Player.m_localPlayer).Message((MessageType)1, $"{req.viewer} spawned {num} fish", 0, (Sprite)null, false); }); } else { Mod.ActionQueue.Enqueue(delegate { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab(choice); int num = Mod.rnd.Next(prefabStats[choice].minAmount, prefabStats[choice].maxAmount); for (int i = 0; i < num; i++) { float num2 = Mod.rnd.Next(prefabStats[choice].minDistance, prefabStats[choice].maxDistance); Object.Instantiate<GameObject>(prefab, ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * num2 + Vector3.up, Quaternion.identity); } ((Character)Player.m_localPlayer).Message((MessageType)1, $"{req.viewer} spawned {num} {choice}", 0, (Sprite)null, false); }); } } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } public static EffectResponse RaiseSkills(ControlClient client, EffectRequest req) { //IL_0047: 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_0046: Expected O, but got Unknown //IL_0089: 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) //IL_0091: Expected O, but got Unknown Skills skills = ((Character)Player.m_localPlayer).GetSkills(); if (!(skills.GetTotalSkill() > 2000f)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { skills.CheatRaiseSkill("all", 1f, true); Player.m_localPlayer.OnSkillLevelup((SkillType)999, 1f); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " raised all your skills", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static EffectResponse LowerSkills(ControlClient client, EffectRequest req) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown Skills skills = ((Character)Player.m_localPlayer).GetSkills(); float totalSkills = skills.GetTotalSkill(); if (!(totalSkills < 40f)) { EffectStatus val = (EffectStatus)0; string text = ""; try { Mod.ActionQueue.Enqueue(delegate { skills.LowerAllSkills(1f / (totalSkills / 15f)); Player.m_localPlayer.OnSkillLevelup((SkillType)999, 1f); ((Character)Player.m_localPlayer).Message((MessageType)1, req.viewer + " lowered all your skills", 0, (Sprite)null, false); }); } catch (Exception arg) { Mod.mls.LogInfo((object)$"Crowd Control Error: {arg}"); } return new EffectResponse(((SimpleJSONMessage)req).ID, val, text); } return new EffectResponse(((SimpleJSONMessage)req).ID, (EffectStatus)3, ""); } public static void setProperty(object a, string prop, object val) { a.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(a, val); } public static object getProperty(object a, string prop) { return a.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(a); } public static void setSubProperty(object a, string prop, string prop2, object val) { FieldInfo field = a.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.NonPublic); field.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(field, val); } public static void callSubFunc(object a, string prop, string func, object val) { callSubFunc(a, prop, func, new object[1] { val }); } public static void callSubFunc(object a, string prop, string func, object[] vals) { FieldInfo field = a.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.NonPublic); field.GetType().GetMethod(func, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Invoke(field, vals); } public static void callFunc(object a, string func, object val) { callFunc(a, func, new object[1] { val }); } public static void callFunc(object a, string func, object[] vals) { a.GetType().GetMethod(func, BindingFlags.Instance | BindingFlags.NonPublic).Invoke(a, vals); } public static object callAndReturnFunc(object a, string func, object val) { return callAndReturnFunc(a, func, new object[1] { val }); } public static object callAndReturnFunc(object a, string func, object[] vals) { return a.GetType().GetMethod(func, BindingFlags.Instance | BindingFlags.NonPublic).Invoke(a, vals); } } internal static class Gifts { private const string TombstonePrefab = "Player_tombstone"; internal static readonly Dictionary<string, (string prefab, int count)[]> Sets = new Dictionary<string, (string, int)[]>(StringComparer.Ordinal) { ["give_wood"] = new(string, int)[4] { ("Wood", 50), ("FineWood", 20), ("RoundLog", 20), ("Resin", 15) }, ["give_stone"] = new(string, int)[3] { ("Stone", 50), ("Flint", 15), ("Coal", 20) }, ["give_ore"] = new(string, int)[3] { ("CopperOre", 15), ("TinOre", 15), ("IronScrap", 10) }, ["give_food"] = new(string, int)[4] { ("CookedMeat", 5), ("Honey", 5), ("Carrot", 5), ("Blueberries", 10) }, ["give_mead"] = new(string, int)[2] { ("MeadHealthMinor", 3), ("MeadStaminaMinor", 3) }, ["give_supplies"] = new(string, int)[4] { ("Feathers", 20), ("LeatherScraps", 20), ("DeerHide", 10), ("Coins", 200) }, ["give_metal"] = new(string, int)[4] { ("Bronze", 10), ("Iron", 10), ("Silver", 5), ("BlackMetal", 5) }, ["give_seeds"] = new(string, int)[5] { ("CarrotSeeds", 10), ("TurnipSeeds", 10), ("OnionSeeds", 10), ("Barley", 10), ("Flax", 10) }, ["give_arrows"] = new(string, int)[5] { ("ArrowFlint", 50), ("ArrowFire", 30), ("ArrowBronze", 30), ("ArrowIron", 30), ("ArrowPoison", 20) }, ["give_valuables"] = new(string, int)[5] { ("Coins", 500), ("Amber", 10), ("AmberPearl", 5), ("Ruby", 5), ("SilverNecklace", 2) }, ["give_hides"] = new(string, int)[4] { ("TrollHide", 10), ("WolfPelt", 10), ("LoxPelt", 5), ("DeerHide", 10) }, ["give_potions"] = new(string, int)[4] { ("MeadHealthMedium", 3), ("MeadStaminaMedium", 3), ("MeadFrostResist", 2), ("MeadPoisonResist", 2) }, ["give_crafting"] = new(string, int)[5] { ("SurtlingCore", 5), ("GreydwarfEye", 20), ("Guck", 10), ("Chain", 3), ("IronNails", 50) } }; private static bool _checked; internal static bool Drop(string from, IEnumerable<(string prefab, int count)> items) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) Player localPlayer = Player.m_localPlayer; ZNetScene instance = ZNetScene.instance; if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null) { return false; } GameObject prefab = instance.GetPrefab("Player_tombstone"); if ((Object)(object)prefab == (Object)null) { Mod.mls.LogWarning((object)"Crowd Control: no 'Player_tombstone' prefab; cannot deliver items"); return false; } Vector3 val = ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward * 1.5f + Vector3.up; GameObject val2 = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity); Container component = val2.GetComponent<Container>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); Mod.mls.LogWarning((object)"Crowd Control: tombstone has no container; cannot deliver items"); return false; } Inventory inventory = component.GetInventory(); int num = 0; foreach (var item3 in items) { string item = item3.prefab; int item2 = item3.count; GameObject prefab2 = instance.GetPrefab(item); if ((Object)(object)prefab2 == (Object)null) { Mod.mls.LogWarning((object)("Crowd Control: unknown item '" + item + "', skipping")); } else { if ((Object)(object)prefab2.GetComponent<ItemDrop>() == (Object)null) { continue; } int num2 = item2; while (num2 > 0) { int num3 = Math.Min(num2, StackLimit(prefab2)); if (!inventory.AddItem(prefab2, num3)) { break; } num2 -= num3; num++; } } } if (num == 0) { Object.Destroy((Object)(object)val2); return false; } TombStone component2 = val2.GetComponent<TombStone>(); if (component2 != null) { component2.Setup(from, localPlayer.GetPlayerID()); } return true; } private static int StackLimit(GameObject prefab) { try { int num = prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_maxStackSize ?? 1; return (num <= 0) ? 1 : num; } catch { return 1; } } internal static void VerifyItems() { if (_checked) { return; } ZNetScene scene = ZNetScene.instance; if ((Object)(object)scene == (Object)null) { return; } _checked = true; List<string> list = (from name in Sets.Values.SelectMany(((string prefab, int count)[] set) => set.Select(((string prefab, int count) item) => item.prefab)).Distinct<string>(StringComparer.Ordinal) where (Object)(object)scene.GetPrefab(name) == (Object)null select name).OrderBy<string, string>((string name) => name, StringComparer.Ordinal).ToList(); if ((Object)(object)scene.GetPrefab("Player_tombstone") == (Object)null) { Mod.mls.LogWarning((object)"Crowd Control: no 'Player_tombstone'; gifts cannot be delivered"); } if (list.Count == 0) { Mod.mls.LogInfo((object)"Crowd Control: all gift items exist in this build"); } else { Mod.mls.LogWarning((object)($"Crowd Control: {list.Count} gift item(s) unknown to this build " + "and will be skipped: " + string.Join(", ", list))); } } } public delegate EffectResponseMetadata MetadataDelegate(ControlClient client); public static class MetadataDelegates { } [BepInPlugin("WarpWorld.CrowdControl", "Crowd Control", "2.0.1")] public class Mod : BaseUnityPlugin { [HarmonyPatch(typeof(Game), "Update")] public static class EffectProcessing { public static void Prefix() { if (ActionQueue.Count == 0) { return; } Queue<Action> queue = new Queue<Action>(); while (ActionQueue.Count > 0) { Action action = ActionQueue.Dequeue(); try { action(); } catch (Exception) { queue.Enqueue(action); } } if (queue.Count > 0) { ActionQueue = queue; } } } [HarmonyPatch(typeof(FejdStartup), "Start")] private class ConsolePatch { public static void Postfix() { Console.SetConsoleEnabled(true); } } [HarmonyPatch(typeof(Character), "ApplyDamage")] private class ApplyDamagePatch { public static bool Prefix(Character __instance, ref HitData hit) { if (__instance.IsPlayer() && invincibility) { return false; } if (!__instance.IsPlayer() && !__instance.IsTamed() && invincibleEnemies) { return false; } return true; } } [HarmonyPatch(typeof(ZNet), "Update")] private class ZNetPatch { public static void Prefix(ZNet __instance) { znet = __instance; } } [HarmonyPatch(typeof(Chat), "Update")] private class ChatPatch { public static void Prefix(Chat __instance) { chat = __instance; } } [HarmonyPatch(typeof(EnvMan), "FixedUpdate")] private class EnvManPatch { public static void Prefix(EnvMan __instance) { envMan = __instance; } } private const string modGUID = "WarpWorld.CrowdControl"; private const string modName = "Crowd Control"; private const string modVersion = "2.0.1"; private readonly Harmony harmony = new Harmony("WarpWorld.CrowdControl"); public static ManualLogSource mls; internal static Mod Instance; private ControlClient client; public static Random rnd = new Random(); public static List<string> comments = new List<string>(); public static bool invincibility = false; public static bool invincibleEnemies = false; public static bool stamina = false; public static bool enemySpeed = false; public static bool enemySize = false; public static bool playerSize = false; public static bool playerSpeed = false; public static Player player = null; public static ZNet znet = null; public static Chat chat = null; public static EnvMan envMan = null; public static int speedDelay = 0; public static int sizeDelay = 0; public static int hitDelay = 0; public static float oldMaxStamina = 0f; public static float maxStamina = 0f; public static float[] playerSpeedValues = new float[14]; public static long playerID = 0L; public static List<Character> speedChangeEnemies = new List<Character>(); public static List<Character> sizeChangeEnemies = new List<Character>(); public static List<string> effectAuths = new List<string>(); private static bool _bootstrapped; private long _greetedServer; private float _greetedAt; private bool _toldServerUnmodded; private const float ServerReplyGrace = 10f; private static readonly Queue<string> PendingNotices = new Queue<string>(); private const float ServerHousekeepingInterval = 5f; private float _housekeeping; public static Queue<Action> ActionQueue = new Queue<Action>(); private void Awake() { Instance = this; mls = Logger.CreateLogSource("Crowd Control"); mls.LogInfo((object)"Loaded WarpWorld.CrowdControl. Patching."); harmony.PatchAll(typeof(Mod)); harmony.PatchAll(); if (ServerMode.IsDedicatedServer) { mls.LogInfo((object)"Crowd Control: dedicated server detected; the mod holds its own connection"); } else { try { client = ControlClient.Instance; new Thread(client.NetworkLoop).Start(); new Thread(client.RequestLoop).Start(); mls.LogInfo((object)"Crowd Control Initialized"); } catch (Exception arg) { mls.LogInfo((object)$"CC Init Error: {arg}"); } } mls = ((BaseUnityPlugin)this).Logger; } private void Bootstrap() { if (_bootstrapped || (Object)(object)ZNet.instance == (Object)null) { return; } if (ServerMode.IsDedicatedServer) { ServerMode.Start(); if (ZRoutedRpc.instance != null) { _bootstrapped = true; } return; } CCNet.Register(); if (ZRoutedRpc.instance != null) { CCNet.LocalExecutor = RunEffectLocally; CCNet.LocalNotice = ShowLocalNotice; CCNet.LocalApplyScale = ApplyRemoteScale; CCNet.LocalApplyEnemyScale = ApplyRemoteEnemyScale; _bootstrapped = true; } } private void AnnounceToServer() { ZNetPeer val; try { ZNet instance = ZNet.instance; val = ((instance != null) ? instance.GetServerPeer() : null); } catch { return; } if (val == null) { _greetedServer = 0L; CCNet.ForgetServer(); } else if (_greetedServer != val.m_uid) { _greetedServer = val.m_uid; _greetedAt = Time.realtimeSinceStartup; _toldServerUnmodded = false; CCNet.ForgetServer(); CCNet.SayHello(); } else if (!_toldServerUnmodded && !CCNet.ServerAnswered && !(Time.realtimeSinceStartup - _greetedAt < 10f)) { _toldServerUnmodded = true; ShowLocalNotice("Crowd Control server mod not available."); } } private static (string status, string message) RunEffectLocally(string code, uint id, string viewer) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (!ControlClient.Delegate.TryGetValue(code, out EffectDelegate value)) { return (status: "unavailable", message: "Unknown effect code: " + code); } if (!ControlClient.Instance.isReady()) { return (status: "retry", message: "Not ready."); } EffectRequest req = new EffectRequest { code = code, id = id, viewer = viewer }; lock (effectAuths) { effectAuths.Add(code); } try { return Interpret(value(ControlClient.Instance, req)); } finally { lock (effectAuths) { effectAuths.Remove(code); } } } private static (string status, string message) Interpret(EffectResponse res) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (res == null) { return (status: "retry", message: ""); } return (status: ((int)res.status == 0) ? "success" : "retry", message: res.message ?? ""); } private static void ShowLocalNotice(string message) { if (string.IsNullOrEmpty(message)) { return; } lock (PendingNotices) { PendingNotices.Enqueue(message); while (PendingNotices.Count > 8) { PendingNotices.Dequeue(); } } } private static void ApplyRemoteScale(long playerId, float scale) { ActionQueue.Enqueue(delegate { //IL_002f: Unknown result type (might be due to invalid IL or missing references) try { Player val = Player.GetPlayer(playerId); if (!((Object)(object)val == (Object)null)) { ((Component)val).transform.localScale = new Vector3(scale, scale, scale); } } catch (Exception ex) { mls.LogInfo((object)("Crowd Control: could not resize player: " + ex.Message)); } }); } private static void ApplyRemoteEnemyScale(ZDOID id, float factor) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) ActionQueue.Enqueue(delegate { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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) try { ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(id) : null); if (!((Object)(object)val == (Object)null)) { Transform transform = val.transform; transform.localScale *= factor; } } catch (Exception ex) { mls.LogInfo((object)("Crowd Control: could not resize creature: " + ex.Message)); } }); } private static void FlushNotices() { lock (PendingNotices) { if (PendingNotices.Count == 0) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } while (PendingNotices.Count > 0) { string text = PendingNotices.Dequeue(); try { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } catch (Exception arg) { mls.LogInfo((object)$"Crowd Control: could not show notice: {arg}"); } } } } private void Update() { Bootstrap(); if (_bootstrapped && !ServerMode.IsDedicatedServer) { AnnounceToServer(); FlushNotices(); Gifts.VerifyItems(); } if (_bootstrapped && ServerMode.IsDedicatedServer) { Gifts.VerifyItems(); StreamerLink.Tick(Time.deltaTime); _housekeeping += Time.deltaTime; if (_housekeeping >= 5f) { _housekeeping = 0f; ServerMode.ReconcilePeers(); ServerMode.ExpirePending(TimeSpan.FromSeconds(30.0)); } } if (ActionQueue.Count > 0) { ActionQueue.Dequeue()(); } lock (TimedThread.threads) { foreach (TimedThread thread in TimedThread.threads) { if (!thread.paused) { thread.effect.tick(); } } } } private void FixedUpdate() { client?.FixedUpdate(); } public static float randomVector3Float() { float num = (float)rnd.Next(0, 11) / 10f; if (rnd.Next(0, 2) == 1) { num -= 1f; } return num; } public static float randomFloat() { return (float)rnd.Next(0, 11) / 10f; } public static bool PlayerIsHost() { return ZNet.instance.GetServerPeer() == null; } } public enum TimedType { INVINCIBILITY, OHKO, INFINITESTAMINA, NOSTAMINA, GIANTPLAYER, TINYPLAYER, FASTPLAYER, SLOWPLAYER, FASTENEMIES, SLOWENEMIES, GIANTENEMIES, TINYENEMIES } public class Timed { public TimedType type; private static int frames; public Timed(TimedType t) { type = t; } public void addEffect() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) switch (type) { case TimedType.INVINCIBILITY: Mod.invincibility = true; break; case TimedType.INFINITESTAMINA: Mod.oldMaxStamina = ((Character)Player.m_localPlayer).GetMaxStamina(); break; case TimedType.GIANTPLAYER: ((Character)Player.m_localPlayer).GetTransform().localScale = new Vector3(3f, 3f, 3f); CCNet.ReportScale(Player.m_localPlayer.GetPlayerID(), 3f); break; case TimedType.TINYPLAYER: ((Character)Player.m_localPlayer).GetTransform().localScale = new Vector3(0.3f, 0.3f, 0.3f); CCNet.ReportScale(Player.m_localPlayer.GetPlayerID(), 0.3f); break; case TimedType.FASTPLAYER: { Mod.playerSpeedValues[0] = ((Character)Player.m_localPlayer).m_crouchSpeed; Mod.playerSpeedValues[1] = ((Character)Player.m_localPlayer).m_walkSpeed; Mod.playerSpeedValues[2] = ((Character)Player.m_localPlayer).m_speed; Mod.playerSpeedValues[3] = ((Character)Player.m_localPlayer).m_turnSpeed; Mod.playerSpeedValues[4] = ((Character)Player.m_localPlayer).m_runSpeed; Mod.playerSpeedValues[5] = ((Character)Player.m_localPlayer).m_runTurnSpeed; Mod.playerSpeedValues[6] = ((Character)Player.m_localPlayer).m_flySlowSpeed; Mod.playerSpeedValues[7] = ((Character)Player.m_localPlayer).m_flyFastSpeed; Mod.playerSpeedValues[8] = ((Character)Player.m_localPlayer).m_flyTurnSpeed; Mod.playerSpeedValues[9] = ((Character)Player.m_localPlayer).m_acceleration; Mod.playerSpeedValues[10] = ((Character)Player.m_localPlayer).m_airControl; Mod.playerSpeedValues[11] = ((Character)Player.m_localPlayer).m_swimSpeed; Mod.playerSpeedValues[12] = ((Character)Player.m_localPlayer).m_swimTurnSpeed; Mod.playerSpeedValues[13] = ((Character)Player.m_localPlayer).m_swimAcceleration; Player localPlayer15 = Player.m_localPlayer; ((Character)localPlayer15).m_crouchSpeed = ((Character)localPlayer15).m_crouchSpeed * 3f; Player localPlayer16 = Player.m_localPlayer; ((Character)localPlayer16).m_walkSpeed = ((Character)localPlayer16).m_walkSpeed * 3f; Player localPlayer17 = Player.m_localPlayer; ((Character)localPlayer17).m_speed = ((Character)localPlayer17).m_speed * 3f; Player localPlayer18 = Player.m_localPlayer; ((Character)localPlayer18).m_turnSpeed = ((Character)localPlayer18).m_turnSpeed * 3f; Player localPlayer19 = Player.m_localPlayer; ((Character)localPlayer19).m_runSpeed = ((Character)localPlayer19).m_runSpeed * 3f; Player localPlayer20 = Player.m_localPlayer; ((Character)localPlayer20).m_runTurnSpeed = ((Character)localPlayer20).m_runTurnSpeed * 3f; Player localPlayer21 = Player.m_localPlayer; ((Character)localPlayer21).m_flySlowSpeed = ((Character)localPlayer21).m_flySlowSpeed * 3f; Player localPlayer22 = Player.m_localPlayer; ((Character)localPlayer22).m_flyFastSpeed = ((Character)localPlayer22).m_flyFastSpeed * 3f; Player localPlayer23 = Player.m_localPlayer; ((Character)localPlayer23).m_flyTurnSpeed = ((Character)localPlayer23).m_flyTurnSpeed * 3f; Player localPlayer24 = Player.m_localPlayer; ((Character)localPlayer24).m_acceleration = ((Character)localPlayer24).m_acceleration * 3f; Player localPlayer25 = Player.m_localPlayer; ((Character)localPlayer25).m_airControl = ((Character)localPlayer25).m_airControl * 3f; Player localPlayer26 = Player.m_localPlayer; ((Character)localPlayer26).m_swimSpeed = ((Character)localPlayer26).m_swimSpeed * 3f; Player localPlayer27 = Player.m_localPlayer; ((Character)localPlayer27).m_swimTurnSpeed = ((Character)localPlayer27).m_swimTurnSpeed * 3f; Player localPlayer28 = Player.m_localPlayer; ((Character)localPlayer28).m_swimAcceleration = ((Character)localPlayer28).m_swimAcceleration * 3f; break; } case TimedType.SLOWPLAYER: { Mod.playerSpeedValues[0] = ((Character)Player.m_localPlayer).m_crouchSpeed; Mod.playerSpeedValues[1] = ((Character)Player.m_localPlayer).m_walkSpeed; Mod.playerSpeedValues[2] = ((Character)Player.m_localPlayer).m_speed; Mod.playerSpeedValues[3] = ((Character)Player.m_localPlayer).m_turnSpeed; Mod.playerSpeedValues[4] = ((Character)Player.m_localPlayer).m_runSpeed; Mod.playerSpeedValues[5] = ((Character)Player.m_localPlayer).m_runTurnSpeed; Mod.playerSpeedValues[6] = ((Character)Player.m_localPlayer).m_flySlowSpeed; Mod.playerSpeedValues[7] = ((Character)Player.m_localPlayer).m_flyFastSpeed; Mod.playerSpeedValues[8] = ((Character)Player.m_localPlayer).m_flyTurnSpeed; Mod.playerSpeedValues[9] = ((Character)Player.m_localPlayer).m_acceleration; Mod.playerSpeedValues[10] = ((Character)Player.m_localPlayer).m_airControl; Mod.playerSpeedValues[11] = ((Character)Player.m_localPlayer).m_swimSpeed; Mod.playerSpeedValues[12] = ((Character)Player.m_localPlayer).m_swimTurnSpeed; Mod.playerSpeedValues[13] = ((Character)Player.m_localPlayer).m_swimAcceleration; Player localPlayer = Player.m_localPlayer; ((Character)localPlayer).m_crouchSpeed = ((Character)localPlayer).m_crouchSpeed / 2f; Player localPlayer2 = Player.m_localPlayer; ((Character)localPlayer2).m_walkSpeed = ((Character)localPlayer2).m_walkSpeed / 2f; Player localPlayer3 = Player.m_localPlayer; ((Character)localPlayer3).m_speed = ((Character)localPlayer3).m_speed / 2f; Player localPlayer4 = Player.m_localPlayer; ((Character)localPlayer4).m_turnSpeed = ((Character)localPlayer4).m_turnSpeed / 2f; Player localPlayer5 = Player.m_localPlayer; ((Character)localPlayer5).m_runSpeed = ((Character)localPlayer5).m_runSpeed / 2f; Player localPlayer6 = Player.m_localPlayer; ((Character)localPlayer6).m_runTurnSpeed = ((Character)localPlayer6).m_runTurnSpeed / 2f; Player localPlayer7 = Player.m_localPlayer; ((Character)localPlayer7).m_flySlowSpeed = ((Character)localPlayer7).m_flySlowSpeed / 2f; Player localPlayer8 = Player.m_localPlayer; ((Character)localPlayer8).m_flyFastSpeed = ((Character)localPlayer8).m_flyFastSpeed / 2f; Player localPlayer9 = Player.m_localPlayer; ((Character)localPlayer9).m_flyTurnSpeed = ((Character)localPlayer9).m_flyTurnSpeed / 2f; Player localPlayer10 = Player.m_localPlayer; ((Character)localPlayer10).m_acceleration = ((Character)localPlayer10).m_acceleration / 2f; Player localPlayer11 = Player.m_localPlayer; ((Character)localPlayer11).m_airControl = ((Character)localPlayer11).m_airControl / 2f; Player localPlayer12 = Player.m_localPlayer; ((Character)localPlayer12).m_swimSpeed = ((Character)localPlayer12).m_swimSpeed / 2f; Player localPlayer13 = Player.m_localPlayer; ((Character)localPlayer13).m_swimTurnSpeed = ((Character)localPlayer13).m_swimTurnSpeed / 2f; Player localPlayer14 = Player.m_localPlayer; ((Character)localPlayer14).m_swimAcceleration = ((Character)localPlayer14).m_swimAcceleration / 2f; break; } case TimedType.OHKO: case TimedType.NOSTAMINA: break; } } public void removeEffect() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Unknown result type (might be due to invalid IL or missing references) switch (type) { case TimedType.INVINCIBILITY: Mod.invincibility = false; break; case TimedType.NOSTAMINA: Player.m_localPlayer.SetMaxStamina(Mod.oldMaxStamina, true); break; case TimedType.GIANTPLAYER: ((Component)Player.m_localPlayer).transform.localScale = new Vector3(1f, 1f, 1f); CCNet.ReportScale(Player.m_localPlayer.GetPlayerID(), 1f); break; case TimedType.TINYPLAYER: ((Component)Player.m_localPlayer).transform.localScale = new Vector3(1f, 1f, 1f); CCNet.ReportScale(Player.m_localPlayer.GetPlayerID(), 1f); break; case TimedType.FASTPLAYER: ((Character)Player.m_localPlayer).m_crouchSpeed = Mod.playerSpeedValues[0]; ((Character)Player.m_localPlayer).m_walkSpeed = Mod.playerSpeedValues[1]; ((Character)Player.m_localPlayer).m_speed = Mod.playerSpeedValues[2]; ((Character)Player.m_localPlayer).m_turnSpeed = Mod.playerSpeedValues[3]; ((Character)Player.m_localPlayer).m_runSpeed = Mod.playerSpeedValues[4]; ((Character)Player.m_localPlayer).m_runTurnSpeed = Mod.playerSpeedValues[5]; ((Character)Player.m_localPlayer).m_flySlowSpeed = Mod.playerSpeedValues[6]; ((Character)Player.m_localPlayer).m_flyFastSpeed = Mod.playerSpeedValues[7]; ((Character)Player.m_localPlayer).m_flyTurnSpeed = Mod.playerSpeedValues[8]; ((Character)Player.m_localPlayer).m_acceleration = Mod.playerSpeedValues[9]; ((Character)Player.m_localPlayer).m_airControl = Mod.playerSpeedValues[10]; ((Character)Player.m_localPlayer).m_swimSpeed = Mod.playerSpeedValues[11]; ((Character)Player.m_localPlayer).m_swimTurnSpeed = Mod.playerSpeedValues[12]; ((Character)Player.m_localPlayer).m_swimAcceleration = Mod.playerSpeedValues[13]; break; case TimedType.SLOWPLAYER: ((Character)Player.m_localPlayer).m_crouchSpeed = Mod.playerSpeedValues[0]; ((Character)Player.m_localPlayer).m_walkSpeed = Mod.playerSpeedValues[1]; ((Character)Player.m_localPlayer).m_speed = Mod.playerSpeedValues[2]; ((Character)Player.m_localPlayer).m_turnSpeed = Mod.playerSpeedValues[3]; ((Character)Player.m_localPlayer).m_runSpeed = Mod.playerSpeedValues[4]; ((Character)Player.m_localPlayer).m_runTurnSpeed = Mod.playerSpeedValues[5]; ((Character)Player.m_localPlayer).m_flySlowSpeed = Mod.playerSpeedValues[6]; ((Character)Player.m_localPlayer).m_flyFastSpeed = Mod.playerSpeedValues[7]; ((Character)Player.m_localPlayer).m_flyTurnSpeed = Mod.playerSpeedValues[8]; ((Character)Player.m_localPlayer).m_acceleration = Mod.playerSpeedValues[9]; ((Character)Player.m_localPlayer).m_airControl = Mod.playerSpeedValues[10]; ((Character)Player.m_localPlayer).m_swimSpeed = Mod.playerSpeedValues[11]; ((Character)Player.m_localPlayer).m_swimTurnSpeed = Mod.playerSpeedValues[12]; ((Character)Player.m_localPlayer).m_swimAcceleration = Mod.playerSpeedValues[13]; break; case TimedType.FASTENEMIES: foreach (Character speedChangeEnemy in Mod.speedChangeEnemies) { if ((Object)(object)speedChangeEnemy != (Object)null) { speedChangeEnemy.m_crouchSpeed /= 3f; speedChangeEnemy.m_walkSpeed /= 3f; speedChangeEnemy.m_speed /= 3f; speedChangeEnemy.m_turnSpeed /= 3f; speedChangeEnemy.m_runSpeed /= 3f; speedChangeEnemy.m_runTurnSpeed /= 3f; speedChangeEnemy.m_flySlowSpeed /= 3f; speedChangeEnemy.m_flyFastSpeed /= 3f; speedChangeEnemy.m_flyTurnSpeed /= 3f; speedChangeEnemy.m_acceleration /= 3f; speedChangeEnemy.m_jumpForce /= 3f; speedChangeEnemy.m_airControl /= 3f; speedChangeEnemy.m_swimSpeed /= 3f; speedChangeEnemy.m_swimTurnSpeed /= 3f; speedChangeEnemy.m_swimAcceleration /= 3f; } } Mod.speedChangeEnemies.Clear(); break; case TimedType.SLOWENEMIES: foreach (Character speedChangeEnemy2 in Mod.speedChangeEnemies) { if ((Object)(object)speedChangeEnemy2 != (Object)null) { speedChangeEnemy2.m_crouchSpeed *= 2f; speedChangeEnemy2.m_walkSpeed *= 2f; speedChangeEnemy2.m_speed *= 2f; speedChangeEnemy2.m_turnSpeed *= 2f; speedChangeEnemy2.m_runSpeed *= 2f; speedChangeEnemy2.m_runTurnSpeed *= 2f; speedChangeEnemy2.m_flySlowSpeed *= 2f; speedChangeEnemy2.m_flyFastSpeed *= 2f; speedChangeEnemy2.m_flyTurnSpeed *= 2f; speedChangeEnemy2.m_acceleration *= 2f; speedChangeEnemy2.m_jumpForce *= 2f; speedChangeEnemy2.m_airControl *= 2f; speedChangeEnemy2.m_swimSpeed *= 2f; speedChangeEnemy2.m_swimTurnSpeed *= 2f; speedChangeEnemy2.m_swimAcceleration *= 2f; } } Mod.speedChangeEnemies.Clear(); break; case TimedType.GIANTENEMIES: foreach (Character speedChangeEnemy3 in Mod.speedChangeEnemies) { if ((Object)(object)speedChangeEnemy3 != (Object)null) { Transform transform2 = speedChangeEnemy3.GetTransform(); transform2.localScale /= 3f; TimedThread.ReportEnemyScale(speedChangeEnemy3, 1f / 3f); } } Mod.sizeChangeEnemies.Clear(); break; case TimedType.TINYENEMIES: foreach (Character speedChangeEnemy4 in Mod.speedChangeEnemies) { if ((Object)(object)speedChangeEnemy4 != (Object)null) { Transform transform = speedChangeEnemy4.GetTransform(); transform.localScale *= 3f; TimedThread.ReportEnemyScale(speedChangeEnemy4, 3f); } } Mod.sizeChangeEnemies.Clear(); break; case TimedType.OHKO: case TimedType.INFINITESTAMINA: break; } } public void tick() { //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Invalid comparison between Unknown and I4 //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Invalid comparison between Unknown and I4 //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Invalid comparison between Unknown and I4 //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) frames++; switch (type) { case TimedType.OHKO: ((Character)Player.m_localPlayer).SetHealth(1f); break; case TimedType.INFINITESTAMINA: ((Character)Player.m_localPlayer).AddStamina(100f); break; case TimedType.NOSTAMINA: Player.m_localPlayer.SetMaxStamina(0f, false); break; case TimedType.FASTENEMIES: if (Mod.speedDelay == 50) { foreach (Character allCharacter in Character.GetAllCharacters()) { if (!allCharacter.IsPlayer() && !allCharacter.IsTamed() && (int)allCharacter.m_faction != 1 && !Mod.speedChangeEnemies.Contains(allCharacter)) { Mod.speedChangeEnemies.Add(allCharacter); allCharacter.m_crouchSpeed *= 3f; allCharacter.m_walkSpeed *= 3f; allCharacter.m_speed *= 3f; allCharacter.m_turnSpeed *= 3f; allCharacter.m_runSpeed *= 3f; allCharacter.m_runTurnSpeed *= 3f; allCharacter.m_flySlowSpeed *= 3f; allCharacter.m_flyFastSpeed *= 3f; allCharacter.m_flyTurnSpeed *= 3f; allCharacter.m_acceleration *= 3f; allCharacter.m_jumpForce *= 3f; allCharacter.m_airControl *= 3f; allCharacter.m_swimSpeed *= 3f; allCharacter.m_swimTurnSpeed *= 3f; allCharacter.m_swimAcceleration *= 3f; } } Mod.speedDelay = 0; } else { Mod.speedDelay++; } break; case TimedType.SLOWENEMIES: if (Mod.speedDelay == 50) { foreach (Character allCharacter2 in Character.GetAllCharacters()) { if (!allCharacter2.IsPlayer() && !allCharacter2.IsTamed(
BepInEx/plugins/Newtonsoft.Json.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; 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.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; 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 System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("13.0.3.27908")] [assembly: AssemblyInformationalVersion("13.0.3+0a2e291c0d9c0c7675d445703e51750363a549ef")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET 4.5")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : 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; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; Volatile.Write(ref _mask, num); } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } public class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDef
BepInEx/plugins/websocket-sharp-customheaders.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using System.Timers; using WebSocketSharp.CustomHeaders.Net; using WebSocketSharp.CustomHeaders.Net.WebSockets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("sta")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("sta.blockhead")] [assembly: AssemblyDescription("websocket-sharp provides the WebSocket protocol client and server.\r\n\r\nIt supports:\r\n- RFC 6455\r\n- WebSocket Client and Server\r\n- Per-message Compression extension\r\n- Secure Connection\r\n- HTTP Authentication (Basic/Digest)\r\n- Query String, Origin header and Cookies\r\n- Connecting through the HTTP Proxy server\r\n- .NET 3.5 or later (includes compatible)\r\n-CustomHeaders")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+98e58b2626fc27c5d5bb2c5987f5c46aedf9c1b6")] [assembly: AssemblyProduct("websocket-sharp-customheaders")] [assembly: AssemblyTitle("websocket-sharp-customheaders")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/qidong5566/websocket-sharp-customheaders")] [assembly: AssemblyVersion("1.0.3.0")] namespace WebSocketSharp.CustomHeaders { public enum ByteOrder { Little, Big } public class CloseEventArgs : EventArgs { private bool _clean; private PayloadData _payloadData; internal PayloadData PayloadData => _payloadData; public ushort Code => _payloadData.Code; public string Reason => _payloadData.Reason ?? string.Empty; public bool WasClean { get { return _clean; } internal set { _clean = value; } } internal CloseEventArgs() { _payloadData = PayloadData.Empty; } internal CloseEventArgs(ushort code) : this(code, null) { } internal CloseEventArgs(CloseStatusCode code) : this((ushort)code, null) { } internal CloseEventArgs(PayloadData payloadData) { _payloadData = payloadData; } internal CloseEventArgs(ushort code, string reason) { _payloadData = new PayloadData(code, reason); } internal CloseEventArgs(CloseStatusCode code, string reason) : this((ushort)code, reason) { } } public enum CloseStatusCode : ushort { Normal = 1000, Away = 1001, ProtocolError = 1002, UnsupportedData = 1003, Undefined = 1004, NoStatus = 1005, Abnormal = 1006, InvalidData = 1007, PolicyViolation = 1008, TooBig = 1009, MandatoryExtension = 1010, ServerError = 1011, TlsHandshakeFailure = 1015 } public enum CompressionMethod : byte { None, Deflate } public class ErrorEventArgs : EventArgs { private Exception _exception; private string _message; public Exception Exception => _exception; public string Message => _message; internal ErrorEventArgs(string message) : this(message, null) { } internal ErrorEventArgs(string message, Exception exception) { _message = message; _exception = exception; } } public static class Ext { private static readonly byte[] _last = new byte[1]; private static readonly int _retry = 5; private const string _tspecials = "()<>@,;:\\\"/[]?={} \t"; private static byte[] compress(this byte[] data) { if (data.LongLength == 0L) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.compressToArray(); } private static MemoryStream compress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0L) { return memoryStream; } stream.Position = 0L; using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, leaveOpen: true); stream.CopyTo(deflateStream, 1024); deflateStream.Close(); memoryStream.Write(_last, 0, 1); memoryStream.Position = 0L; return memoryStream; } private static byte[] compressToArray(this Stream stream) { using MemoryStream memoryStream = stream.compress(); memoryStream.Close(); return memoryStream.ToArray(); } private static byte[] decompress(this byte[] data) { if (data.LongLength == 0L) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.decompressToArray(); } private static MemoryStream decompress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0L) { return memoryStream; } stream.Position = 0L; using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true); deflateStream.CopyTo(memoryStream, 1024); memoryStream.Position = 0L; return memoryStream; } private static byte[] decompressToArray(this Stream stream) { using MemoryStream memoryStream = stream.decompress(); memoryStream.Close(); return memoryStream.ToArray(); } private static void times(this ulong n, Action action) { for (ulong num = 0uL; num < n; num++) { action(); } } internal static byte[] Append(this ushort code, string reason) { byte[] array = code.InternalToByteArray(ByteOrder.Big); if (reason != null && reason.Length > 0) { List<byte> list = new List<byte>(array); list.AddRange(Encoding.UTF8.GetBytes(reason)); array = list.ToArray(); } return array; } internal static void Close(this WebSocketSharp.CustomHeaders.Net.HttpListenerResponse response, WebSocketSharp.CustomHeaders.Net.HttpStatusCode code) { response.StatusCode = (int)code; response.OutputStream.Close(); } internal static void CloseWithAuthChallenge(this WebSocketSharp.CustomHeaders.Net.HttpListenerResponse response, string challenge) { response.Headers.InternalSet("WWW-Authenticate", challenge, response: true); response.Close(WebSocketSharp.CustomHeaders.Net.HttpStatusCode.Unauthorized); } internal static byte[] Compress(this byte[] data, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return data; } return data.compress(); } internal static Stream Compress(this Stream stream, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return stream; } return stream.compress(); } internal static byte[] CompressToArray(this Stream stream, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return stream.ToByteArray(); } return stream.compressToArray(); } internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition) { foreach (T item in source) { if (condition(item)) { return true; } } return false; } internal static bool ContainsTwice(this string[] values) { int len = values.Length; int end = len - 1; Func<int, bool> seek = null; seek = delegate(int idx) { if (idx == end) { return false; } string text = values[idx]; for (int i = idx + 1; i < len; i++) { if (values[i] == text) { return true; } } return seek(++idx); }; return seek(0); } internal static T[] Copy<T>(this T[] source, int length) { T[] array = new T[length]; Array.Copy(source, 0, array, 0, length); return array; } internal static T[] Copy<T>(this T[] source, long length) { T[] array = new T[length]; Array.Copy(source, 0L, array, 0L, length); return array; } internal static void CopyTo(this Stream source, Stream destination, int bufferLength) { byte[] buffer = new byte[bufferLength]; int num = 0; while ((num = source.Read(buffer, 0, bufferLength)) > 0) { destination.Write(buffer, 0, num); } } internal static void CopyToAsync(this Stream source, Stream destination, int bufferLength, Action completed, Action<Exception> error) { byte[] buff = new byte[bufferLength]; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = source.EndRead(ar); if (num <= 0) { if (completed != null) { completed(); } } else { destination.Write(buff, 0, num); source.BeginRead(buff, 0, bufferLength, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { source.BeginRead(buff, 0, bufferLength, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static byte[] Decompress(this byte[] data, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return data; } return data.decompress(); } internal static Stream Decompress(this Stream stream, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return stream; } return stream.decompress(); } internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method) { if (method != CompressionMethod.Deflate) { return stream.ToByteArray(); } return stream.decompressToArray(); } internal static bool EqualsWith(this int value, char c, Action<int> action) { action(value); return value == c; } internal static string GetAbsolutePath(this Uri uri) { if (uri.IsAbsoluteUri) { return uri.AbsolutePath; } string originalString = uri.OriginalString; if (originalString[0] != '/') { return null; } int num = originalString.IndexOfAny(new char[2] { '?', '#' }); if (num <= 0) { return originalString; } return originalString.Substring(0, num); } internal static string GetDnsSafeHost(this Uri uri, bool bracketIPv6) { if (!bracketIPv6 || uri.HostNameType != UriHostNameType.IPv6) { return uri.DnsSafeHost; } return uri.Host; } internal static string GetMessage(this CloseStatusCode code) { return code switch { CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.", CloseStatusCode.ServerError => "WebSocket server got an internal error.", CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).", CloseStatusCode.TooBig => "A too big message has been received.", CloseStatusCode.PolicyViolation => "A policy violation has occurred.", CloseStatusCode.InvalidData => "Invalid data has been received.", CloseStatusCode.Abnormal => "An exception has occurred.", CloseStatusCode.UnsupportedData => "Unsupported data has been received.", CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.", _ => string.Empty, }; } internal static string GetName(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); if (num <= 0) { return null; } return nameAndValue.Substring(0, num).Trim(); } internal static string GetValue(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); if (num <= -1 || num >= nameAndValue.Length - 1) { return null; } return nameAndValue.Substring(num + 1).Trim(); } internal static string GetValue(this string nameAndValue, char separator, bool unquote) { int num = nameAndValue.IndexOf(separator); if (num < 0 || num == nameAndValue.Length - 1) { return null; } string text = nameAndValue.Substring(num + 1).Trim(); if (!unquote) { return text; } return text.Unquote(); } internal static byte[] InternalToByteArray(this ushort value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static byte[] InternalToByteArray(this ulong value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static bool IsCompressionExtension(this string value, CompressionMethod method) { return value.StartsWith(method.ToExtensionString()); } internal static bool IsControl(this byte opcode) { if (opcode > 7) { return opcode < 16; } return false; } internal static bool IsControl(this Opcode opcode) { return (int)opcode >= 8; } internal static bool IsData(this byte opcode) { if (opcode != 1) { return opcode == 2; } return true; } internal static bool IsData(this Opcode opcode) { if (opcode != Opcode.Text) { return opcode == Opcode.Binary; } return true; } internal static bool IsPortNumber(this int value) { if (value > 0) { return value < 65536; } return false; } internal static bool IsReserved(this ushort code) { if (code != 1004 && code != 1005 && code != 1006) { return code == 1015; } return true; } internal static bool IsReserved(this CloseStatusCode code) { if (code != CloseStatusCode.Undefined && code != CloseStatusCode.NoStatus && code != CloseStatusCode.Abnormal) { return code == CloseStatusCode.TlsHandshakeFailure; } return true; } internal static bool IsSupported(this byte opcode) { return Enum.IsDefined(typeof(Opcode), opcode); } internal static bool IsText(this string value) { int length = value.Length; for (int i = 0; i < length; i++) { char c = value[i]; if (c < ' ') { if (!Contains("\r\n\t", c)) { return false; } if (c == '\n') { i++; if (i == length) { break; } c = value[i]; if (!Contains(" \t", c)) { return false; } } } else if (c == '\u007f') { return false; } } return true; } internal static bool IsToken(this string value) { foreach (char c in value) { if (c < ' ') { return false; } if (c >= '\u007f') { return false; } if (Contains("()<>@,;:\\\"/[]?={} \t", c)) { return false; } } return true; } internal static string Quote(this string value) { return string.Format("\"{0}\"", value.Replace("\"", "\\\"")); } internal static byte[] ReadBytes(this Stream stream, int length) { byte[] array = new byte[length]; int num = 0; try { int num2 = 0; while (length > 0) { num2 = stream.Read(array, num, length); if (num2 != 0) { num += num2; length -= num2; continue; } break; } } catch { } return array.SubArray(0, num); } internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(); try { byte[] buffer = new byte[bufferLength]; int num = 0; while (length > 0) { if (length < bufferLength) { bufferLength = (int)length; } num = stream.Read(buffer, 0, bufferLength); if (num != 0) { memoryStream.Write(buffer, 0, num); length -= num; continue; } break; } } catch { } memoryStream.Close(); return memoryStream.ToArray(); } internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error) { byte[] buff = new byte[length]; int offset = 0; int retry = 0; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num == 0 && retry < _retry) { retry++; stream.BeginRead(buff, offset, length, callback, null); } else if (num == 0 || num == length) { if (completed != null) { completed(buff.SubArray(0, offset + num)); } } else { retry = 0; offset += num; length -= num; stream.BeginRead(buff, offset, length, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { stream.BeginRead(buff, offset, length, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static void ReadBytesAsync(this Stream stream, long length, int bufferLength, Action<byte[]> completed, Action<Exception> error) { MemoryStream dest = new MemoryStream(); byte[] buff = new byte[bufferLength]; int retry = 0; Action<long> read = null; read = delegate(long len) { if (len < bufferLength) { bufferLength = (int)len; } stream.BeginRead(buff, 0, bufferLength, delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num > 0) { dest.Write(buff, 0, num); } if (num == 0 && retry < _retry) { int num2 = retry; retry = num2 + 1; read(len); } else if (num == 0 || num == len) { if (completed != null) { dest.Close(); completed(dest.ToArray()); } dest.Dispose(); } else { retry = 0; read(len - num); } } catch (Exception obj2) { dest.Dispose(); if (error != null) { error(obj2); } } }, null); }; try { read(length); } catch (Exception obj) { dest.Dispose(); if (error != null) { error(obj); } } } internal static string RemovePrefix(this string value, params string[] prefixes) { int num = 0; foreach (string text in prefixes) { if (value.StartsWith(text)) { num = text.Length; break; } } if (num <= 0) { return value; } return value.Substring(num); } internal static T[] Reverse<T>(this T[] array) { int num = array.Length; T[] array2 = new T[num]; int num2 = num - 1; for (int i = 0; i <= num2; i++) { array2[i] = array[num2 - i]; } return array2; } internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators) { int len = value.Length; string seps = new string(separators); StringBuilder buff = new StringBuilder(32); bool escaped = false; bool quoted = false; for (int i = 0; i < len; i++) { char c = value[i]; switch (c) { case '"': if (escaped) { escaped = !escaped; } else { quoted = !quoted; } break; case '\\': if (i < len - 1 && value[i + 1] == '"') { escaped = true; } break; default: if (Contains(seps, c) && !quoted) { yield return buff.ToString(); buff.Length = 0; continue; } break; } buff.Append(c); } if (buff.Length > 0) { yield return buff.ToString(); } } internal static byte[] ToByteArray(this Stream stream) { using MemoryStream memoryStream = new MemoryStream(); stream.Position = 0L; stream.CopyTo(memoryStream, 1024); memoryStream.Close(); return memoryStream.ToArray(); } internal static CompressionMethod ToCompressionMethod(this string value) { foreach (CompressionMethod value2 in Enum.GetValues(typeof(CompressionMethod))) { if (value2.ToExtensionString() == value) { return value2; } } return CompressionMethod.None; } internal static string ToExtensionString(this CompressionMethod method, params string[] parameters) { if (method == CompressionMethod.None) { return string.Empty; } string text = $"permessage-{method.ToString().ToLower()}"; if (parameters == null || parameters.Length == 0) { return text; } return string.Format("{0}; {1}", text, parameters.ToString("; ")); } internal static IPAddress ToIPAddress(this string value) { if (value == null || value.Length == 0) { return null; } if (IPAddress.TryParse(value, out IPAddress address)) { return address; } try { return Dns.GetHostAddresses(value)[0]; } catch { return null; } } internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } internal static string ToString(this IPAddress address, bool bracketIPv6) { if (!bracketIPv6 || address.AddressFamily != AddressFamily.InterNetworkV6) { return address.ToString(); } return $"[{address.ToString()}]"; } internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0); } internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0); } internal static string TrimSlashFromEnd(this string value) { string text = value.TrimEnd(new char[1] { '/' }); if (text.Length <= 0) { return "/"; } return text; } internal static string TrimSlashOrBackslashFromEnd(this string value) { string text = value.TrimEnd('/', '\\'); if (text.Length <= 0) { return value[0].ToString(); } return text; } internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message) { result = null; message = null; Uri uri = uriString.ToUri(); if (uri == null) { message = "An invalid URI string."; return false; } if (!uri.IsAbsoluteUri) { message = "A relative URI."; return false; } string scheme = uri.Scheme; if (!(scheme == "ws") && !(scheme == "wss")) { message = "The scheme part is not 'ws' or 'wss'."; return false; } int port = uri.Port; if (port == 0) { message = "The port part is zero."; return false; } if (uri.Fragment.Length > 0) { message = "It includes the fragment component."; return false; } result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery))); return true; } internal static bool TryGetUTF8DecodedString(this byte[] bytes, out string s) { s = null; try { s = Encoding.UTF8.GetString(bytes); } catch { return false; } return true; } internal static bool TryGetUTF8EncodedBytes(this string s, out byte[] bytes) { bytes = null; try { bytes = Encoding.UTF8.GetBytes(s); } catch { return false; } return true; } internal static bool TryOpenRead(this FileInfo fileInfo, out FileStream fileStream) { fileStream = null; try { fileStream = fileInfo.OpenRead(); } catch { return false; } return true; } internal static string Unquote(this string value) { int num = value.IndexOf('"'); if (num < 0) { return value; } int num2 = value.LastIndexOf('"') - num - 1; if (num2 >= 0) { if (num2 != 0) { return value.Substring(num + 1, num2).Replace("\\\"", "\""); } return string.Empty; } return value; } internal static string UTF8Decode(this byte[] bytes) { try { return Encoding.UTF8.GetString(bytes); } catch { return null; } } internal static byte[] UTF8Encode(this string s) { return Encoding.UTF8.GetBytes(s); } internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(bytes); memoryStream.CopyTo(stream, bufferLength); } internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error) { MemoryStream input = new MemoryStream(bytes); input.CopyToAsync(stream, bufferLength, delegate { if (completed != null) { completed(); } input.Dispose(); }, delegate(Exception ex) { input.Dispose(); if (error != null) { error(ex); } }); } public static bool Contains(this string value, params char[] chars) { if (chars != null && chars.Length != 0) { if (value != null && value.Length != 0) { return value.IndexOfAny(chars) > -1; } return false; } return true; } public static bool Contains(this NameValueCollection collection, string name) { if (collection == null || collection.Count <= 0) { return false; } return collection[name] != null; } public static bool Contains(this NameValueCollection collection, string name, string value) { if (collection == null || collection.Count == 0) { return false; } string text = collection[name]; if (text == null) { return false; } string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { if (array[i].Trim().Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static void Emit(this EventHandler eventHandler, object sender, EventArgs e) { eventHandler?.Invoke(sender, e); } public static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs { eventHandler?.Invoke(sender, e); } public static WebSocketSharp.CustomHeaders.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response) { string name = (response ? "Set-Cookie" : "Cookie"); if (headers == null || !headers.Contains(name)) { return new WebSocketSharp.CustomHeaders.Net.CookieCollection(); } return WebSocketSharp.CustomHeaders.Net.CookieCollection.Parse(headers[name], response); } public static string GetDescription(this WebSocketSharp.CustomHeaders.Net.HttpStatusCode code) { return ((int)code).GetStatusDescription(); } public static string GetStatusDescription(this int code) { return code switch { 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-Uri Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "Http Version Not Supported", 507 => "Insufficient Storage", _ => string.Empty, }; } public static bool IsCloseStatusCode(this ushort value) { if (value > 999) { return value < 5000; } return false; } public static bool IsEnclosedIn(this string value, char c) { if (value != null && value.Length > 1 && value[0] == c) { return value[value.Length - 1] == c; } return false; } public static bool IsHostOrder(this ByteOrder order) { return BitConverter.IsLittleEndian == (order == ByteOrder.Little); } public static bool IsLocal(this IPAddress address) { if (address == null) { return false; } if (address.Equals(IPAddress.Any)) { return true; } if (address.Equals(IPAddress.Loopback)) { return true; } if (Socket.OSSupportsIPv6) { if (address.Equals(IPAddress.IPv6Any)) { return true; } if (address.Equals(IPAddress.IPv6Loopback)) { return true; } } IPAddress[] hostAddresses = Dns.GetHostAddresses(Dns.GetHostName()); foreach (IPAddress obj in hostAddresses) { if (address.Equals(obj)) { return true; } } return false; } public static bool IsNullOrEmpty(this string value) { if (value != null) { return value.Length == 0; } return true; } public static bool IsPredefinedScheme(this string value) { if (value == null || value.Length < 2) { return false; } switch (value[0]) { case 'h': if (!(value == "http")) { return value == "https"; } return true; case 'w': if (!(value == "ws")) { return value == "wss"; } return true; case 'f': if (!(value == "file")) { return value == "ftp"; } return true; case 'g': return value == "gopher"; case 'm': return value == "mailto"; case 'n': { char c = value[1]; if (c != 'e') { return value == "nntp"; } if (!(value == "news") && !(value == "net.pipe")) { return value == "net.tcp"; } return true; } default: return false; } } public static bool IsUpgradeTo(this WebSocketSharp.CustomHeaders.Net.HttpListenerRequest request, string protocol) { if (request == null) { throw new ArgumentNullException("request"); } if (protocol == null) { throw new ArgumentNullException("protocol"); } if (protocol.Length == 0) { throw new ArgumentException("An empty string.", "protocol"); } if (request.Headers.Contains("Upgrade", protocol)) { return request.Headers.Contains("Connection", "Upgrade"); } return false; } public static bool MaybeUri(this string value) { if (value == null || value.Length == 0) { return false; } int num = value.IndexOf(':'); if (num == -1) { return false; } if (num >= 10) { return false; } return value.Substring(0, num).IsPredefinedScheme(); } public static T[] SubArray<T>(this T[] array, int startIndex, int length) { int num; if (array == null || (num = array.Length) == 0) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > num) { return new T[0]; } if (startIndex == 0 && length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0, length); return array2; } public static T[] SubArray<T>(this T[] array, long startIndex, long length) { long num; if (array == null || (num = array.LongLength) == 0L) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > num) { return new T[0]; } if (startIndex == 0L && length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0L, length); return array2; } public static void Times(this int n, Action action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this long n, Action action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this uint n, Action action) { if (n != 0 && action != null) { times(n, action); } } public static void Times(this ulong n, Action action) { if (n != 0 && action != null) { n.times(action); } } public static void Times(this int n, Action<int> action) { if (n > 0 && action != null) { for (int i = 0; i < n; i++) { action(i); } } } public static void Times(this long n, Action<long> action) { if (n > 0 && action != null) { for (long num = 0L; num < n; num++) { action(num); } } } public static void Times(this uint n, Action<uint> action) { if (n != 0 && action != null) { for (uint num = 0u; num < n; num++) { action(num); } } } public static void Times(this ulong n, Action<ulong> action) { if (n != 0 && action != null) { for (ulong num = 0uL; num < n; num++) { action(num); } } } public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length == 0) { return default(T); } Type typeFromHandle = typeof(T); byte[] value = source.ToHostOrder(sourceOrder); if (!(typeFromHandle == typeof(bool))) { if (!(typeFromHandle == typeof(char))) { if (!(typeFromHandle == typeof(double))) { if (!(typeFromHandle == typeof(short))) { if (!(typeFromHandle == typeof(int))) { if (!(typeFromHandle == typeof(long))) { if (!(typeFromHandle == typeof(float))) { if (!(typeFromHandle == typeof(ushort))) { if (!(typeFromHandle == typeof(uint))) { if (!(typeFromHandle == typeof(ulong))) { return default(T); } return (T)(object)BitConverter.ToUInt64(value, 0); } return (T)(object)BitConverter.ToUInt32(value, 0); } return (T)(object)BitConverter.ToUInt16(value, 0); } return (T)(object)BitConverter.ToSingle(value, 0); } return (T)(object)BitConverter.ToInt64(value, 0); } return (T)(object)BitConverter.ToInt32(value, 0); } return (T)(object)BitConverter.ToInt16(value, 0); } return (T)(object)BitConverter.ToDouble(value, 0); } return (T)(object)BitConverter.ToChar(value, 0); } return (T)(object)BitConverter.ToBoolean(value, 0); } public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct { Type typeFromHandle = typeof(T); byte[] array = ((typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : ((!(typeFromHandle == typeof(byte))) ? ((typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : ((typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : ((typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : ((typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : ((typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : ((typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : ((typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : ((typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : ((typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : WebSocket.EmptyBytes))))))))) : new byte[1] { (byte)(object)value })); if (array.Length > 1 && !order.IsHostOrder()) { Array.Reverse((Array)array); } return array; } public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder) { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length <= 1 || sourceOrder.IsHostOrder()) { return source; } return source.Reverse(); } public static string ToString<T>(this T[] array, string separator) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { return string.Empty; } if (separator == null) { separator = string.Empty; } StringBuilder buff = new StringBuilder(64); (num - 1).Times(delegate(int i) { buff.AppendFormat("{0}{1}", array[i].ToString(), separator); }); buff.Append(array[num - 1].ToString()); return buff.ToString(); } public static Uri ToUri(this string value) { Uri.TryCreate(value, value.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result); return result; } public static string UrlDecode(this string value) { if (value == null || value.Length <= 0) { return value; } return HttpUtility.UrlDecode(value); } public static string UrlEncode(this string value) { if (value == null || value.Length <= 0) { return value; } return HttpUtility.UrlEncode(value); } public static void WriteContent(this WebSocketSharp.CustomHeaders.Net.HttpListenerResponse response, byte[] content) { if (response == null) { throw new ArgumentNullException("response"); } if (content == null) { throw new ArgumentNullException("content"); } long num = content.LongLength; if (num == 0L) { response.Close(); return; } response.ContentLength64 = num; Stream outputStream = response.OutputStream; if (num <= int.MaxValue) { outputStream.Write(content, 0, (int)num); } else { outputStream.WriteBytes(content, 1024); } outputStream.Close(); } } internal enum Fin : byte { More, Final } internal abstract class HttpBase { private NameValueCollection _headers; private const int _headersMaxLength = 8192; private Version _version; internal byte[] EntityBodyData; protected const string CrLf = "\r\n"; public string EntityBody { get { if (EntityBodyData == null || EntityBodyData.LongLength == 0L) { return string.Empty; } Encoding encoding = null; string text = _headers["Content-Type"]; if (text != null && text.Length > 0) { encoding = HttpUtility.GetEncoding(text); } return (encoding ?? Encoding.UTF8).GetString(EntityBodyData); } } public NameValueCollection Headers => _headers; public Version ProtocolVersion => _version; protected HttpBase(Version version, NameValueCollection headers) { _version = version; _headers = headers; } private static byte[] readEntityBody(Stream stream, string length) { if (!long.TryParse(length, out var result)) { throw new ArgumentException("Cannot be parsed.", "length"); } if (result < 0) { throw new ArgumentOutOfRangeException("length", "Less than zero."); } if (result <= 1024) { if (result <= 0) { return null; } return stream.ReadBytes((int)result); } return stream.ReadBytes(result, 1024); } private static string[] readHeaders(Stream stream, int maxLength) { List<byte> buff = new List<byte>(); int cnt = 0; Action<int> action = delegate(int i) { if (i == -1) { throw new EndOfStreamException("The header cannot be read from the data source."); } buff.Add((byte)i); cnt++; }; bool flag = false; while (cnt < maxLength) { if (stream.ReadByte().EqualsWith('\r', action) && stream.ReadByte().EqualsWith('\n', action) && stream.ReadByte().EqualsWith('\r', action) && stream.ReadByte().EqualsWith('\n', action)) { flag = true; break; } } if (!flag) { throw new WebSocketException("The length of header part is greater than the max length."); } return Encoding.UTF8.GetString(buff.ToArray()).Replace("\r\n ", " ").Replace("\r\n\t", " ") .Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); } protected static T Read<T>(Stream stream, Func<string[], T> parser, int millisecondsTimeout) where T : HttpBase { bool timeout = false; System.Threading.Timer timer = new System.Threading.Timer(delegate { timeout = true; stream.Close(); }, null, millisecondsTimeout, -1); T val = null; Exception ex = null; try { val = parser(readHeaders(stream, 8192)); string text = val.Headers["Content-Length"]; if (text != null && text.Length > 0) { val.EntityBodyData = readEntityBody(stream, text); } } catch (Exception ex2) { ex = ex2; } finally { timer.Change(-1, -1); timer.Dispose(); } string text2 = (timeout ? "A timeout has occurred while reading an HTTP request/response." : ((ex != null) ? "An exception has occurred while reading an HTTP request/response." : null)); if (text2 != null) { throw new WebSocketException(text2, ex); } return val; } public byte[] ToByteArray() { return Encoding.UTF8.GetBytes(ToString()); } } internal class HttpRequest : HttpBase { private string _method; private string _uri; private bool _websocketRequest; private bool _websocketRequestSet; public AuthenticationResponse AuthenticationResponse { get { string text = base.Headers["Authorization"]; if (text == null || text.Length <= 0) { return null; } return AuthenticationResponse.Parse(text); } } public WebSocketSharp.CustomHeaders.Net.CookieCollection Cookies => base.Headers.GetCookies(response: false); public string HttpMethod => _method; public bool IsWebSocketRequest { get { if (!_websocketRequestSet) { NameValueCollection headers = base.Headers; _websocketRequest = _method == "GET" && base.ProtocolVersion > WebSocketSharp.CustomHeaders.Net.HttpVersion.Version10 && headers.Contains("Upgrade", "websocket") && headers.Contains("Connection", "Upgrade"); _websocketRequestSet = true; } return _websocketRequest; } } public string RequestUri => _uri; private HttpRequest(string method, string uri, Version version, NameValueCollection headers) : base(version, headers) { _method = method; _uri = uri; } internal HttpRequest(string method, string uri) : this(method, uri, WebSocketSharp.CustomHeaders.Net.HttpVersion.Version11, new NameValueCollection()) { base.Headers["User-Agent"] = "websocket-sharp/1.0"; } internal static HttpRequest CreateConnectRequest(Uri uri) { string dnsSafeHost = uri.DnsSafeHost; int port = uri.Port; string text = $"{dnsSafeHost}:{port}"; HttpRequest httpRequest = new HttpRequest("CONNECT", text); httpRequest.Headers["Host"] = ((port == 80) ? dnsSafeHost : text); return httpRequest; } internal static HttpRequest CreateWebSocketRequest(Uri uri) { HttpRequest httpRequest = new HttpRequest("GET", uri.PathAndQuery); NameValueCollection headers = httpRequest.Headers; int port = uri.Port; string scheme = uri.Scheme; headers["Host"] = (((port == 80 && scheme == "ws") || (port == 443 && scheme == "wss")) ? uri.DnsSafeHost : uri.Authority); headers["Upgrade"] = "websocket"; headers["Connection"] = "Upgrade"; return httpRequest; } internal HttpResponse GetResponse(Stream stream, int millisecondsTimeout) { byte[] array = ToByteArray(); stream.Write(array, 0, array.Length); return HttpBase.Read(stream, HttpResponse.Parse, millisecondsTimeout); } internal static HttpRequest Parse(string[] headerParts) { string[] array = headerParts[0].Split(new char[1] { ' ' }, 3); if (array.Length != 3) { throw new ArgumentException("Invalid request line: " + headerParts[0]); } WebSocketSharp.CustomHeaders.Net.WebHeaderCollection webHeaderCollection = new WebSocketSharp.CustomHeaders.Net.WebHeaderCollection(); for (int i = 1; i < headerParts.Length; i++) { webHeaderCollection.InternalSet(headerParts[i], response: false); } return new HttpRequest(array[0], array[1], new Version(array[2].Substring(5)), webHeaderCollection); } internal static HttpRequest Read(Stream stream, int millisecondsTimeout) { return HttpBase.Read(stream, Parse, millisecondsTimeout); } public void SetCookies(WebSocketSharp.CustomHeaders.Net.CookieCollection cookies) { if (cookies == null || cookies.Count == 0) { return; } StringBuilder stringBuilder = new StringBuilder(64); foreach (WebSocketSharp.CustomHeaders.Net.Cookie item in cookies.Sorted) { if (!item.Expired) { stringBuilder.AppendFormat("{0}; ", item.ToString()); } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; base.Headers["Cookie"] = stringBuilder.ToString(); } } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(64); stringBuilder.AppendFormat("{0} {1} HTTP/{2}{3}", _method, _uri, base.ProtocolVersion, "\r\n"); NameValueCollection headers = base.Headers; string[] allKeys = headers.AllKeys; foreach (string text in allKeys) { stringBuilder.AppendFormat("{0}: {1}{2}", text, headers[text], "\r\n"); } stringBuilder.Append("\r\n"); string entityBody = base.EntityBody; if (entityBody.Length > 0) { stringBuilder.Append(entityBody); } return stringBuilder.ToString(); } } internal class HttpResponse : HttpBase { private string _code; private string _reason; public WebSocketSharp.CustomHeaders.Net.CookieCollection Cookies => base.Headers.GetCookies(response: true); public bool HasConnectionClose => base.Headers.Contains("Connection", "close"); public bool IsProxyAuthenticationRequired => _code == "407"; public bool IsRedirect { get { if (!(_code == "301")) { return _code == "302"; } return true; } } public bool IsUnauthorized => _code == "401"; public bool IsWebSocketResponse { get { NameValueCollection headers = base.Headers; if (base.ProtocolVersion > WebSocketSharp.CustomHeaders.Net.HttpVersion.Version10 && _code == "101" && headers.Contains("Upgrade", "websocket")) { return headers.Contains("Connection", "Upgrade"); } return false; } } public string Reason => _reason; public string StatusCode => _code; private HttpResponse(string code, string reason, Version version, NameValueCollection headers) : base(version, headers) { _code = code; _reason = reason; } internal HttpResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode code) : this(code, code.GetDescription()) { } internal HttpResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode code, string reason) : this(((int)code).ToString(), reason, WebSocketSharp.CustomHeaders.Net.HttpVersion.Version11, new NameValueCollection()) { base.Headers["Server"] = "websocket-sharp/1.0"; } internal static HttpResponse CreateCloseResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode code) { HttpResponse httpResponse = new HttpResponse(code); httpResponse.Headers["Connection"] = "close"; return httpResponse; } internal static HttpResponse CreateUnauthorizedResponse(string challenge) { HttpResponse httpResponse = new HttpResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode.Unauthorized); httpResponse.Headers["WWW-Authenticate"] = challenge; return httpResponse; } internal static HttpResponse CreateWebSocketResponse() { HttpResponse httpResponse = new HttpResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode.SwitchingProtocols); NameValueCollection headers = httpResponse.Headers; headers["Upgrade"] = "websocket"; headers["Connection"] = "Upgrade"; return httpResponse; } internal static HttpResponse Parse(string[] headerParts) { string[] array = headerParts[0].Split(new char[1] { ' ' }, 3); if (array.Length != 3) { throw new ArgumentException("Invalid status line: " + headerParts[0]); } WebSocketSharp.CustomHeaders.Net.WebHeaderCollection webHeaderCollection = new WebSocketSharp.CustomHeaders.Net.WebHeaderCollection(); for (int i = 1; i < headerParts.Length; i++) { webHeaderCollection.InternalSet(headerParts[i], response: true); } return new HttpResponse(array[1], array[2], new Version(array[0].Substring(5)), webHeaderCollection); } internal static HttpResponse Read(Stream stream, int millisecondsTimeout) { return HttpBase.Read(stream, Parse, millisecondsTimeout); } public void SetCookies(WebSocketSharp.CustomHeaders.Net.CookieCollection cookies) { if (cookies == null || cookies.Count == 0) { return; } NameValueCollection headers = base.Headers; foreach (WebSocketSharp.CustomHeaders.Net.Cookie item in cookies.Sorted) { headers.Add("Set-Cookie", item.ToResponseString()); } } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(64); stringBuilder.AppendFormat("HTTP/{0} {1} {2}{3}", base.ProtocolVersion, _code, _reason, "\r\n"); NameValueCollection headers = base.Headers; string[] allKeys = headers.AllKeys; foreach (string text in allKeys) { stringBuilder.AppendFormat("{0}: {1}{2}", text, headers[text], "\r\n"); } stringBuilder.Append("\r\n"); string entityBody = base.EntityBody; if (entityBody.Length > 0) { stringBuilder.Append(entityBody); } return stringBuilder.ToString(); } } public class LogData { private StackFrame _caller; private DateTime _date; private LogLevel _level; private string _message; public StackFrame Caller => _caller; public DateTime Date => _date; public LogLevel Level => _level; public string Message => _message; internal LogData(LogLevel level, StackFrame caller, string message) { _level = level; _caller = caller; _message = message ?? string.Empty; _date = DateTime.Now; } public override string ToString() { string text = $"{_date}|{_level,-5}|"; MethodBase method = _caller.GetMethod(); Type declaringType = method.DeclaringType; string arg = $"{text}{declaringType.Name}.{method.Name}|"; string[] array = _message.Replace("\r\n", "\n").TrimEnd(new char[1] { '\n' }).Split(new char[1] { '\n' }); if (array.Length <= 1) { return $"{arg}{_message}"; } StringBuilder stringBuilder = new StringBuilder($"{arg}{array[0]}\n", 64); string format = $"{{0,{text.Length}}}{{1}}\n"; for (int i = 1; i < array.Length; i++) { stringBuilder.AppendFormat(format, "", array[i]); } stringBuilder.Length--; return stringBuilder.ToString(); } } public class Logger { private volatile string _file; private volatile LogLevel _level; private Action<LogData, string> _output; private object _sync; public string File { get { return _file; } set { lock (_sync) { _file = value; Warn($"The current path to the log file has been changed to {_file}."); } } } public LogLevel Level { get { return _level; } set { lock (_sync) { _level = value; Warn($"The current logging level has been changed to {_level}."); } } } public Action<LogData, string> Output { get { return _output; } set { lock (_sync) { _output = value ?? new Action<LogData, string>(defaultOutput); Warn("The current output action has been changed."); } } } public Logger() : this(LogLevel.Error, null, null) { } public Logger(LogLevel level) : this(level, null, null) { } public Logger(LogLevel level, string file, Action<LogData, string> output) { _level = level; _file = file; _output = output ?? new Action<LogData, string>(defaultOutput); _sync = new object(); } private static void defaultOutput(LogData data, string path) { string value = data.ToString(); Console.WriteLine(value); if (path != null && path.Length > 0) { writeToFile(value, path); } } private void output(string message, LogLevel level) { lock (_sync) { if (_level > level) { return; } LogData logData = null; try { logData = new LogData(level, new StackFrame(2, needFileInfo: true), message); _output(logData, _file); } catch (Exception ex) { logData = new LogData(LogLevel.Fatal, new StackFrame(0, needFileInfo: true), ex.Message); Console.WriteLine(logData.ToString()); } } } private static void writeToFile(string value, string path) { using StreamWriter writer = new StreamWriter(path, append: true); using TextWriter textWriter = TextWriter.Synchronized(writer); textWriter.WriteLine(value); } public void Debug(string message) { if (_level <= LogLevel.Debug) { output(message, LogLevel.Debug); } } public void Error(string message) { if (_level <= LogLevel.Error) { output(message, LogLevel.Error); } } public void Fatal(string message) { output(message, LogLevel.Fatal); } public void Info(string message) { if (_level <= LogLevel.Info) { output(message, LogLevel.Info); } } public void Trace(string message) { if (_level <= LogLevel.Trace) { output(message, LogLevel.Trace); } } public void Warn(string message) { if (_level <= LogLevel.Warn) { output(message, LogLevel.Warn); } } } public enum LogLevel { Trace, Debug, Info, Warn, Error, Fatal } internal enum Mask : byte { Off, On } public class MessageEventArgs : EventArgs { private string _data; private bool _dataSet; private Opcode _opcode; private byte[] _rawData; internal Opcode Opcode => _opcode; public string Data { get { setData(); return _data; } } public bool IsBinary => _opcode == Opcode.Binary; public bool IsPing => _opcode == Opcode.Ping; public bool IsText => _opcode == Opcode.Text; public byte[] RawData { get { setData(); return _rawData; } } internal MessageEventArgs(WebSocketFrame frame) { _opcode = frame.Opcode; _rawData = frame.PayloadData.ApplicationData; } internal MessageEventArgs(Opcode opcode, byte[] rawData) { if ((ulong)rawData.LongLength > PayloadData.MaxLength) { throw new WebSocketException(CloseStatusCode.TooBig); } _opcode = opcode; _rawData = rawData; } private void setData() { if (!_dataSet) { if (_opcode == Opcode.Binary) { _dataSet = true; return; } _data = _rawData.UTF8Decode(); _dataSet = true; } } } internal enum Opcode : byte { Cont = 0, Text = 1, Binary = 2, Close = 8, Ping = 9, Pong = 10 } internal class PayloadData : IEnumerable<byte>, IEnumerable { private ushort _code; private bool _codeSet; private byte[] _data; private long _extDataLength; private long _length; private string _reason; private bool _reasonSet; public static readonly PayloadData Empty; public static readonly ulong MaxLength; internal ushort Code { get { if (!_codeSet) { _code = (ushort)((_length > 1) ? _data.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005); _codeSet = true; } return _code; } } internal long ExtensionDataLength { get { return _extDataLength; } set { _extDataLength = value; } } internal bool HasReservedCode { get { if (_length > 1) { return Code.IsReserved(); } return false; } } internal string Reason { get { if (!_reasonSet) { _reason = ((_length > 2) ? _data.SubArray(2L, _length - 2).UTF8Decode() : string.Empty); _reasonSet = true; } return _reason; } } public byte[] ApplicationData { get { if (_extDataLength <= 0) { return _data; } return _data.SubArray(_extDataLength, _length - _extDataLength); } } public byte[] ExtensionData { get { if (_extDataLength <= 0) { return WebSocket.EmptyBytes; } return _data.SubArray(0L, _extDataLength); } } public ulong Length => (ulong)_length; static PayloadData() { Empty = new PayloadData(); MaxLength = 9223372036854775807uL; } internal PayloadData() { _code = 1005; _reason = string.Empty; _data = WebSocket.EmptyBytes; _codeSet = true; _reasonSet = true; } internal PayloadData(byte[] data) : this(data, data.LongLength) { } internal PayloadData(byte[] data, long length) { _data = data; _length = length; } internal PayloadData(ushort code, string reason) { _code = code; _reason = reason ?? string.Empty; _data = code.Append(reason); _length = _data.LongLength; _codeSet = true; _reasonSet = true; } internal void Mask(byte[] key) { for (long num = 0L; num < _length; num++) { _data[num] ^= key[num % 4]; } } public IEnumerator<byte> GetEnumerator() { byte[] data = _data; for (int i = 0; i < data.Length; i++) { yield return data[i]; } } public byte[] ToArray() { return _data; } public override string ToString() { return BitConverter.ToString(_data); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal enum Rsv : byte { Off, On } public class WebSocket : IDisposable { private AuthenticationChallenge _authChallenge; private string _base64Key; private bool _client; private Action _closeContext; private CompressionMethod _compression; private WebSocketContext _context; private WebSocketSharp.CustomHeaders.Net.CookieCollection _cookies; private WebSocketSharp.CustomHeaders.Net.NetworkCredential _credentials; private bool _emitOnPing; private bool _enableRedirection; private string _extensions; private bool _extensionsRequested; private object _forMessageEventQueue; private object _forPing; private object _forSend; private object _forState; private MemoryStream _fragmentsBuffer; private bool _fragmentsCompressed; private Opcode _fragmentsOpcode; private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; private Func<WebSocketContext, string> _handshakeRequestChecker; private bool _ignoreExtensions; private bool _inContinuation; private volatile bool _inMessage; private volatile Logger _logger; private static readonly int _maxRetryCountForConnect; private Action<MessageEventArgs> _message; private Queue<MessageEventArgs> _messageEventQueue; private uint _nonceCount; private string _origin; private ManualResetEvent _pongReceived; private bool _preAuth; private string _protocol; private string[] _protocols; private bool _protocolsRequested; private WebSocketSharp.CustomHeaders.Net.NetworkCredential _proxyCredentials; private Uri _proxyUri; private volatile WebSocketState _readyState; private ManualResetEvent _receivingExited; private int _retryCountForConnect; private bool _secure; private ClientSslConfiguration _sslConfig; private Stream _stream; private TcpClient _tcpClient; private Uri _uri; private const string _version = "13"; private TimeSpan _waitTime; internal static readonly byte[] EmptyBytes; public static int FragmentLength; internal static readonly RandomNumberGenerator RandomNumber; internal WebSocketSharp.CustomHeaders.Net.CookieCollection CookieCollection => _cookies; internal Func<WebSocketContext, string> CustomHandshakeRequestChecker { get { return _handshakeRequestChecker; } set { _handshakeRequestChecker = value; } } internal bool HasMessage { get { lock (_forMessageEventQueue) { return _messageEventQueue.Count > 0; } } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } internal bool IsConnected { get { if (_readyState != WebSocketState.Open) { return _readyState == WebSocketState.Closing; } return true; } } public IEnumerable<KeyValuePair<string, string>> CustomHeaders { get; set; } public CompressionMethod Compression { get { return _compression; } set { string text = null; if (!_client) { text = "The set operation cannot be used by servers."; throw new InvalidOperationException(text); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _compression = value; } } } } public IEnumerable<WebSocketSharp.CustomHeaders.Net.Cookie> Cookies { get { lock (_cookies.SyncRoot) { foreach (WebSocketSharp.CustomHeaders.Net.Cookie cookie in _cookies) { yield return cookie; } } } } public WebSocketSharp.CustomHeaders.Net.NetworkCredential Credentials => _credentials; public bool EmitOnPing { get { return _emitOnPing; } set { _emitOnPing = value; } } public bool EnableRedirection { get { return _enableRedirection; } set { string text = null; if (!_client) { text = "The set operation cannot be used by servers."; throw new InvalidOperationException(text); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _enableRedirection = value; } } } } public string Extensions => _extensions ?? string.Empty; public bool IsAlive => ping(EmptyBytes); public bool IsSecure => _secure; public Logger Log { get { return _logger; } internal set { _logger = value; } } public string Origin { get { return _origin; } set { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!value.IsNullOrEmpty()) { if (!Uri.TryCreate(value, UriKind.Absolute, out Uri result)) { text = "Not an absolute URI string."; throw new ArgumentException(text, value); } if (result.Segments.Length > 1) { text = "It includes the path segments."; throw new ArgumentException(text, value); } } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); return; } _origin = ((!value.IsNullOrEmpty()) ? value.TrimEnd(new char[1] { '/' }) : value); } } } public string Protocol { get { return _protocol ?? string.Empty; } internal set { _protocol = value; } } public WebSocketState ReadyState => _readyState; public ClientSslConfiguration SslConfiguration { get { if (!_client) { throw new InvalidOperationException("This instance is not a client."); } if (!_secure) { throw new InvalidOperationException("This instance does not use a secure connection."); } if (_sslConfig == null) { _sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost); } return _sslConfig; } } public Uri Url { get { if (!_client) { return _context.RequestUri; } return _uri; } } public TimeSpan WaitTime { get { return _waitTime; } set { if (value <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("value", "Zero or less."); } if (!canSet(out var text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _waitTime = value; } } } } public event EventHandler<CloseEventArgs> OnClose; public event EventHandler<ErrorEventArgs> OnError; public event EventHandler<MessageEventArgs> OnMessage; public event EventHandler OnOpen; static WebSocket() { _maxRetryCountForConnect = 10; EmptyBytes = new byte[0]; FragmentLength = 1016; RandomNumber = new RNGCryptoServiceProvider(); } internal WebSocket(HttpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } internal WebSocket(TcpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } public WebSocket(string url, params string[] protocols) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Length == 0) { throw new ArgumentException("An empty string.", "url"); } if (!url.TryCreateWebSocketUri(out _uri, out var text)) { throw new ArgumentException(text, "url"); } if (protocols != null && protocols.Length != 0) { if (!checkProtocols(protocols, out text)) { throw new ArgumentException(text, "protocols"); } _protocols = protocols; } _base64Key = CreateBase64Key(); _client = true; _logger = new Logger(); _message = messagec; _secure = _uri.Scheme == "wss"; _waitTime = TimeSpan.FromSeconds(5.0); init(); } private bool accept() { lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); return false; } try { if (!acceptHandshake()) { return false; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while accepting.", ex); return false; } return true; } } private bool acceptHandshake() { _logger.Debug($"A request from {_context.UserEndPoint}:\n{_context}"); if (!checkHandshakeRequest(_context, out var text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.ProtocolError); return false; } if (!customCheckHandshakeRequest(_context, out text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.PolicyViolation); return false; } _base64Key = _context.Headers["Sec-WebSocket-Key"]; if (_protocol != null) { processSecWebSocketProtocolHeader(_context.SecWebSocketProtocols); } if (!_ignoreExtensions) { processSecWebSocketExtensionsClientHeader(_context.Headers["Sec-WebSocket-Extensions"]); } return sendHttpResponse(createHandshakeResponse()); } private bool canSet(out string message) { message = null; if (_readyState == WebSocketState.Open) { message = "The connection has already been established."; return false; } if (_readyState == WebSocketState.Closing) { message = "The connection is closing."; return false; } return true; } private bool checkHandshakeRequest(WebSocketContext context, out string message) { message = null; if (context.RequestUri == null) { message = "Specifies an invalid Request-URI."; return false; } if (!context.IsWebSocketRequest) { message = "Not a WebSocket handshake request."; return false; } NameValueCollection headers = context.Headers; if (!validateSecWebSocketKeyHeader(headers["Sec-WebSocket-Key"])) { message = "Includes no Sec-WebSocket-Key header, or it has an invalid value."; return false; } if (!validateSecWebSocketVersionClientHeader(headers["Sec-WebSocket-Version"])) { message = "Includes no Sec-WebSocket-Version header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolClientHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes an invalid Sec-WebSocket-Protocol header."; return false; } if (!_ignoreExtensions && !validateSecWebSocketExtensionsClientHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } return true; } private bool checkHandshakeResponse(HttpResponse response, out string message) { message = null; if (response.IsRedirect) { message = "Indicates the redirection."; return false; } if (response.IsUnauthorized) { message = "Requires the authentication."; return false; } if (!response.IsWebSocketResponse) { message = "Not a WebSocket handshake response."; return false; } NameValueCollection headers = response.Headers; if (!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"])) { message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolServerHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value."; return false; } if (!validateSecWebSocketExtensionsServerHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } if (!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"])) { message = "Includes an invalid Sec-WebSocket-Version header."; return false; } return true; } private bool checkIfAvailable(bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!connecting && _readyState == WebSocketState.Connecting) { message = "This operation is not available in: connecting"; return false; } if (!open && _readyState == WebSocketState.Open) { message = "This operation is not available in: open"; return false; } if (!closing && _readyState == WebSocketState.Closing) { message = "This operation is not available in: closing"; return false; } if (!closed && _readyState == WebSocketState.Closed) { message = "This operation is not available in: closed"; return false; } return true; } private bool checkIfAvailable(bool client, bool server, bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!client && _client) { message = "This operation is not available in: client"; return false; } if (!server && !_client) { message = "This operation is not available in: server"; return false; } return checkIfAvailable(connecting, open, closing, closed, out message); } private static bool checkParametersForSetCredentials(string username, string password, out string message) { message = null; if (username.IsNullOrEmpty()) { return true; } if (Ext.Contains(username, ':') || !username.IsText()) { message = "'username' contains an invalid character."; return false; } if (password.IsNullOrEmpty()) { return true; } if (!password.IsText()) { message = "'password' contains an invalid character."; return false; } return true; } private static bool checkParametersForSetProxy(string url, string username, string password, out string message) { message = null; if (url.IsNullOrEmpty()) { return true; } if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result) || result.Scheme != "http" || result.Segments.Length > 1) { message = "'url' is an invalid URL."; return false; } if (username.IsNullOrEmpty()) { return true; } if (Ext.Contains(username, ':') || !username.IsText()) { message = "'username' contains an invalid character."; return false; } if (password.IsNullOrEmpty()) { return true; } if (!password.IsText()) { message = "'password' contains an invalid character."; return false; } return true; } private static bool checkProtocols(string[] protocols, out string message) { message = null; Func<string, bool> condition = (string protocol) => protocol.IsNullOrEmpty() || !protocol.IsToken(); if (protocols.Contains(condition)) { message = "It contains a value that is not a token."; return false; } if (protocols.ContainsTwice()) { message = "It contains a value twice."; return false; } return true; } private bool checkReceivedFrame(WebSocketFrame frame, out string message) { message = null; bool isMasked = frame.IsMasked; if (_client && isMasked) { message = "A frame from the server is masked."; return false; } if (!_client && !isMasked) { message = "A frame from a client is not masked."; return false; } if (_inContinuation && frame.IsData) { message = "A data frame has been received while receiving continuation frames."; return false; } if (frame.IsCompressed && _compression == CompressionMethod.None) { message = "A compressed frame has been received without any agreement for it."; return false; } if (frame.Rsv2 == Rsv.On) { message = "The RSV2 of a frame is non-zero without any negotiation for it."; return false; } if (frame.Rsv3 == Rsv.On) { message = "The RSV3 of a frame is non-zero without any negotiation for it."; return false; } return true; } private void close(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } if (code == 1005) { close(PayloadData.Empty, send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); close(new PayloadData(code, reason), receive, receive, received: false); } private void close(PayloadData payloadData, bool send, bool receive, bool received) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } send = send && _readyState == WebSocketState.Open; receive = send && receive; _readyState = WebSocketState.Closing; } _logger.Trace("Begin closing the connection."); bool wasClean = closeHandshake(payloadData, send, receive, received); releaseResources(); _logger.Trace("End closing the connection."); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs(payloadData); e.WasClean = wasClean; try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during the OnClose event.", ex); } } private void closeAsync(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } if (code == 1005) { closeAsync(PayloadData.Empty, send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); closeAsync(new PayloadData(code, reason), receive, receive, received: false); } private void closeAsync(PayloadData payloadData, bool send, bool receive, bool received) { ThreadPool.QueueUserWorkItem(delegate { try { close(payloadData, send, receive, received); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during an async close.", ex); } }, null); } private bool closeHandshake(byte[] frameAsBytes, bool receive, bool received) { bool flag = frameAsBytes != null && sendBytes(frameAsBytes); if (!received && flag && receive && _receivingExited != null) { received = _receivingExited.WaitOne(_waitTime); } bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool closeHandshake(PayloadData payloadData, bool send, bool receive, bool received) { bool flag = false; if (send) { WebSocketFrame webSocketFrame = WebSocketFrame.CreateCloseFrame(payloadData, _client); flag = sendBytes(webSocketFrame.ToArray()); if (_client) { webSocketFrame.Unmask(); } } if (!received && flag && receive && _receivingExited != null) { received = _receivingExited.WaitOne(_waitTime); } bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool connect() { lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); return false; } if (_retryCountForConnect > _maxRetryCountForConnect) { _retryCountForConnect = 0; _logger.Fatal("A series of reconnecting has failed."); return false; } _readyState = WebSocketState.Connecting; try { doHandshake(); } catch (Exception ex) { _retryCountForConnect++; _logger.Fatal(ex.ToString()); fatal("An exception has occurred while connecting.", ex); return false; } _retryCountForConnect = 1; _readyState = WebSocketState.Open; return true; } } private string createExtensions() { StringBuilder stringBuilder = new StringBuilder(80); if (_compression != CompressionMethod.None) { string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover"); stringBuilder.AppendFormat("{0}, ", arg); } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; return stringBuilder.ToString(); } return null; } private HttpResponse createHandshakeFailureResponse(WebSocketSharp.CustomHeaders.Net.HttpStatusCode code) { HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code); httpResponse.Headers["Sec-WebSocket-Version"] = "13"; return httpResponse; } private HttpRequest createHandshakeRequest() { HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri); NameValueCollection headers = httpRequest.Headers; if (!_origin.IsNullOrEmpty()) { headers["Origin"] = _origin; } headers["Sec-WebSocket-Key"] = _base64Key; _protocolsRequested = _protocols != null; if (_protocolsRequested) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); } _extensionsRequested = _compression != CompressionMethod.None; if (_extensionsRequested) { headers["Sec-WebSocket-Extensions"] = createExtensions(); } headers["Sec-WebSocket-Version"] = "13"; AuthenticationResponse authenticationResponse = null; if (_authChallenge != null && _credentials != null) { authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; } else if (_preAuth) { authenticationResponse = new AuthenticationResponse(_credentials); } if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_cookies.Count > 0) { httpRequest.SetCookies(_cookies); } return httpRequest; } private HttpResponse createHandshakeResponse() { HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse(); NameValueCollection headers = httpResponse.Headers; headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key); if (_protocol != null) { headers["Sec-WebSocket-Protocol"] = _protocol; } if (_extensions != null) { headers["Sec-WebSocket-Extensions"] = _extensions; } if (_cookies.Count > 0) { httpResponse.SetCookies(_cookies); } return httpResponse; } private bool customCheckHandshakeRequest(WebSocketContext context, out string message) { message = null; if (_handshakeRequestChecker != null) { return (message = _handshakeRequestChecker(context)) == null; } return true; } private MessageEventArgs dequeueFromMessageEventQueue() { lock (_forMessageEventQueue) { return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null; } } private void doHandshake() { setClientStream(); HttpResponse httpResponse = sendHandshakeRequest(); if (!checkHandshakeResponse(httpResponse, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } if (_protocolsRequested) { _protocol = httpResponse.Headers["Sec-WebSocket-Protocol"]; } if (_extensionsRequested) { processSecWebSocketExtensionsServerHeader(httpResponse.Headers["Sec-WebSocket-Extensions"]); } processCookies(httpResponse.Cookies); } private void enqueueToMessageEventQueue(MessageEventArgs e) { lock (_forMessageEventQueue) { _messageEventQueue.Enqueue(e); } } private void error(string message, Exception exception) { try { this.OnError.Emit(this, new ErrorEventArgs(message, exception)); } catch (Exception ex) { _logger.Error(ex.ToString()); } } private void fatal(string message, Exception exception) { CloseStatusCode code = ((exception is WebSocketException) ? ((WebSocketException)exception).Code : CloseStatusCode.Abnormal); fatal(message, (ushort)code); } private void fatal(string message, ushort code) { PayloadData payloadData = new PayloadData(code, message); close(payloadData, !code.IsReserved(), receive: false, received: false); } private void fatal(string message, CloseStatusCode code) { fatal(message, (ushort)code); } private void init() { _compression = CompressionMethod.None; _cookies = new WebSocketSharp.CustomHeaders.Net.CookieCollection(); _forPing = new object(); _forSend = new object(); _forState = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.Connecting; } private void message() { MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { return; } _inMessage = true; obj = _messageEventQueue.Dequeue(); } try { _message(obj); } catch (Exception ex) { lock (_forMessageEventQueue) { _inMessage = false; } _logger.Error(ex.ToString()); error("An error has occurred during an OnMessage event.", ex); } } private void messagec(MessageEventArgs e) { while (true) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; break; } e = _messageEventQueue.Dequeue(); } } } private void messages(MessageEventArgs e) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } e = _messageEventQueue.Dequeue(); } try { ThreadPool.QueueUserWorkItem(delegate(object state) { messages((MessageEventArgs)state); }, e); } catch (Exception ex2) { lock (_forMessageEventQueue) { _inMessage = false; } _logger.Error(ex2.ToString()); error("An error has occurred during an OnMessage event.", ex2); } } private void open() { _inMessage = true; startReceiving(); try { this.OnOpen.Emit(this, EventArgs.Empty); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during the OnOpen event.", ex); } MessageEventArgs state = null; lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } state = _messageEventQueue.Dequeue(); } try { ThreadPool.QueueUserWorkItem(delegate(object obj) { _message((MessageEventArgs)obj); }, state); } catch (Exception ex2) { lock (_forMessageEventQueue) { _inMessage = false; } _logger.Error(ex2.ToString()); error("An error has occurred during an OnMessage event.", ex2); } } private bool ping(byte[] data) { if (_readyState != WebSocketState.Open) { return false; } ManualResetEvent pongReceived = _pongReceived; if (pongReceived == null) { return false; } lock (_forPing) { try { pongReceived.Reset(); if (!send(Fin.Final, Opcode.Ping, data, compressed: false)) { return false; } return pongReceived.WaitOne(_waitTime); } catch (ObjectDisposedException) { return false; } } } private bool processCloseFrame(WebSocketFrame frame) { PayloadData payloadData = frame.PayloadData; close(payloadData, !payloadData.HasReservedCode, receive: false, received: true); return false; } private void processCookies(WebSocketSharp.CustomHeaders.Net.CookieCollection cookies) { if (cookies.Count != 0) { _cookies.SetOrRemove(cookies); } } private bool processDataFrame(WebSocketFrame frame) { enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame)); return true; } private bool processFragmentFrame(WebSocketFrame frame) { if (!_inContinuation) { if (frame.IsContinuation) { return true; } _fragmentsOpcode = frame.Opcode; _fragmentsCompressed = frame.IsCompressed; _fragmentsBuffer = new MemoryStream(); _inContinuation = true; } _fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024); if (frame.IsFinal) { using (_fragmentsBuffer) { byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray()); enqueueToMessageEventQueue(new MessageEventArgs(_fragmentsOpcode, rawData)); } _fragmentsBuffer = null; _inContinuation = false; } return true; } private bool processPingFrame(WebSocketFrame frame) { _logger.Trace("A ping was received."); WebSocketFrame webSocketFrame = WebSocketFrame.CreatePongFrame(frame.PayloadData, _client); lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The connection is closing."); return true; } if (!sendBytes(webSocketFrame.ToArray())) { return false; } } _logger.Trace("A pong to this ping has been sent."); if (_emitOnPing) { if (_client) { webSocketFrame.Unmask(); } enqueueToMessageEventQueue(new MessageEventArgs(frame)); } return true; } private bool processPongFrame(WebSocketFrame frame) { _logger.Trace("A pong was received."); try { _pongReceived.Set(); } catch (NullReferenceException ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); return false; } catch (ObjectDisposedException ex2) { _logger.Error(ex2.Message); _logger.Debug(ex2.ToString()); return false; } _logger.Trace("It has been signaled."); return true; } private bool processReceivedFrame(WebSocketFrame frame) { if (!checkReceivedFrame(frame, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } frame.Unmask(); if (!frame.IsFragment) { if (!frame.IsData) { if (!frame.IsPing) { if (!frame.IsPong) { if (!frame.IsClose) { return processUnsupportedFrame(frame); } return processCloseFrame(frame); } return processPongFrame(frame); } return processPingFrame(frame); } return processDataFrame(frame); } return processFragmentFrame(frame); } private void processSecWebSocketExtensionsClientHeader(string value) { if (value == null) { return; } StringBuilder stringBuilder = new StringBuilder(80); bool flag = false; foreach (string item in value.SplitHeaderValue(',')) { string value2 = item.Trim(); if (!flag && value2.IsCompressionExtension(CompressionMethod.Deflate)) { _compression = CompressionMethod.Deflate; stringBuilder.AppendFormat("{0}, ", _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover")); flag = true; } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; _extensions = stringBuilder.ToString(); } } private void processSecWebSocketExtensionsServerHeader(string value) { if (value == null) { _compression = CompressionMethod.None; } else { _extensions = value; } } private void processSecWebSocketProtocolHeader(IEnumerable<string> values) { if (!values.Contains((string p) => p == _protocol)) { _protocol = null; } } private bool processUnsupportedFrame(WebSocketFrame frame) { _logger.Fatal("An unsupported frame:" + frame.PrintToString(dumped: false)); fatal("There is no way to handle it.", CloseStatusCode.PolicyViolation); return false; } private void releaseClientResources() { if (_stream != null) { _stream.Dispose(); _stream = null; } if (_tcpClient != null) { _tcpClient.Close(); _tcpClient = null; } } private void releaseCommonResources() { if (_fragmentsBuffer != null) { _fragmentsBuffer.Dispose(); _fragmentsBuffer = null; _inContinuation = false; } if (_pongReceived != null) { _pongReceived.Close(); _pongReceived = null; } if (_receivingExited != null) { _receivingExited.Close(); _receivingExited = null; } } private void releaseResources() { if (_client) { releaseClientResources(); } else { releaseServerResources(); } releaseCommonResources(); } private void releaseServerResources() { if (_closeContext != null) { _closeContext(); _closeContext = null; _stream = null; _context = null; } } private bool send(Opcode opcode, Stream stream) { lock (_forSend) { Stream stream2 = stream; bool flag = false; bool flag2 = false; try { if (_compression != CompressionMethod.None) { stream = stream.Compress(_compression); flag = true; } flag2 = send(opcode, stream, flag); if (!flag2) { error("A send has been interrupted.", null); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during a send.", ex); } finally { if (flag) { stream.Dispose(); } stream2.Dispose(); } return flag2; } } private bool send(Opcode opcode, Stream stream, bool compressed) { long length = stream.Length; if (length == 0L) { return send(Fin.Final, opcode, EmptyBytes, compressed: false); } long num = length / FragmentLength; int num2 = (int)(length % FragmentLength); byte[] array = null; switch (num) { case 0L: array = new byte[num2]; if (stream.Read(array, 0, num2) == num2) { return send(Fin.Final, opcode, array, compressed); } return false; case 1L: if (num2 == 0) { array = new byte[FragmentLength]; if (stream.Read(array, 0, FragmentLength) == FragmentLength) { return send(Fin.Final, opcode, array, compressed); } return false; } break; } array = new byte[FragmentLength]; if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, opcode, array, compressed)) { return false; } long num3 = ((num2 == 0) ? (num - 2) : (num - 1)); for (long num4 = 0L; num4 < num3; num4++) { if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed: false)) { return false; } } if (num2 == 0) { num2 = FragmentLength; } else { array = new byte[num2]; } if (stream.Read(array, 0, num2) == num2) { return send(Fin.Final, Opcode.Cont, array, compressed: false); } return false; } private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The connection is closing."); return false; } WebSocketFrame webSocketFrame = new WebSocketFrame(fin, opcode, data, compressed, _client); return sendBytes(webSocketFrame.ToArray()); } } private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed) { ThreadPool.QueueUserWorkItem(delegate { try { bool obj = send(opcode, stream); if (completed != null) { completed(obj); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during the callback for an async send.", ex); } }, null); } private bool sendBytes(byte[] bytes) { try { _stream.Write(bytes, 0, bytes.Length); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); return false; } return true; } private HttpResponse sendHandshakeRequest() { HttpRequest httpRequest = createHandshakeRequest(); if (CustomHeaders != null) { foreach (KeyValuePair<string, string> customHeader in CustomHeaders) { if (customHeader.Key == "Sec-WebSocket-Key") { _logger.Error("Sec-WebSocket-Key is automatically generated and your override will not work."); } else { httpRequest.Headers.Set(customHeader.Key, customHeader.Value); } } } HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsUnauthorized) { string text = httpResponse.Headers["WWW-Authenticate"]; _logger.Warn($"Received an authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { _logger.Error("No authentication challenge is specified."); return httpResponse; } _authChallenge = AuthenticationChallenge.Parse(text); if (_authChallenge == null) { _logger.Error("An invalid authentication challenge is specified."); return httpResponse; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.CustomHeaders.Net.AuthenticationSchemes.Digest)) { if (httpResponse.HasConnectionClose) { releaseClientResources(); setClientStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; httpRequest.Headers["Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } } if (httpResponse.IsRedirect) { string text2 = httpResponse.Headers["Location"]; _logger.Warn($"Received a redirection to '{text2}'."); if (_enableRedirection) { if (text2.IsNullOrEmpty()) { _logger.Error("No url to redirect is located."); return httpResponse; } if (!text2.TryCreateWebSocketUri(out var result, out var text3)) { _logger.Error("An invalid url to redirect is located: " + text3); return httpResponse; } releaseClientResources(); _uri = result; _secure = result.Scheme == "wss"; setClientStream(); return sendHandshakeRequest(); } } return httpResponse; } private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout) { _logger.Debug("A request to the server:\n" + request.ToString()); HttpResponse response = request.GetResponse(_stream, millisecondsTimeout); _logger.Debug("A response to this request:\n" + response.ToString()); return response; } private bool sendHttpResponse(HttpResponse response) { _logger.Debug("A response to this request:\n" + response.ToString()); return sendBytes(response.ToByteArray()); } private void sendProxyConnectRequest() { HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsProxyAuthenticationRequired) { string text = httpResponse.Headers["Proxy-Authenticate"]; _logger.Warn($"Received a proxy authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { throw new WebSocketException("No proxy authentication challenge is specified."); } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text); if (authenticationChallenge == null) { throw new WebSocketException("An invalid proxy authentication challenge is specified."); } if (_proxyCredentials != null) { if (httpResponse.HasConnectionClose) { releaseClientResources(); _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u); httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } if (httpResponse.IsProxyAuthenticationRequired) { throw new WebSocketException("A proxy authentication is required."); } } if (httpResponse.StatusCode[0] != '2') { throw new WebSocketException("The proxy has failed a connection to the requested host and port."); } } private void setClientStream() { if (_proxyUri != null) { _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); sendProxyConnectRequest(); } else { _tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port); _stream = _tcpClient.GetStream(); } if (_secure) { ClientSslConfiguration sslConfiguration = SslConfiguration; string targetHost = sslConfiguration.TargetHost; if (targetHost != _uri.DnsSafeHost) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified."); } try { SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback); sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation); _stream = sslStream; } catch (Exception innerException) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException); } } } private void startReceiving() { if (_messageEventQueue.Count > 0) { _messageEventQueue.Clear(); } _pongReceived = new ManualResetEvent(initialState: false); _receivingExited = new ManualResetEvent(initialState: false); Action receive = null; receive = delegate { WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame) { if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed) { _receivingExited?.Set(); } else { receive(); if (!_inMessage && HasMessage && _readyState == WebSocketState.Open) { message(); } } }, delegate(Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while receiving.", ex); }); }; receive(); } private bool validateSecWebSocketAcceptHeader(string value) { if (value != null) { return value == CreateResponseKey(_base64Key); } return false; } private bool validateSecWebSocketExtensionsClientHeader(string value) { if (value != null) { return value.Length > 0; } return true; } private bool validateSecWebSocketExtensionsServerHeader(string value) {