Decompiled source of CrowdControl GambleWithYourFriends v1.0.0
BepInEx/plugins/ConnectorLib.JSON.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; 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.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© 2025 Warp World, Inc.")] [assembly: AssemblyFileVersion("5.0.9624.35466")] [assembly: AssemblyInformationalVersion("5.0.9624.35466+3863de10ef7a620b1c411661d2fc30d749c952d0")] [assembly: AssemblyProduct("ConnectorLib.JSON")] [assembly: AssemblyTitle("ConnectorLib.JSON")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.0.9624.35466")] [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 IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ConnectorLib.JSON { internal class AnnotatedEnumConverter<T> : JsonConverter<T> where T : unmanaged, 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() { _attributes = ((T[])Enum.GetValues(typeof(T))).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; object[] array = enumVal2.GetType().GetTypeInfo().DeclaredMembers.First((MemberInfo m) => string.Equals(m.Name, enumVal2.ToString(), StringComparison.Ordinal)).GetCustomAttributes(typeof(T), inherit: false).ToArray(); if (array.Length == 0) { return null; } return (T)array[0]; } 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 JTokenType type = reader.Type; if ((int)type != 6) { if ((int)type == 8) { string text = Extensions.Value<string>((IEnumerable<JToken>)reader); if (text == null) { throw new SerializationException("The value was null."); } if (Enum.TryParse(objectType, text, ignoreCase: true, out object result)) { return (Enum)result; } 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 DataRequest : SimpleJSONRequest { public string key; public DataRequest(string key) { this.key = key; type = RequestType.DataRequest; } } [Serializable] public class DataResponse : SimpleJSONResponse { public string key; public JToken? value; public EffectStatus status; public long timeRemaining; public string? message; [JsonConstructor] public DataResponse(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; type = ResponseType.DataResponse; } public static DataResponse SuccessIfDefined(string key, object? value, string failMessage = "") { if (value == null) { return Retry(key, 0L, failMessage); } if (value is string input && input.IsNullOrWhiteSpace()) { return Retry(key, 0L, failMessage); } return Success(key, value); } public static DataResponse Success(string key, object? value) { return new DataResponse(key, EffectStatus.Success, value, 0L); } public static DataResponse Success(string key, object? value, string? message) { return new DataResponse(key, EffectStatus.Success, value, 0L, message); } public static DataResponse Failure(string key) { return new DataResponse(key, EffectStatus.Failure, null, 0L); } public static DataResponse Failure(string key, string? message) { return new DataResponse(key, EffectStatus.Failure, null, 0L, message); } public static DataResponse Failure(string key, object? value, string? message = null) { return new DataResponse(key, EffectStatus.Failure, value, 0L, message); } public static DataResponse Retry(string key, long delay = 0L, string? message = null) { return new DataResponse(key, EffectStatus.Retry, null, delay, message); } } [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 long? cost; public Guid? requestID; [JsonConverter(typeof(IEffectSourceDetails.Converter))] public IEffectSourceDetails? sourceDetails; public EffectRequest() { type = RequestType.Start; } } [Serializable] public class EffectResponse : SimpleJSONResponse { private class MetadataConverter : JsonConverter<Dictionary<string, DataResponse>?> { public override void WriteJson(JsonWriter writer, Dictionary<string, DataResponse>? value, JsonSerializer serializer) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown if (value == null) { serializer.Serialize(writer, (object)null); return; } JObject val = new JObject(); foreach (KeyValuePair<string, DataResponse> 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, DataResponse>? ReadJson(JsonReader reader, Type objectType, Dictionary<string, DataResponse>? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown JObject val = (JObject)serializer.Deserialize(reader); if (val == null) { return null; } Dictionary<string, DataResponse> dictionary = new Dictionary<string, DataResponse>(); 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<DataResponse>()); } return dictionary; } } public EffectStatus status; public string? message; public StandardErrors messageID; public long timeRemaining; [JsonConverter(typeof(MetadataConverter))] public Dictionary<string, DataResponse>? metadata; public EffectResponse() { } public EffectResponse(uint id, EffectStatus status) : this(id, status, 0L, null) { } public EffectResponse(uint id, EffectStatus status, StandardErrors messageID) : this(id, status, 0L, messageID) { } public EffectResponse(uint id, EffectStatus status, string? message) : this(id, status, 0L, message) { } public EffectResponse(uint id, EffectStatus status, TimeSpan timeRemaining) : this(id, status, checked((long)timeRemaining.TotalMilliseconds), null) { } public EffectResponse(uint id, EffectStatus status, TimeSpan timeRemaining, StandardErrors messageID) : this(id, status, checked((long)timeRemaining.TotalMilliseconds), messageID) { } public EffectResponse(uint id, EffectStatus status, TimeSpan timeRemaining, string? message) : this(id, status, checked((long)timeRemaining.TotalMilliseconds), message) { } public EffectResponse(uint id, EffectStatus status, long timeRemaining) : this(id, status, timeRemaining, null) { } public EffectResponse(uint id, EffectStatus status, long timeRemaining, StandardErrors messageID) : this(id, status, timeRemaining) { this.messageID = messageID; } [JsonConstructor] public EffectResponse(uint id, EffectStatus status, long timeRemaining, string? message) { base.id = id; this.status = status; this.timeRemaining = timeRemaining; this.message = message; type = ResponseType.EffectRequest; } public static EffectResponse Success(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Success, message); } public static EffectResponse Success(uint id, long delay, string? message = null) { return new EffectResponse(id, EffectStatus.Success, delay, message); } public static EffectResponse Success(uint id, TimeSpan delay, string? message = null) { return new EffectResponse(id, EffectStatus.Success, delay, message); } public static EffectResponse Failure(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Failure, message); } public static EffectResponse Failure(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Failure, error); } public static EffectResponse Unavailable(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Unavailable, message); } public static EffectResponse Unavailable(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Unavailable, error); } public static EffectResponse Retry(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Retry, 0L, message); } public static EffectResponse Retry(uint id, long delay, string? message = null) { return new EffectResponse(id, EffectStatus.Retry, delay, message); } public static EffectResponse Retry(uint id, TimeSpan delay, string? message = null) { return new EffectResponse(id, EffectStatus.Retry, delay, message); } public static EffectResponse Retry(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Retry, 0L, error); } public static EffectResponse Retry(uint id, long delay, StandardErrors error) { return new EffectResponse(id, EffectStatus.Retry, delay, error); } public static EffectResponse Retry(uint id, TimeSpan delay, StandardErrors error) { return new EffectResponse(id, EffectStatus.Retry, delay, error); } public static EffectResponse Paused(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Paused, 0L, message); } public static EffectResponse Paused(uint id, long timeRemaining, string? message = null) { return new EffectResponse(id, EffectStatus.Paused, timeRemaining, message); } public static EffectResponse Paused(uint id, TimeSpan timeRemaining, string? message = null) { return new EffectResponse(id, EffectStatus.Paused, timeRemaining, message); } public static EffectResponse Paused(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Paused, 0L, error); } public static EffectResponse Paused(uint id, long timeRemaining, StandardErrors error) { return new EffectResponse(id, EffectStatus.Paused, timeRemaining, error); } public static EffectResponse Paused(uint id, TimeSpan timeRemaining, StandardErrors error) { return new EffectResponse(id, EffectStatus.Paused, timeRemaining, error); } public static EffectResponse Resumed(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Resumed, 0L, message); } public static EffectResponse Resumed(uint id, long timeRemaining, string? message = null) { return new EffectResponse(id, EffectStatus.Resumed, timeRemaining, message); } public static EffectResponse Resumed(uint id, TimeSpan timeRemaining, string? message = null) { return new EffectResponse(id, EffectStatus.Resumed, timeRemaining, message); } public static EffectResponse Resumed(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Resumed, 0L, error); } public static EffectResponse Resumed(uint id, long timeRemaining, StandardErrors error) { return new EffectResponse(id, EffectStatus.Resumed, timeRemaining, error); } public static EffectResponse Resumed(uint id, TimeSpan timeRemaining, StandardErrors error) { return new EffectResponse(id, EffectStatus.Resumed, timeRemaining, error); } public static EffectResponse Finished(uint id, string? message = null) { return new EffectResponse(id, EffectStatus.Finished, 0L, message); } public static EffectResponse Finished(uint id, StandardErrors error) { return new EffectResponse(id, EffectStatus.Finished, 0L, error); } } public interface IEffectSourceDetails { public 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType == 11) { return null; } JObject val = JObject.Load(reader); JToken obj = val["type"]; return ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null) 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, }; } 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; } } public class TwitchChannelRewardSourceDetails : IEffectSourceDetails { [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; } } public class StreamLabsDonationSourceDetails : IEffectSourceDetails { [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; } } public class HypeTrainSourceDetails : IEffectSourceDetails { 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; } } public abstract class TikTokSourceDetails : IEffectSourceDetails { [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; } } 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 class TikTokLikeSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-like"; } public class TikTokFollowSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-follow"; } public class TikTokShareSourceDetails : TikTokSourceDetails { [JsonProperty("type")] public override string Type => "tiktok-share"; } public class PulsoidTriggerSourceDetails : IEffectSourceDetails { [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; } } public class CrowdControlTestSourceDetails : IEffectSourceDetails { [JsonProperty("type")] public string Type => "crowd-control-test"; } public class CrowdControlChaosModeSourceDetails : IEffectSourceDetails { [JsonProperty("type")] public string Type => "crowd-control-chaos-mode"; } public class CrowdControlRetrySourceDetails : IEffectSourceDetails { [JsonProperty("type")] public string Type => "crowd-control-retry"; } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum EffectStatus { Success = 0, Failure = 1, Unavailable = 2, Retry = 3, Queue = 4, Running = 5, Paused = 6, Resumed = 7, Finished = 8, Wait = 9, RemoteScheduled = 10, Visible = 128, NotVisible = 129, Selectable = 130, NotSelectable = 131, Reserved0 = 160, NotReady = 255 } [Serializable] public class EffectUpdate : SimpleJSONResponse { [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum IdentifierType { Effect, Group, Category } [Obsolete("This field is deprecated. Please use the ids field instead.")] [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; } public EffectUpdate(string[] ids, EffectStatus status, string? message = null) { this.ids = ids; idType = IdentifierType.Effect; this.status = status; this.message = message; type = ResponseType.EffectStatus; } public EffectUpdate(IEnumerable<string> ids, EffectStatus status, string? message = null) { this.ids = ids.ToArray(); 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 { internal 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, BadGameSettings = -3, WrongVersion = -4, NotFocused = -5, Loading = -6, Paused = -7, WrongMode = -8, SafeArea = -9, UntimedArea = -10, Cutscene = -11, BadPlayerState = -12, Menu = -13, Map = -14, InCombat = -15, NotInCombat = -16, PipelineBusy = -128 } [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 GenericEventRequest : SimpleJSONRequest { [JsonProperty(PropertyName = "internal")] public bool @internal; public string eventType; public Dictionary<string, object>? data; public GenericEventRequest(string eventType) { type = RequestType.GenericEvent; this.eventType = eventType; } [JsonConstructor] public GenericEventRequest(string eventType, IEnumerable<KeyValuePair<string, object>>? data) : this(eventType) { this.data = data?.ToDictionary(); } [JsonConstructor] public GenericEventRequest(string eventType, IEnumerable<KeyValuePair<string, object>>? data, bool @internal) : this(eventType, data) { this.@internal = @internal; } } [Serializable] public class GenericEventResponse : SimpleJSONResponse { [JsonProperty(PropertyName = "internal")] public bool @internal; public string eventType; public Dictionary<string, object>? data; public GenericEventResponse(string eventType) { type = ResponseType.GenericEvent; this.eventType = eventType; } public GenericEventResponse(string eventType, IEnumerable<KeyValuePair<string, object>>? data, bool @internal = false) : this(eventType) { this.data = data?.ToDictionary(); this.@internal = @internal; } [JsonConstructor] public GenericEventResponse(string eventType, Dictionary<string, object>? data, [JsonProperty(PropertyName = "internal")] bool @internal) : this(eventType, data) { this.@internal = @internal; } } 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) { if (TryParse(serializer.Deserialize<string>(reader), 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('#'); switch (value.Length) { case 6: { string[] array2 = value.Chop(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 = value.Chop(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; } } } internal static class IEnumerableEx { internal static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> values) where TKey : notnull { Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(); foreach (KeyValuePair<TKey, TValue> value in values) { dictionary.Add(value.Key, value.Value); } return dictionary; } } public interface IParameterValue { string ID { get; } string Name { get; } ParameterBase.ParameterType Type { get; } object? Value { get; } } [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 { internal static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : class { if (value == null) { return null; } return selector(value); } } 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; } } 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; 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); return (float)checked(Math.Max(Math.Max(r, g), b) + 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) { if (left.value == right.value) { return left.state == right.state; } return false; } public static bool operator !=(ParameterColorValue left, ParameterColorValue right) { return !(left == right); } public override bool Equals(object? obj) { if (obj is ParameterColorValue other) { return Equals(other); } return false; } public bool Equals(ParameterColorValue other) { return this == other; } public override int GetHashCode() { return (value.GetHashCode() * 397) ^ state.GetHashCode(); } } public class ParameterValue<TValue> : ParameterBase, IParameterValue { [JsonProperty(PropertyName = "value")] public TValue? 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, TValue? 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.PlayerInfo; } } [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 obj = JObject.Load(reader); List<IParameterValue> list = new List<IParameterValue>(); foreach (KeyValuePair<string, JToken> item in obj) { 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 value = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]); list.Add(new ParameterValue<string>(name, key, value)); break; } case ParameterBase.ParameterType.HexColor: { if (HexColorConverter.TryParse(Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"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> parameters) { parameters = parameters.ToArray(); _parameters = parameters.ToDictionary((IParameterValue d) => d.ID); _parameter_list = parameters.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 enum RequestType : byte { [Obsolete("Use EffectTest instead.")] Test = 0, EffectTest = 0, [Obsolete("Use EffectStart instead.")] Start = 1, EffectStart = 1, [Obsolete("Use EffectStop instead.")] Stop = 2, EffectStop = 2, GenericEvent = 16, DataRequest = 32, 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, DataResponse = 32, RpcRequest = 208, Login = 240, LoginSuccess = 241, GameUpdate = 253, Disconnect = 254, KeepAlive = byte.MaxValue } [Serializable] public class RpcRequest : SimpleJSONResponse { public string? method; public object?[]? args; public RpcRequest() { type = ResponseType.RpcRequest; } } [Serializable] public class RpcResponse : SimpleJSONRequest { public object? value; public RpcResponse() { type = RequestType.RpcResponse; } } public abstract class SimpleJSONMessage { public static readonly JsonSerializerSettings JSON_SERIALIZER_SETTINGS; public static readonly JsonSerializer JSON_SERIALIZER; private static int _next_id; 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; } static SimpleJSONMessage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, MissingMemberHandling = (MissingMemberHandling)0, Formatting = (Formatting)0 }; JSON_SERIALIZER = new JsonSerializer { NullValueHandling = JSON_SERIALIZER_SETTINGS.NullValueHandling, MissingMemberHandling = JSON_SERIALIZER_SETTINGS.MissingMemberHandling, Formatting = JSON_SERIALIZER_SETTINGS.Formatting }; _next_id = 0; AppDomain.CurrentDomain.AssemblyResolve += delegate(object _, ResolveEventArgs args) { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), new AssemblyName(args.Name).Name + ".dll"); return (!File.Exists(text)) ? null : Assembly.LoadFrom(text); }; } public string Serialize() { return JsonConvert.SerializeObject((object)this, JSON_SERIALIZER_SETTINGS); } } [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 bool TryParse(string json, [MaybeNullWhen(false)] out SimpleJSONRequest request) { return TryParse(JObject.Parse(json), out request); } public static bool TryParse(JObject j, [MaybeNullWhen(false)] out SimpleJSONRequest request) { try { JToken value = j.GetValue("type"); RequestType requestType = ((value != null) ? ((RequestType)(object)CamelCaseStringEnumConverter.ReadJToken(value, typeof(RequestType))) : RequestType.Test); switch (requestType) { case RequestType.Stop: if (requestType != RequestType.Stop) { break; } request = ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.Test: case RequestType.Start: request = ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.DataRequest: request = ((JToken)j).ToObject<DataRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.RpcResponse: request = ((JToken)j).ToObject<RpcResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.PlayerInfo: request = ((JToken)j).ToObject<PlayerInfo>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.Login: request = ((JToken)j).ToObject<MessageRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.GameUpdate: request = ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case RequestType.KeepAlive: request = ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; } } catch { } request = null; return false; } } [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 bool TryParse(string json, [MaybeNullWhen(false)] out SimpleJSONResponse response) { return TryParse(JObject.Parse(json), out response); } public static bool TryParse(JObject j, [MaybeNullWhen(false)] out SimpleJSONResponse response) { try { JToken value = j.GetValue("type"); ResponseType responseType = ((value != null) ? ((ResponseType)(object)CamelCaseStringEnumConverter.ReadJToken(value, typeof(ResponseType))) : ResponseType.EffectRequest); switch (responseType) { case ResponseType.EffectStatus: if (responseType != ResponseType.EffectStatus) { break; } response = ((JToken)j).ToObject<EffectUpdate>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.EffectRequest: response = ((JToken)j).ToObject<EffectResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.RpcRequest: response = ((JToken)j).ToObject<RpcRequest>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.GenericEvent: response = ((JToken)j).ToObject<GenericEventResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.DataResponse: response = ((JToken)j).ToObject<DataResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.Login: response = ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.LoginSuccess: response = ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.GameUpdate: response = ((JToken)j).ToObject<GameUpdate>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.Disconnect: response = ((JToken)j).ToObject<MessageResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; case ResponseType.KeepAlive: response = ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER); return true; } } catch { } response = null; return false; } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum StandardErrors { Unknown = 0, ExceptionThrown = 1, BadRequest = 4096, [Obsolete("Use EffectUnknown instead.")] UnknownEffect = 4097, EffectUnknown = 4097, EffectDisabled = 4098, AlreadyFailed = 4099, CannotParseNumber = 4112, UnknownSelection = 4113, ConnectorError = 8192, ConnectorReadFailure = 8193, ConnectorWriteFailure = 8194, ConnectorNotConnected = 8195, ConnectorNotSupported = 8196, SettingsError = 12288, CooldownPerEffect = 12545, CooldownGlobal = 12546, RetryMaxTime = 12291, RetryMaxAttempts = 12292, NoSession = 20480, SessionEnding = 20481, BadGameState = 16384, GameObjectNotFound = 16640, PlayerNotFound = 16641, CharacterNotFound = 16642, EnemyNotFound = 16643, ObjectNotFound = 16644, PrerequisiteNotFound = 16645, ObjectStateError = 16896, AlreadyInState = 16897, AlreadyAcquired = 16898, AlreadyFinished = 16899, NoEmptyContainers = 16912, PartyFull = 16913, InvalidArea = 16928, InvalidTarget = 16929, NoValidTargets = 16930, SpawnNotAllowedHere = 16932, RangeError = 17152, AlreadyMinimum = 17153, AlreadyMaximum = 17154, EffectNotImplemented = 24576, PackResourceMissing = 24577, ConflictingEffectRunning = 32768, UnqueueablePending = 32769, EmulatorNotSupported = 28672, EmulatorInvalidSetting = 28673 } internal static class StringEx { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNullOrWhiteSpace(this string? input) { return string.IsNullOrWhiteSpace(input); } internal 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; } } internal 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; } } }
BepInEx/plugins/CrowdControl.dll
Decompiled 2 days 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.Globalization; using System.IO; using System.Linq; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ConnectorLib.JSON; using CrowdControl.Delegates.Effects; using CrowdControl.Delegates.Metadata; using Extensions; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using Newtonsoft.Json; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class ParamCollectionAttribute : 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 CrowdControl { internal static class CasinoBetMaxPusher { private static readonly FieldInfo? s_canBetField = typeof(GameBase).GetField("canBet", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo? sRouletteBets = typeof(Roulette).GetField("_bets", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo? sRouletteButtons = typeof(Roulette).GetField("buttons", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo? sRouletteRpcTotalText = typeof(Roulette).GetMethod("RpcSetTotalBetText", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo? sKeypadApplyInput = typeof(Keypad).GetMethod("ApplyInput", BindingFlags.Instance | BindingFlags.NonPublic); private static bool ReadCanBet(GameBase gb) { if (s_canBetField == null) { return !gb.isPlaying; } object value = s_canBetField.GetValue(gb); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } public static int PushAllTablesToAffordableMax() { if (!NetworkServer.active) { return 0; } MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { return 0; } long balance = instance.balance; int num = 0; GameBase[] array = CasinoTimedOdds.FindAllGameBasesInScene(); for (int i = 0; i < array.Length; i++) { if (TryPushSingleTableToAffordableMax(array[i], balance)) { num = checked(num + 1); } } return num; } internal static bool TryPushSingleTableToAffordableMax(GameBase gb, long? balanceOverride = null) { if (!NetworkServer.active || (Object)(object)gb == (Object)null || !Object.op_Implicit((Object)(object)gb) || (Object)(object)gb.Keypad == (Object)null) { return false; } MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } long num = balanceOverride ?? instance.balance; if (!ReadCanBet(gb) || gb.isPlaying) { return false; } Roulette val = (Roulette)(object)((gb is Roulette) ? gb : null); if (val != null) { return TryPushRoulette(val, num); } long maxBet = gb.MaxBet; long minBet = gb.MinBet; if (maxBet < minBet) { return false; } long num2 = Math.Min(maxBet, Math.Max(minBet, num)); if (gb.isGoldenChipApplied) { num2 = maxBet; } if (num2 == gb.currentBet) { return false; } TryApplyBetThroughKeypad(gb, num2); return true; } private static void TryApplyBetThroughKeypad(GameBase gb, long target) { if ((Object)(object)gb.Keypad != (Object)null && sKeypadApplyInput != null) { sKeypadApplyInput.Invoke(gb.Keypad, new object[2] { target.ToString(), false }); } else { gb.ServerSetBet(target); } } private static bool TryPushRoulette(Roulette r, long balance) { if (sRouletteBets == null || sRouletteRpcTotalText == null) { return false; } long maxBet = ((GameBase)r).MaxBet; long minBet = ((GameBase)r).MinBet; if (maxBet < minBet) { return false; } long num = Math.Min(maxBet, Math.Max(minBet, balance)); if (((GameBase)r).isGoldenChipApplied) { num = maxBet; } Dictionary<string, long> dictionary = (Dictionary<string, long>)sRouletteBets.GetValue(r); long num2 = 0L; foreach (long value2 in dictionary.Values) { num2 = checked(num2 + value2); } if (num2 == num) { return false; } dictionary.Clear(); RouletteButton[] array = sRouletteButtons?.GetValue(r) as RouletteButton[]; string key = "Red"; if (array != null && array.Length != 0 && !string.IsNullOrEmpty(((Object)array[0]).name)) { key = ((Object)array[0]).name; } dictionary[key] = num; ((GameBase)r).ServerSetBet(num); sRouletteRpcTotalText.Invoke(r, new object[1] { MoneyFormatter.FormatWithDollar(num, false) }); if (array != null) { RouletteButton[] array2 = array; foreach (RouletteButton val in array2) { if (!((Object)(object)val == (Object)null)) { long value; long num3 = (dictionary.TryGetValue(((Object)val).name, out value) ? value : 0); val.ServerSetBets(((GameBase)r).MaxBet, num3); } } } return true; } } internal static class CasinoOopsMaxBetsGate { private static int _sessions; private static bool _inServerSetBetPostfix; private static bool IsSessionActive => Volatile.Read(ref _sessions) > 0; internal static void BeginSession() { Interlocked.Increment(ref _sessions); } internal static void EndSession() { if (Interlocked.Decrement(ref _sessions) < 0) { Interlocked.Exchange(ref _sessions, 0); } } internal static bool IsActive() { return IsSessionActive; } internal static void AfterServerSetBet(GameBase gb) { if (!NetworkServer.active || !IsSessionActive || _inServerSetBetPostfix) { return; } _inServerSetBetPostfix = true; try { CasinoBetMaxPusher.TryPushSingleTableToAffordableMax(gb); } finally { _inServerSetBetPostfix = false; } } } internal static class CasinoTimedOdds { private static readonly FieldInfo s_estimatedValueField = typeof(GameBase).GetField("estimatedValue", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly Dictionary<uint, Dictionary<int, float>> s_estimatedSessions = new Dictionary<uint, Dictionary<int, float>>(); private static readonly Dictionary<uint, Dictionary<int, double>> s_maxBetSessions = new Dictionary<uint, Dictionary<int, double>>(); public static float ReadEstimatedValue(GameBase gameBase) { return (float)s_estimatedValueField.GetValue(gameBase); } private static GameBase[] FindAllGameBases() { return Object.FindObjectsByType<GameBase>((FindObjectsInactive)0, (FindObjectsSortMode)0); } internal static GameBase[] FindAllGameBasesInScene() { return FindAllGameBases(); } public static void BeginEstimatedUniformSession(uint crowdControlRequestId, float uniformValue) { Dictionary<int, float> dictionary = new Dictionary<int, float>(); GameBase[] array = FindAllGameBases(); foreach (GameBase val in array) { if (Object.op_Implicit((Object)(object)val)) { int instanceID = ((Object)((Component)val).gameObject).GetInstanceID(); dictionary[instanceID] = ReadEstimatedValue(val); val.SetEstimatedValue(uniformValue); } } s_estimatedSessions[crowdControlRequestId] = dictionary; } public static void BeginEstimatedScaleSession(uint crowdControlRequestId, float scale, float maxValue) { Dictionary<int, float> dictionary = new Dictionary<int, float>(); GameBase[] array = FindAllGameBases(); foreach (GameBase val in array) { if (Object.op_Implicit((Object)(object)val)) { int instanceID = ((Object)((Component)val).gameObject).GetInstanceID(); float num2 = (dictionary[instanceID] = ReadEstimatedValue(val)); val.SetEstimatedValue(Mathf.Min(num2 * scale, maxValue)); } } s_estimatedSessions[crowdControlRequestId] = dictionary; } public static void RestoreEstimatedSession(uint crowdControlRequestId) { if (!s_estimatedSessions.TryGetValue(crowdControlRequestId, out Dictionary<int, float> value)) { return; } GameBase[] array = FindAllGameBases(); foreach (GameBase val in array) { if (Object.op_Implicit((Object)(object)val) && value.TryGetValue(((Object)((Component)val).gameObject).GetInstanceID(), out var value2)) { val.SetEstimatedValue(value2); } } s_estimatedSessions.Remove(crowdControlRequestId); } public static void BeginMaxBetScaleSession(uint crowdControlRequestId, double factor, double maxMultiplier) { Dictionary<int, double> dictionary = new Dictionary<int, double>(); GameBase[] array = FindAllGameBases(); foreach (GameBase val in array) { if (Object.op_Implicit((Object)(object)val)) { int instanceID = ((Object)((Component)val).gameObject).GetInstanceID(); double num = (dictionary[instanceID] = val.MaxBetOverrideMultiplier); val.MaxBetOverrideMultiplier = Math.Min(num * factor, maxMultiplier); } } s_maxBetSessions[crowdControlRequestId] = dictionary; } public static void RestoreMaxBetSession(uint crowdControlRequestId) { if (!s_maxBetSessions.TryGetValue(crowdControlRequestId, out Dictionary<int, double> value)) { return; } GameBase[] array = FindAllGameBases(); foreach (GameBase val in array) { if (Object.op_Implicit((Object)(object)val) && value.TryGetValue(((Object)((Component)val).gameObject).GetInstanceID(), out var value2)) { val.MaxBetOverrideMultiplier = value2; } } s_maxBetSessions.Remove(crowdControlRequestId); } internal static bool HasAnyEstimatedSession() { return s_estimatedSessions.Count > 0; } internal static bool HasAnyMaxBetSession() { return s_maxBetSessions.Count > 0; } } public sealed class CrowdControlEffectHud : MonoBehaviour { private sealed class ActiveTimed { public TimedEffectState Tracker; public string Title = ""; public string Summary = ""; } private sealed class MirrorTimed { public float EndRealtimeSinceStartup; public string Title = ""; public string Summary = ""; } private CrowdControlMod? _mod; private Texture2D? _white; private Font? _gameFont; private static bool s_loggedMissingGameFont; private int _fontResolveAttempts; private readonly Dictionary<uint, ActiveTimed> _activeTimed = new Dictionary<uint, ActiveTimed>(); private readonly Dictionary<uint, MirrorTimed> _mirrorTimed = new Dictionary<uint, MirrorTimed>(); private readonly List<(float until, string text)> _toasts = new List<(float, string)>(); private GUIStyle? _body; private GUIStyle? _bodyBold; public static CrowdControlEffectHud? Instance { get; private set; } private void Awake() { Instance = this; } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } if ((Object)(object)_white != (Object)null) { Object.Destroy((Object)(object)_white); } } internal void Init(CrowdControlMod mod) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) _mod = mod; TryLoadGameFont(mod, logOnFailure: false); _white = new Texture2D(1, 1, (TextureFormat)4, false); _white.SetPixel(0, 0, Color.white); _white.Apply(); } private void DrawSolidToastFrame(Rect r, float scale) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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) if (!((Object)(object)_white == (Object)null)) { Color val = default(Color); ((Color)(ref val))..ctor(0.96f, 0.96f, 1f, 1f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.12f, 0.12f, 0.15f, 1f); float num = Mathf.Max(2f, 2.75f * scale); GUI.DrawTexture(r, (Texture)(object)_white, (ScaleMode)0, false, 0f, val, 0f, 0f); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref r)).x + num, ((Rect)(ref r)).y + num, ((Rect)(ref r)).width - 2f * num, ((Rect)(ref r)).height - 2f * num); if (((Rect)(ref val3)).width > 0f && ((Rect)(ref val3)).height > 0f) { GUI.DrawTexture(val3, (Texture)(object)_white, (ScaleMode)0, false, 0f, val2, 0f, 0f); } } } private void TryLoadGameFont(CrowdControlMod mod, bool logOnFailure) { _gameFont = Resources.Load<Font>("Fonts/Bungee-Regular"); if ((Object)(object)_gameFont == (Object)null) { Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.IndexOf("Bungee", StringComparison.OrdinalIgnoreCase) >= 0) { _gameFont = val; break; } } } if ((Object)(object)_gameFont == (Object)null && logOnFailure && !s_loggedMissingGameFont) { s_loggedMissingGameFont = true; mod.Logger.LogInfo((object)"Crowd Control HUD: no Bungee font found; using skin default (try after load if still wrong)."); } if ((Object)(object)_gameFont != (Object)null) { InvalidateStyles(); } } private void MaybeResolveFontAgain() { if (!((Object)(object)_gameFont != (Object)null) && !((Object)(object)_mod == (Object)null) && _fontResolveAttempts < 12) { checked { _fontResolveAttempts++; } if (_fontResolveAttempts % 3 == 0) { TryLoadGameFont(_mod, _fontResolveAttempts >= 12); } } } private void InvalidateStyles() { _body = (_bodyBold = null); } private void Update() { if ((Object)(object)_mod == (Object)null || !_mod.ConfigShowEffectHud.Value) { return; } float unscaledTime = Time.unscaledTime; List<uint> list; checked { for (int num = _toasts.Count - 1; num >= 0; num--) { if (_toasts[num].until <= unscaledTime) { _toasts.RemoveAt(num); } } list = null; } foreach (KeyValuePair<uint, ActiveTimed> item in _activeTimed) { TimedEffectState.EffectState state = item.Value.Tracker.State; if ((uint)(state - 3) <= 1u) { (list ?? (list = new List<uint>())).Add(item.Key); } } if (list != null) { foreach (uint item2 in list) { _activeTimed.Remove(item2); } } float realtimeSinceStartup = Time.realtimeSinceStartup; List<uint> list2 = null; foreach (KeyValuePair<uint, MirrorTimed> item3 in _mirrorTimed) { if (realtimeSinceStartup >= item3.Value.EndRealtimeSinceStartup) { (list2 ?? (list2 = new List<uint>())).Add(item3.Key); } } if (list2 == null) { return; } foreach (uint item4 in list2) { _mirrorTimed.Remove(item4); } } internal static void NotifyInstant(string? code, EffectResponse response) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance?._mod == (Object)null) && Instance._mod.ConfigShowEffectHud.Value && (int)response.status == 0) { CrowdControlEffectPresentation.TryGet(code, out string title, out string _); float item = Time.unscaledTime + Instance._mod.ConfigEffectToastSeconds.Value; Instance._toasts.Add((item, title)); while (Instance._toasts.Count > 8) { Instance._toasts.RemoveAt(0); } } } internal static void NotifyTimedStarted(TimedEffectState state, EffectResponse response) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance?._mod == (Object)null) && Instance._mod.ConfigShowEffectHud.Value && (int)response.status == 0 && state.State == TimedEffectState.EffectState.Running) { CrowdControlEffectPresentation.TryGet(state.Request.code, out string title, out string summary); uint id = ((SimpleJSONRequest)state.Request).id; Instance._activeTimed[id] = new ActiveTimed { Tracker = state, Title = title, Summary = summary }; float num = Mathf.Min(2.25f, Instance._mod.ConfigEffectToastSeconds.Value); Instance._toasts.Add((Time.unscaledTime + num, title)); while (Instance._toasts.Count > 8) { Instance._toasts.RemoveAt(0); } } } internal static void NotifyTimedEnded(uint requestId) { if (!((Object)(object)Instance == (Object)null)) { Instance._activeTimed.Remove(requestId); Instance._mirrorTimed.Remove(requestId); } } internal static void NotifyMirrorTimedEnded(uint requestId) { if (!((Object)(object)Instance == (Object)null)) { Instance._mirrorTimed.Remove(requestId); } } internal static void NotifyNetworkTimed(string code, uint requestId, float durationSeconds) { if (!((Object)(object)Instance?._mod == (Object)null) && Instance._mod.ConfigShowEffectHud.Value) { CrowdControlEffectPresentation.TryGet(code, out string title, out string summary); float endRealtimeSinceStartup = Time.realtimeSinceStartup + Mathf.Max(0.05f, durationSeconds); Instance._mirrorTimed[requestId] = new MirrorTimed { EndRealtimeSinceStartup = endRealtimeSinceStartup, Title = title, Summary = summary }; float num = Mathf.Min(2.25f, Instance._mod.ConfigEffectToastSeconds.Value); Instance._toasts.Add((Time.unscaledTime + num, title)); while (Instance._toasts.Count > 8) { Instance._toasts.RemoveAt(0); } } } private void OnGUI() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_mod == (Object)null || !_mod.ConfigShowEffectHud.Value || (Object)(object)_white == (Object)null || (int)Event.current.type != 7) { return; } MaybeResolveFontAgain(); int depth = GUI.depth; GUI.depth = -2000; float num = Mathf.Clamp((float)Screen.height / 1080f * _mod.ConfigEffectHudScale.Value, 0.55f, 2.2f); float num2 = (float)Screen.height / 1080f; Mathf.RoundToInt(8f * num); float gap = Mathf.Max(4f, 5f * num); float num3 = Mathf.Max(0f, _mod.ConfigTimedHudTopOffsetPx.Value * num2); if (_activeTimed.Count > 0 || _mirrorTimed.Count > 0) { float num4 = _mod.ConfigTimedHudTicketStripLeftPx.Value * num2; num4 = Mathf.Max(num4, 4f * num + 36f * num); float num5 = Mathf.Max(20f, 24f * num); GUIStyle st = StyleBodyBold(num, timed: true); TextInfo textInfo = CultureInfo.InvariantCulture.TextInfo; float num6 = TimedRowHeight(num5, gap); float num7 = num3; float num8 = (float)Screen.width - num4 - Mathf.Max(2f, 4f * num); foreach (ActiveTimed value in _activeTimed.Values) { string text = ((value.Tracker.State == TimedEffectState.EffectState.Paused) ? " (PAUSED)" : ""); double num9 = Math.Max(0.0, value.Tracker.TimeRemaining.TotalSeconds); string arg = textInfo.ToUpper(value.Title); string text2 = (string.IsNullOrEmpty(text) ? $"<color=#FAF6F0>{arg}</color> - <color=#7CFFB2>{num9:F0}S</color>" : $"<color=#FAF6F0>{arg}</color> - <color=#7CFFB2>{num9:F0}S</color><color=#C8CCD4>{text}</color>"); DrawLabelSoftShadow(new Rect(num4, num7, num8, num5 * 1.1f), text2, st, num, rich: true); num7 += num6; } foreach (KeyValuePair<uint, MirrorTimed> item in _mirrorTimed) { if (!_activeTimed.ContainsKey(item.Key)) { float num10 = Mathf.Max(0f, item.Value.EndRealtimeSinceStartup - Time.realtimeSinceStartup); double num11 = ((!(num10 <= 0f)) ? Mathf.CeilToInt(num10) : 0); string arg2 = textInfo.ToUpper(item.Value.Title); string text3 = $"<color=#FAF6F0>{arg2}</color> - <color=#7CFFB2>{num11:F0}S</color>"; DrawLabelSoftShadow(new Rect(num4, num7, num8, num5 * 1.1f), text3, st, num, rich: true); num7 += num6; } } GUI.color = Color.white; } if (_toasts.Count == 0) { GUI.depth = depth; return; } GUIStyle val = StyleBody(num); val.fontSize = Mathf.RoundToInt(16.5f * num); float num12 = Mathf.RoundToInt(10f * num); float num13 = Mathf.RoundToInt(7f * num); float shadowD = ToastShadowOffset(num); float num14 = 0f; checked { for (int i = 0; i < _toasts.Count; i++) { num14 = Mathf.Max(num14, MeasureToastContentWidth(val, _toasts[i].text, shadowD, num)); } float num15 = Mathf.Min(num14 + num12 * 2f, (float)Screen.width * 0.52f); num15 = Mathf.Max(num15, num12 * 2f + 4f * num); float num16 = Mathf.Max(1f, num15 - num12 * 2f); float[] array = new float[_toasts.Count]; float num17 = 0f; for (int j = 0; j < _toasts.Count; j++) { array[j] = MeasureToastRowHeight(val, _toasts[j].text, num16, shadowD, num); num17 += array[j]; } float num18 = num13 * 2f + num17; float num19 = _mod.ConfigToastBottomMarginPx.Value * num2; float num20 = (float)Screen.width - num15; float num21 = (float)Screen.height - num18 - num19; Rect r = default(Rect); ((Rect)(ref r))..ctor(num20, num21, num15, num18); DrawSolidToastFrame(r, num); GUI.color = new Color(0.95f, 0.96f, 0.98f, 1f); float num22 = ((Rect)(ref r)).y + num13; for (int num23 = _toasts.Count - 1; num23 >= 0; num23--) { float num24 = array[num23]; DrawLabelSoftShadow(new Rect(((Rect)(ref r)).x + num12, num22, num16, num24), _toasts[num23].text, val, num, val.richText); num22 += num24; } GUI.color = Color.white; GUI.depth = depth; } } private static float TimedRowHeight(float line, float gap) { return line * 1.06f + gap; } private static float ToastShadowOffset(float scale) { return Mathf.Max(1f, scale * 0.45f); } private static float MeasureToastContentWidth(GUIStyle st, string text, float shadowD, float scale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0009: Unknown result type (might be due to invalid IL or missing references) GUIContent val = new GUIContent(text); float num = Mathf.Ceil(st.CalcSize(val).x); float num2 = default(float); float num3 = default(float); st.CalcMinMaxWidth(val, ref num2, ref num3); num = Mathf.Max(new float[3] { num, Mathf.Ceil(num2), Mathf.Ceil(num3) }); num += shadowD * 2f + Mathf.Max(6f * scale, 4f); return num + Mathf.Ceil((float)st.fontSize * 0.22f); } private static float MeasureToastRowHeight(GUIStyle st, string text, float textW, float shadowD, float scale) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return Mathf.Max(Mathf.Ceil(st.CalcHeight(new GUIContent(text), textW)), Mathf.Ceil((float)st.fontSize * 1.34f)) + Mathf.Ceil(shadowD + 2f); } private static void DrawLabelSoftShadow(Rect r, string text, GUIStyle st, float scale, bool rich) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) st.richText = rich; float num = ToastShadowOffset(scale); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.42f); GUI.Label(new Rect(((Rect)(ref r)).x + num, ((Rect)(ref r)).y + num, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, st); GUI.Label(new Rect(((Rect)(ref r)).x - num, ((Rect)(ref r)).y + num, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, st); GUI.color = color; GUI.Label(r, text, st); } private GUIStyle StyleBody(float scale) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (_body == null) { _body = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)0, wordWrap = true, richText = true }; if ((Object)(object)_gameFont != (Object)null) { _body.font = _gameFont; } } _body.fontSize = Mathf.RoundToInt(12.5f * scale); return _body; } private GUIStyle StyleBodyBold(float scale, bool timed) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if (_bodyBold == null) { _bodyBold = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)0, alignment = (TextAnchor)0, wordWrap = true, richText = true }; if ((Object)(object)_gameFont != (Object)null) { _bodyBold.font = _gameFont; } } _bodyBold.fontSize = Mathf.RoundToInt((timed ? 17f : 12f) * scale); return _bodyBold; } } internal static class CrowdControlEffectPresentation { private static readonly Dictionary<string, (string Title, string Summary)> s_map = new Dictionary<string, (string, string)> { ["add_cash_50"] = ("+$50", "Shared cash."), ["add_cash_100"] = ("+$100", "Shared cash."), ["add_cash_500"] = ("+$500", "Shared cash."), ["add_cash_1000"] = ("+$1000", "Shared cash."), ["remove_cash_50"] = ("−$50", "Shared cash if affordable."), ["remove_cash_100"] = ("−$100", "Shared cash if affordable."), ["remove_cash_500"] = ("−$500", "Shared cash if affordable."), ["remove_cash_1000"] = ("−$1000", "Shared cash if affordable."), ["add_tickets_1"] = ("+1 ticket", "Shared tickets."), ["add_tickets_2"] = ("+2 tickets", "Shared tickets."), ["add_tickets_5"] = ("+5 tickets", "Shared tickets."), ["remove_tickets_1"] = ("−1 ticket", "Shared tickets if possible."), ["remove_tickets_2"] = ("−2 tickets", "Shared tickets if possible."), ["remove_tickets_5"] = ("−5 tickets", "Shared tickets if possible."), ["grant_auxiliary_money"] = ("Auxiliary payout", "Quota-day auxiliary cash (host applies)."), ["add_day_time"] = ("+Day time", "Shared day timer."), ["remove_day_time"] = ("−Day time", "Shared day timer."), ["casino_house_crush"] = ("Cold tables", "Payouts crash toward zero on every table (whole group)."), ["casino_hot_table"] = ("Hot tables", "Better table payouts (whole group)."), ["casino_maxbet_surge"] = ("Double Cap on Bets", "Doubles max-bet limits on every table (whole group)."), ["casino_oops_max_bets"] = ("Opps, all max bets!", "Snaps open tables to max wager (whole group)."), ["luck_tipsy_surge"] = ("Tipsy fortune ↑", "Better win slice for you."), ["luck_tipsy_hangover"] = ("Tipsy fortune ↓", "Worse win slice for you."), ["buff_drink_tipsy"] = ("Drunk", "Drink-style buff on streamer: fortune up, more profit while drunk (includes short wobble voice effect)."), ["buff_immunity"] = ("Immunity aura", "Holy Statue–style: block losses for you and nearby players."), ["buff_inspiring_melody"] = ("Inspiring melody", "Mic-style buff: profit boost for nearby players while active."), ["upgrade_insurance_boost"] = ("Insurance ↑", "Softer losses on payouts."), ["upgrade_bonus_draw_boost"] = ("Bonus Draw ↑", "Extra ticket chance on wins."), ["upgrade_stakeholder_boost"] = ("Stakeholder ↑", "Stronger drink / tipsy scaling."), ["upgrade_gamblers_confidence_nerf"] = ("Confidence ↓", "Small GC tick down."), ["upgrade_gamblers_confidence_boost"] = ("Confidence ↑", "Small GC tick up."), ["upgrade_reset_run"] = ("Reset upgrades", "Your run upgrades to default."), ["reset_balances"] = ("Reset balances", "Money & tickets to defaults."), ["player_movement_fast"] = ("Fast movement", "Higher move speed."), ["player_movement_slow"] = ("Slow movement", "Lower move speed."), ["player_movement_very_slow"] = ("Very slow", "Much lower move speed."), ["spawn_bat"] = ("Spawn bat", "Bat pickup in front of you."), ["spawn_drink"] = ("Spawn drink", "Drink bottle: tipsy fortune + drunk profit."), ["spawn_immunity_cross"] = ("Spawn Holy Statue", "Immunity cross / statue pickup."), ["spawn_microphone"] = ("Spawn mic", "Microphone: Inspiring Melody for allies."), ["spawn_coordinator"] = ("Spawn coordinator", "Coordinator camera pickup."), ["spawn_golden_chip"] = ("Spawn golden chip", "Golden chip pickup."), ["spawn_devils_reel"] = ("Spawn Devil's Reel", "Pickup."), ["spawn_angels_reel"] = ("Spawn Angel's Reel", "Pickup."), ["spawn_time_machine"] = ("Spawn time machine", "Pickup."), ["spawn_taser"] = ("Spawn taser", "Pickup."), ["spawn_quota_gun"] = ("Spawn quota gun", "Pickup."), ["spawn_mystery_box"] = ("Spawn mystery box", "Pickup."), ["spawn_upgrade_stakeholder"] = ("Spawn Stakeholder upgrade", "Upgrade pickup."), ["spawn_upgrade_insurance"] = ("Spawn Insurance upgrade", "Upgrade pickup."), ["spawn_upgrade_bonus_draw"] = ("Spawn Bonus Draw upgrade", "Upgrade pickup."), ["spawn_upgrade_gamblers_confidence"] = ("Spawn Gambler's Confidence", "Upgrade pickup near you."), ["spawn_holy_statue"] = ("Spawn Holy Statue", "Same immunity-cross pickup as spawn_immunity_cross in this build (catalog id 10)."), ["spawn_voice_wand"] = ("Spawn voice wand", "Toy that cycles voice effects while held."), ["spawn_gacha_sphere"] = ("Spawn gacha sphere", "Cosmetic capsule (catalog “Cosmetic Item”, id 1)."), ["spawn_basketball"] = ("Spawn basketball", "Ball pickup if prefab is registered (e.g. hoop minigame assets loaded)."), ["spawn_sledding_frog"] = ("Spawn sledding frog", "Plush from Mirror spawn list or loaded prefab prototypes."), ["spawn_bongo"] = ("Spawn bongos", "From spawn prefabs / prototypes when available."), ["spawn_dice"] = ("Spawn dice", "From spawn prefabs / prototypes when available."), ["spawn_chess_piece"] = ("Spawn chess piece", "From spawn prefabs / prototypes when available."), ["spawn_bingbong"] = ("Spawn Bing Bong", "Plush whose name hints match bing/bong in spawn data."), ["spawn_debt_bag"] = ("Spawn debt bag", "From DebtBagMachine prefab or spawn list when that scene exists."), ["cosmetic_random_piece"] = ("Random cosmetic", "Random piece on you."), ["cosmetic_reset_outfit"] = ("Reset outfit", "Default outfit."), ["cosmetic_clear_hats"] = ("Clear hats", "Hat slot cleared."), ["voice_low"] = ("Low voice effect", "Low pitch on your outgoing voice."), ["voice_wobble"] = ("Wobble voice effect", "Wobble filter on your outgoing voice."), ["voice_radio"] = ("Radio voice effect", "Radio-style filter on your outgoing voice."), ["voice_no_mouth_on"] = ("No-mouth on", "Voice appearance filter on."), ["voice_no_mouth_off"] = ("No-mouth off", "Voice appearance filter off."), ["voice_reset"] = ("Reset voice effects", "Clear voice filters.") }; internal static bool TryGet(string? code, out string title, out string summary) { title = ""; summary = ""; if (string.IsNullOrEmpty(code)) { return false; } if (s_map.TryGetValue(code, out (string, string) value)) { (title, summary) = value; return true; } title = Humanize(code); summary = ""; return true; } private static string Humanize(string code) { return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(code.Replace('_', ' ')); } } internal static class CrowdControlGlobalHudMirror { internal static void Announce(string? code, uint requestId, float durationSeconds) { if (!string.IsNullOrEmpty(code) && CrowdControlGlobalHudMirrorCodes.CodesSet.Contains(code)) { if (NetworkServer.active) { NetworkConnection excludeConnection = (NetworkConnection)(object)((NetworkClient.active && NetworkServer.localConnection != null) ? NetworkServer.localConnection : null); CrowdControlGlobalTimedHud.ServerBroadcastByCode(requestId, code, durationSeconds, excludeConnection); } else { CrowdControlGlobalHudMirrorNetwork.ClientSendAnnounce(requestId, code, durationSeconds); } } } internal static void AnnounceEnd(uint requestId) { if (NetworkServer.active) { NetworkConnection excludeConnection = (NetworkConnection)(object)((NetworkClient.active && NetworkServer.localConnection != null) ? NetworkServer.localConnection : null); CrowdControlGlobalTimedHud.ServerBroadcastRemove(requestId, excludeConnection); } else { CrowdControlGlobalHudMirrorNetwork.ClientSendRemove(requestId); } } } internal static class CrowdControlGlobalHudMirrorCodes { internal static readonly HashSet<string> CodesSet = new HashSet<string>(StringComparer.Ordinal) { "buff_immunity", "buff_inspiring_melody", "buff_drink_tipsy", "luck_tipsy_surge", "luck_tipsy_hangover", "player_movement_fast", "player_movement_slow", "player_movement_very_slow", "voice_low", "voice_wobble", "voice_radio" }; } internal struct CrowdControlGlobalTimedHudCodeMsg : NetworkMessage { public uint RequestId; public string Code; public float DurationSeconds; } internal struct CrowdControlGlobalHudMirrorAnnounceFromClient : NetworkMessage { public uint RequestId; public string Code; public float DurationSeconds; } internal struct CrowdControlGlobalTimedHudRemoveMsg : NetworkMessage { public uint RequestId; } internal struct CrowdControlGlobalHudMirrorRemoveFromClient : NetworkMessage { public uint RequestId; } internal static class CrowdControlGlobalHudMirrorNetwork { private static bool _serverHandlerInstalled; internal static void InstallSerialization() { Writer<CrowdControlGlobalTimedHudCodeMsg>.write = delegate(NetworkWriter w, CrowdControlGlobalTimedHudCodeMsg v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); NetworkWriterExtensions.WriteString(w, v.Code ?? string.Empty); NetworkWriterExtensions.WriteFloat(w, v.DurationSeconds); }; Reader<CrowdControlGlobalTimedHudCodeMsg>.read = delegate(NetworkReader r) { CrowdControlGlobalTimedHudCodeMsg result4 = default(CrowdControlGlobalTimedHudCodeMsg); result4.RequestId = NetworkReaderExtensions.ReadUInt(r); result4.Code = NetworkReaderExtensions.ReadString(r); result4.DurationSeconds = NetworkReaderExtensions.ReadFloat(r); return result4; }; Writer<CrowdControlGlobalHudMirrorAnnounceFromClient>.write = delegate(NetworkWriter w, CrowdControlGlobalHudMirrorAnnounceFromClient v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); NetworkWriterExtensions.WriteString(w, v.Code ?? string.Empty); NetworkWriterExtensions.WriteFloat(w, v.DurationSeconds); }; Reader<CrowdControlGlobalHudMirrorAnnounceFromClient>.read = delegate(NetworkReader r) { CrowdControlGlobalHudMirrorAnnounceFromClient result3 = default(CrowdControlGlobalHudMirrorAnnounceFromClient); result3.RequestId = NetworkReaderExtensions.ReadUInt(r); result3.Code = NetworkReaderExtensions.ReadString(r); result3.DurationSeconds = NetworkReaderExtensions.ReadFloat(r); return result3; }; Writer<CrowdControlGlobalTimedHudRemoveMsg>.write = delegate(NetworkWriter w, CrowdControlGlobalTimedHudRemoveMsg v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); }; Reader<CrowdControlGlobalTimedHudRemoveMsg>.read = delegate(NetworkReader r) { CrowdControlGlobalTimedHudRemoveMsg result2 = default(CrowdControlGlobalTimedHudRemoveMsg); result2.RequestId = NetworkReaderExtensions.ReadUInt(r); return result2; }; Writer<CrowdControlGlobalHudMirrorRemoveFromClient>.write = delegate(NetworkWriter w, CrowdControlGlobalHudMirrorRemoveFromClient v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); }; Reader<CrowdControlGlobalHudMirrorRemoveFromClient>.read = delegate(NetworkReader r) { CrowdControlGlobalHudMirrorRemoveFromClient result = default(CrowdControlGlobalHudMirrorRemoveFromClient); result.RequestId = NetworkReaderExtensions.ReadUInt(r); return result; }; } internal static void RegisterServerHandlerIfNeeded() { InstallSerialization(); if (!_serverHandlerInstalled && NetworkServer.active) { NetworkServer.ReplaceHandler<CrowdControlGlobalHudMirrorAnnounceFromClient>((Action<NetworkConnectionToClient, CrowdControlGlobalHudMirrorAnnounceFromClient>)OnServerAnnounceFromClient, true); NetworkServer.ReplaceHandler<CrowdControlGlobalHudMirrorRemoveFromClient>((Action<NetworkConnectionToClient, CrowdControlGlobalHudMirrorRemoveFromClient>)OnServerRemoveFromClient, true); _serverHandlerInstalled = true; CrowdControlMod.Instance.Logger.LogInfo((object)"Crowd Control: registered global HUD mirror announce (client → host)."); } } internal static void UnregisterServerHandlerIfNeeded() { if (_serverHandlerInstalled) { NetworkServer.UnregisterHandler<CrowdControlGlobalHudMirrorAnnounceFromClient>(); NetworkServer.UnregisterHandler<CrowdControlGlobalHudMirrorRemoveFromClient>(); _serverHandlerInstalled = false; } } private static void OnServerAnnounceFromClient(NetworkConnectionToClient conn, CrowdControlGlobalHudMirrorAnnounceFromClient msg) { if (conn != null && !string.IsNullOrEmpty(msg.Code) && CrowdControlGlobalHudMirrorCodes.CodesSet.Contains(msg.Code)) { CrowdControlGlobalTimedHud.ServerBroadcastByCode(msg.RequestId, msg.Code, msg.DurationSeconds, (NetworkConnection?)(object)conn); } } private static void OnServerRemoveFromClient(NetworkConnectionToClient conn, CrowdControlGlobalHudMirrorRemoveFromClient msg) { if (conn != null) { CrowdControlGlobalTimedHud.ServerBroadcastRemove(msg.RequestId, (NetworkConnection?)(object)conn); } } internal static bool ClientSendAnnounce(uint requestId, string code, float durationSeconds) { InstallSerialization(); if (!NetworkClient.isConnected) { return false; } if (NetworkClient.connection == null) { return false; } if (string.IsNullOrEmpty(code) || !CrowdControlGlobalHudMirrorCodes.CodesSet.Contains(code)) { return false; } CrowdControlGlobalHudMirrorAnnounceFromClient crowdControlGlobalHudMirrorAnnounceFromClient = default(CrowdControlGlobalHudMirrorAnnounceFromClient); crowdControlGlobalHudMirrorAnnounceFromClient.RequestId = requestId; crowdControlGlobalHudMirrorAnnounceFromClient.Code = code; crowdControlGlobalHudMirrorAnnounceFromClient.DurationSeconds = durationSeconds; NetworkClient.Send<CrowdControlGlobalHudMirrorAnnounceFromClient>(crowdControlGlobalHudMirrorAnnounceFromClient, 0); return true; } internal static bool ClientSendRemove(uint requestId) { InstallSerialization(); if (!NetworkClient.isConnected) { return false; } if (NetworkClient.connection == null) { return false; } CrowdControlGlobalHudMirrorRemoveFromClient crowdControlGlobalHudMirrorRemoveFromClient = default(CrowdControlGlobalHudMirrorRemoveFromClient); crowdControlGlobalHudMirrorRemoveFromClient.RequestId = requestId; NetworkClient.Send<CrowdControlGlobalHudMirrorRemoveFromClient>(crowdControlGlobalHudMirrorRemoveFromClient, 0); return true; } } internal static class CrowdControlGlobalTimedHud { private static bool _clientHandlersInstalled; internal static void InstallClientHandlerIfNeeded() { if (!_clientHandlersInstalled) { CrowdControlGlobalHudMirrorNetwork.InstallSerialization(); NetworkClient.ReplaceHandler<CrowdControlGlobalTimedHudMsg>((Action<CrowdControlGlobalTimedHudMsg>)OnGlobalTimedHud, true); NetworkClient.ReplaceHandler<CrowdControlGlobalTimedHudCodeMsg>((Action<CrowdControlGlobalTimedHudCodeMsg>)OnGlobalTimedHudByCode, true); NetworkClient.ReplaceHandler<CrowdControlGlobalTimedHudRemoveMsg>((Action<CrowdControlGlobalTimedHudRemoveMsg>)OnGlobalTimedHudRemove, true); _clientHandlersInstalled = true; } } internal static void UninstallClientHandlerIfNeeded() { if (_clientHandlersInstalled) { NetworkClient.UnregisterHandler<CrowdControlGlobalTimedHudMsg>(); NetworkClient.UnregisterHandler<CrowdControlGlobalTimedHudCodeMsg>(); NetworkClient.UnregisterHandler<CrowdControlGlobalTimedHudRemoveMsg>(); _clientHandlersInstalled = false; } } private static void OnGlobalTimedHud(CrowdControlGlobalTimedHudMsg msg) { string text = CrowdControlHostCcServerExecutor.CodeString((CrowdControlHostCcEffectCode)msg.EffectCode); if (!string.IsNullOrEmpty(text)) { CrowdControlEffectHud.NotifyNetworkTimed(text, msg.RequestId, msg.DurationSeconds); } } private static void OnGlobalTimedHudByCode(CrowdControlGlobalTimedHudCodeMsg msg) { if (!string.IsNullOrEmpty(msg.Code)) { CrowdControlEffectHud.NotifyNetworkTimed(msg.Code, msg.RequestId, msg.DurationSeconds); } } private static void OnGlobalTimedHudRemove(CrowdControlGlobalTimedHudRemoveMsg msg) { CrowdControlEffectHud.NotifyMirrorTimedEnded(msg.RequestId); } internal static void ServerBroadcast(uint requestId, CrowdControlHostCcEffectCode effectCode, float durationSeconds, NetworkConnection? excludeConnection) { if (!NetworkServer.active) { return; } CrowdControlGlobalTimedHudMsg crowdControlGlobalTimedHudMsg = default(CrowdControlGlobalTimedHudMsg); crowdControlGlobalTimedHudMsg.RequestId = requestId; crowdControlGlobalTimedHudMsg.EffectCode = (ushort)effectCode; crowdControlGlobalTimedHudMsg.DurationSeconds = durationSeconds; CrowdControlGlobalTimedHudMsg crowdControlGlobalTimedHudMsg2 = crowdControlGlobalTimedHudMsg; foreach (NetworkConnectionToClient value in NetworkServer.connections.Values) { NetworkConnectionToClient val = ((value is NetworkConnectionToClient) ? value : null); if (val != null && (excludeConnection == null || val != excludeConnection)) { ((NetworkConnection)val).Send<CrowdControlGlobalTimedHudMsg>(crowdControlGlobalTimedHudMsg2, 0); } } } internal static void ServerBroadcastByCode(uint requestId, string code, float durationSeconds, NetworkConnection? excludeConnection) { if (!NetworkServer.active) { return; } CrowdControlGlobalTimedHudCodeMsg crowdControlGlobalTimedHudCodeMsg = default(CrowdControlGlobalTimedHudCodeMsg); crowdControlGlobalTimedHudCodeMsg.RequestId = requestId; crowdControlGlobalTimedHudCodeMsg.Code = code; crowdControlGlobalTimedHudCodeMsg.DurationSeconds = durationSeconds; CrowdControlGlobalTimedHudCodeMsg crowdControlGlobalTimedHudCodeMsg2 = crowdControlGlobalTimedHudCodeMsg; foreach (NetworkConnectionToClient value in NetworkServer.connections.Values) { NetworkConnectionToClient val = ((value is NetworkConnectionToClient) ? value : null); if (val != null && (excludeConnection == null || val != excludeConnection)) { ((NetworkConnection)val).Send<CrowdControlGlobalTimedHudCodeMsg>(crowdControlGlobalTimedHudCodeMsg2, 0); } } } internal static void ServerBroadcastRemove(uint requestId, NetworkConnection? excludeConnection) { if (!NetworkServer.active) { return; } CrowdControlGlobalTimedHudRemoveMsg crowdControlGlobalTimedHudRemoveMsg = default(CrowdControlGlobalTimedHudRemoveMsg); crowdControlGlobalTimedHudRemoveMsg.RequestId = requestId; CrowdControlGlobalTimedHudRemoveMsg crowdControlGlobalTimedHudRemoveMsg2 = crowdControlGlobalTimedHudRemoveMsg; foreach (NetworkConnectionToClient value in NetworkServer.connections.Values) { NetworkConnectionToClient val = ((value is NetworkConnectionToClient) ? value : null); if (val != null && (excludeConnection == null || val != excludeConnection)) { ((NetworkConnection)val).Send<CrowdControlGlobalTimedHudRemoveMsg>(crowdControlGlobalTimedHudRemoveMsg2, 0); } } } } internal enum CrowdControlHostCcEffectCode : ushort { None, AddDayTime, RemoveDayTime, GrantAuxiliaryMoney, CasinoHouseCrush, CasinoHotTable, CasinoMaxBetSurge, CasinoOopsMaxBets } internal enum CrowdControlHostCcKind : byte { Instant = 1, TimedStart, TimedStop } internal struct CrowdControlHostCcFromClient : NetworkMessage { public byte Kind; public ushort EffectCode; public uint RequestId; public float DurationSeconds; } internal struct CrowdControlHostCcToClient : NetworkMessage { public uint RequestId; public byte Status; public string Message; } internal struct CrowdControlGlobalTimedHudMsg : NetworkMessage { public uint RequestId; public ushort EffectCode; public float DurationSeconds; } internal static class CrowdControlHostCcRelay { internal const byte StatusOk = 0; internal const byte StatusFail = 1; internal const byte StatusConflict = 2; private static bool _serverHandlerInstalled; private static readonly Dictionary<uint, (byte status, string message)> _pendingResults = new Dictionary<uint, (byte, string)>(); private static bool RelayLogEnabled { get { if ((Object)(object)CrowdControlMod.Instance != (Object)null) { return CrowdControlMod.Instance.ConfigLogClientHostCcRelay.Value; } return false; } } private static void LogRelay(string line) { if (RelayLogEnabled) { CrowdControlMod.Instance.Logger.LogMessage((object)("[Crowd Control][HostCcRelay] " + line)); } } private static string FormatKind(byte kind) { return (CrowdControlHostCcKind)kind switch { CrowdControlHostCcKind.Instant => "Instant", CrowdControlHostCcKind.TimedStart => "TimedStart", CrowdControlHostCcKind.TimedStop => "TimedStop", _ => $"Unknown({kind})", }; } private static string FormatEffect(ushort effectCode) { CrowdControlHostCcEffectCode crowdControlHostCcEffectCode = (CrowdControlHostCcEffectCode)effectCode; string text = CrowdControlHostCcServerExecutor.CodeString(crowdControlHostCcEffectCode); if (!string.IsNullOrEmpty(text)) { return $"{crowdControlHostCcEffectCode} ({text})"; } return $"effectCode={effectCode}"; } private static int ConnectionLogId(NetworkConnection conn) { return ((NetworkConnectionToClient)(((conn is NetworkConnectionToClient) ? conn : null)?)).connectionId ?? (-1); } internal static bool TryConsumeResponse(uint requestId, out EffectResponse response) { if (!_pendingResults.TryGetValue(requestId, out (byte, string) value)) { response = null; return false; } _pendingResults.Remove(requestId); response = (EffectResponse)(value.Item1 switch { 0 => EffectResponse.Success(requestId, (string)null), 2 => EffectResponse.Failure(requestId, (StandardErrors)32768), _ => string.IsNullOrEmpty(value.Item2) ? EffectResponse.Failure(requestId, (StandardErrors)16384) : EffectResponse.Failure(requestId, value.Item2), }); return true; } internal static void ClearPending(uint requestId) { _pendingResults.Remove(requestId); } internal static void InstallSerialization() { Writer<CrowdControlHostCcFromClient>.write = delegate(NetworkWriter w, CrowdControlHostCcFromClient v) { w.WriteByte(v.Kind); NetworkWriterExtensions.WriteUInt(w, (uint)v.EffectCode); NetworkWriterExtensions.WriteUInt(w, v.RequestId); NetworkWriterExtensions.WriteFloat(w, v.DurationSeconds); }; Reader<CrowdControlHostCcFromClient>.read = delegate(NetworkReader r) { CrowdControlHostCcFromClient result3 = default(CrowdControlHostCcFromClient); result3.Kind = r.ReadByte(); result3.EffectCode = checked((ushort)NetworkReaderExtensions.ReadUInt(r)); result3.RequestId = NetworkReaderExtensions.ReadUInt(r); result3.DurationSeconds = NetworkReaderExtensions.ReadFloat(r); return result3; }; Writer<CrowdControlHostCcToClient>.write = delegate(NetworkWriter w, CrowdControlHostCcToClient v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); w.WriteByte(v.Status); NetworkWriterExtensions.WriteString(w, v.Message ?? string.Empty); }; Reader<CrowdControlHostCcToClient>.read = delegate(NetworkReader r) { CrowdControlHostCcToClient result2 = default(CrowdControlHostCcToClient); result2.RequestId = NetworkReaderExtensions.ReadUInt(r); result2.Status = r.ReadByte(); result2.Message = NetworkReaderExtensions.ReadString(r); return result2; }; Writer<CrowdControlGlobalTimedHudMsg>.write = delegate(NetworkWriter w, CrowdControlGlobalTimedHudMsg v) { NetworkWriterExtensions.WriteUInt(w, v.RequestId); NetworkWriterExtensions.WriteUInt(w, (uint)v.EffectCode); NetworkWriterExtensions.WriteFloat(w, v.DurationSeconds); }; Reader<CrowdControlGlobalTimedHudMsg>.read = delegate(NetworkReader r) { CrowdControlGlobalTimedHudMsg result = default(CrowdControlGlobalTimedHudMsg); result.RequestId = NetworkReaderExtensions.ReadUInt(r); result.EffectCode = checked((ushort)NetworkReaderExtensions.ReadUInt(r)); result.DurationSeconds = NetworkReaderExtensions.ReadFloat(r); return result; }; CrowdControlGlobalHudMirrorNetwork.InstallSerialization(); } internal static void RegisterServerHandlerIfNeeded() { InstallSerialization(); if (!_serverHandlerInstalled && NetworkServer.active) { NetworkServer.ReplaceHandler<CrowdControlHostCcFromClient>((Action<NetworkConnectionToClient, CrowdControlHostCcFromClient>)OnServerHostCcFromClient, true); _serverHandlerInstalled = true; CrowdControlMod.Instance.Logger.LogInfo((object)"Crowd Control: registered host CC relay (client → host)."); } } internal static void UnregisterServerHandlerIfNeeded() { if (_serverHandlerInstalled) { NetworkServer.UnregisterHandler<CrowdControlHostCcFromClient>(); _serverHandlerInstalled = false; } } private static void OnServerHostCcFromClient(NetworkConnectionToClient conn, CrowdControlHostCcFromClient msg) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Invalid comparison between Unknown and I4 //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (conn == null) { return; } LogRelay($"Host received: connId={ConnectionLogId((NetworkConnection)(object)conn)} kind={FormatKind(msg.Kind)} {FormatEffect(msg.EffectCode)} requestId={msg.RequestId} durationSeconds={msg.DurationSeconds:F2}"); byte kind = msg.Kind; bool flag = (uint)(kind - 1) <= 1u; if (flag && GameStateManager.RequiresActiveCasinoPlay(CrowdControlHostCcServerExecutor.CodeString((CrowdControlHostCcEffectCode)msg.EffectCode))) { GameStateManager gameStateManager = CrowdControlMod.Instance?.GameStateManager; if (gameStateManager != null && !gameStateManager.IsStrictCasinoGamblingReady()) { ((NetworkConnection)conn).Send<CrowdControlHostCcToClient>(new CrowdControlHostCcToClient { RequestId = msg.RequestId, Status = 1, Message = "This effect is not available in the current game state (need an active casino day / timer)." }, 0); return; } } CrowdControlHostCcToClient crowdControlHostCcToClient = default(CrowdControlHostCcToClient); crowdControlHostCcToClient.RequestId = msg.RequestId; crowdControlHostCcToClient.Status = 1; crowdControlHostCcToClient.Message = string.Empty; CrowdControlHostCcToClient crowdControlHostCcToClient2 = crowdControlHostCcToClient; switch ((CrowdControlHostCcKind)msg.Kind) { case CrowdControlHostCcKind.Instant: { EffectResponse val = CrowdControlHostCcServerExecutor.TryInstant((CrowdControlHostCcEffectCode)msg.EffectCode, msg.RequestId); crowdControlHostCcToClient2.Status = (((int)val.status > 0) ? ((byte)1) : ((byte)0)); crowdControlHostCcToClient2.Message = (((int)val.status == 0) ? string.Empty : (val.message ?? string.Empty)); break; } case CrowdControlHostCcKind.TimedStart: { CrowdControlHostCcEffectCode effectCode = (CrowdControlHostCcEffectCode)msg.EffectCode; if (!CrowdControlHostCcServerExecutor.TryTimedStart(effectCode, msg.RequestId, msg.DurationSeconds, out var conflict)) { crowdControlHostCcToClient2.Status = (byte)((!conflict) ? 1 : 2); break; } crowdControlHostCcToClient2.Status = 0; CrowdControlGlobalTimedHud.ServerBroadcast(msg.RequestId, effectCode, msg.DurationSeconds, (NetworkConnection?)(object)conn); break; } case CrowdControlHostCcKind.TimedStop: CrowdControlHostCcServerExecutor.TimedStop(msg.RequestId); crowdControlHostCcToClient2.Status = 0; break; } ((NetworkConnection)conn).Send<CrowdControlHostCcToClient>(crowdControlHostCcToClient2, 0); } internal static bool ClientSendInstant(CrowdControlHostCcEffectCode code, uint requestId) { InstallSerialization(); if (!NetworkClient.isConnected) { return false; } NetworkConnection connection = (NetworkConnection)(object)NetworkClient.connection; if (connection == null) { return false; } CrowdControlHostCcFromClient crowdControlHostCcFromClient = default(CrowdControlHostCcFromClient); crowdControlHostCcFromClient.Kind = 1; crowdControlHostCcFromClient.EffectCode = (ushort)code; crowdControlHostCcFromClient.RequestId = requestId; crowdControlHostCcFromClient.DurationSeconds = 0f; CrowdControlHostCcFromClient crowdControlHostCcFromClient2 = crowdControlHostCcFromClient; LogRelay($"Client sending: connId={ConnectionLogId(connection)} kind=Instant {FormatEffect(crowdControlHostCcFromClient2.EffectCode)} requestId={requestId}"); NetworkClient.Send<CrowdControlHostCcFromClient>(crowdControlHostCcFromClient2, 0); return true; } internal static bool ClientSendTimedStart(CrowdControlHostCcEffectCode code, uint requestId, float durationSeconds) { InstallSerialization(); if (!NetworkClient.isConnected) { return false; } NetworkConnection connection = (NetworkConnection)(object)NetworkClient.connection; if (connection == null) { return false; } CrowdControlHostCcFromClient crowdControlHostCcFromClient = default(CrowdControlHostCcFromClient); crowdControlHostCcFromClient.Kind = 2; crowdControlHostCcFromClient.EffectCode = (ushort)code; crowdControlHostCcFromClient.RequestId = requestId; crowdControlHostCcFromClient.DurationSeconds = durationSeconds; CrowdControlHostCcFromClient crowdControlHostCcFromClient2 = crowdControlHostCcFromClient; LogRelay($"Client sending: connId={ConnectionLogId(connection)} kind=TimedStart {FormatEffect(crowdControlHostCcFromClient2.EffectCode)} requestId={requestId} durationSeconds={durationSeconds:F2}"); NetworkClient.Send<CrowdControlHostCcFromClient>(crowdControlHostCcFromClient2, 0); return true; } internal static void ClientSendTimedStop(uint requestId) { InstallSerialization(); if (NetworkClient.isConnected) { NetworkConnection connection = (NetworkConnection)(object)NetworkClient.connection; if (connection != null) { CrowdControlHostCcFromClient crowdControlHostCcFromClient = default(CrowdControlHostCcFromClient); crowdControlHostCcFromClient.Kind = 3; crowdControlHostCcFromClient.EffectCode = 0; crowdControlHostCcFromClient.RequestId = requestId; crowdControlHostCcFromClient.DurationSeconds = 0f; CrowdControlHostCcFromClient crowdControlHostCcFromClient2 = crowdControlHostCcFromClient; LogRelay($"Client sending: connId={ConnectionLogId(connection)} kind=TimedStop requestId={requestId}"); NetworkClient.Send<CrowdControlHostCcFromClient>(crowdControlHostCcFromClient2, 0); } } } private static void OnClientHostCcToClient(CrowdControlHostCcToClient msg) { _pendingResults[msg.RequestId] = (msg.Status, msg.Message ?? string.Empty); } internal static void RegisterClientResponseHandlerIfNeeded() { InstallSerialization(); NetworkClient.ReplaceHandler<CrowdControlHostCcToClient>((Action<CrowdControlHostCcToClient>)OnClientHostCcToClient, true); } internal static void UnregisterClientResponseHandlerIfNeeded() { NetworkClient.UnregisterHandler<CrowdControlHostCcToClient>(); } internal static bool NeedsRelayHost(string code) { return CrowdControlHostOnlyEffectCodes.CodesSet.Contains(code); } internal static bool TryMapCode(string code, out CrowdControlHostCcEffectCode effectCode) { switch (code) { case "add_day_time": effectCode = CrowdControlHostCcEffectCode.AddDayTime; return true; case "remove_day_time": effectCode = CrowdControlHostCcEffectCode.RemoveDayTime; return true; case "grant_auxiliary_money": effectCode = CrowdControlHostCcEffectCode.GrantAuxiliaryMoney; return true; case "casino_house_crush": effectCode = CrowdControlHostCcEffectCode.CasinoHouseCrush; return true; case "casino_hot_table": effectCode = CrowdControlHostCcEffectCode.CasinoHotTable; return true; case "casino_maxbet_surge": effectCode = CrowdControlHostCcEffectCode.CasinoMaxBetSurge; return true; case "casino_oops_max_bets": effectCode = CrowdControlHostCcEffectCode.CasinoOopsMaxBets; return true; default: effectCode = CrowdControlHostCcEffectCode.None; return false; } } } internal static class CrowdControlHostCcServerExecutor { internal static EffectResponse TryInstant(CrowdControlHostCcEffectCode code, uint requestId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown EffectRequest request = new EffectRequest { id = requestId, code = CodeString(code) }; return (EffectResponse)(code switch { CrowdControlHostCcEffectCode.AddDayTime => AddDayTimeCore(request), CrowdControlHostCcEffectCode.RemoveDayTime => RemoveDayTimeCore(request), CrowdControlHostCcEffectCode.GrantAuxiliaryMoney => GrantAuxiliaryMoneyCore(request), _ => EffectResponse.Failure(requestId, (StandardErrors)4097), }); } internal static string? CodeString(CrowdControlHostCcEffectCode code) { return code switch { CrowdControlHostCcEffectCode.AddDayTime => "add_day_time", CrowdControlHostCcEffectCode.RemoveDayTime => "remove_day_time", CrowdControlHostCcEffectCode.GrantAuxiliaryMoney => "grant_auxiliary_money", CrowdControlHostCcEffectCode.CasinoHouseCrush => "casino_house_crush", CrowdControlHostCcEffectCode.CasinoHotTable => "casino_hot_table", CrowdControlHostCcEffectCode.CasinoMaxBetSurge => "casino_maxbet_surge", CrowdControlHostCcEffectCode.CasinoOopsMaxBets => "casino_oops_max_bets", _ => null, }; } internal static EffectResponse AddDayTimeCore(EffectRequest request) { GameManager instance = NetworkSingleton<GameManager>.Instance; if ((Object)(object)instance == (Object)null) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, (StandardErrors)16640); } GameSettings val = Resources.Load<GameSettings>("GameSettings"); if ((Object)(object)val == (Object)null) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, (StandardErrors)16640); } if (!GwyfDayTimerRules.CanAddRemainingSeconds(val, instance, 30f)) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, GwyfDayTimerRules.DescribeCannotAddTime(val, instance, 30f)); } instance.ServerAdjustTimer(-30f); GameStateManager.LogCrowdControl($"ServerAdjustTimer({-30f}) — ~30s more day time (host)."); return EffectResponse.Success(((SimpleJSONMessage)request).ID, (string)null); } internal static EffectResponse RemoveDayTimeCore(EffectRequest request) { GameManager instance = NetworkSingleton<GameManager>.Instance; if ((Object)(object)instance == (Object)null) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, (StandardErrors)16640); } GameSettings val = Resources.Load<GameSettings>("GameSettings"); if ((Object)(object)val == (Object)null) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, (StandardErrors)16640); } if (!GwyfDayTimerRules.CanRemoveRemainingSeconds(val, instance, 30f)) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, GwyfDayTimerRules.DescribeCannotRemoveTime(val, instance, 30f)); } instance.ServerAdjustTimer(30f); GameStateManager.LogCrowdControl($"ServerAdjustTimer(+{30f}) — day ends sooner (host)."); return EffectResponse.Success(((SimpleJSONMessage)request).ID, (string)null); } internal static EffectResponse GrantAuxiliaryMoneyCore(EffectRequest request) { GameManager instance = NetworkSingleton<GameManager>.Instance; if ((Object)(object)instance == (Object)null) { return EffectResponse.Failure(((SimpleJSONMessage)request).ID, (StandardErrors)16640); } instance.ServerGetAuxiliaryMoney(); GameStateManager.LogCrowdControl("ServerGetAuxiliaryMoney (host)."); return EffectResponse.Success(((SimpleJSONMessage)request).ID, (string)null); } internal static bool TryTimedStart(CrowdControlHostCcEffectCode code, uint requestId, float durationSeconds, out bool conflict) { conflict = false; if (CrowdControlHostTimedRelaySessions.HasConflict(code)) { conflict = true; return false; } switch (code) { case CrowdControlHostCcEffectCode.CasinoHouseCrush: CrowdControlHostTimedRelaySessions.RegisterHouseCrush(requestId, durationSeconds); return true; case CrowdControlHostCcEffectCode.CasinoHotTable: CrowdControlHostTimedRelaySessions.RegisterHotTable(requestId, durationSeconds); return true; case CrowdControlHostCcEffectCode.CasinoMaxBetSurge: CrowdControlHostTimedRelaySessions.RegisterMaxBetSurge(requestId, durationSeconds); return true; case CrowdControlHostCcEffectCode.CasinoOopsMaxBets: CrowdControlHostTimedRelaySessions.RegisterOopsMaxBets(requestId, durationSeconds); return true; default: return false; } } internal static void TimedStop(uint requestId) { CrowdControlHostTimedRelaySessions.Stop(requestId); } } internal static class CrowdControlHostOnlyEffectCodes { internal static readonly string[] Codes = new string[7] { "add_day_time", "remove_day_time", "grant_auxiliary_money", "casino_house_crush", "casino_hot_table", "casino_maxbet_surge", "casino_oops_max_bets" }; internal static readonly HashSet<string> CodesSet = new HashSet<string>(Codes, StringComparer.Ordinal); } internal static class CrowdControlHostTimedRelaySessions { private sealed class Session { public CrowdControlHostCcEffectCode Code; public uint RequestId; public float TimeLeft; public float OopsAccum; } private static readonly Dictionary<uint, Session> Sessions = new Dictionary<uint, Session>(); internal static bool HasConflict(CrowdControlHostCcEffectCode code) { foreach (Session value in Sessions.Values) { if (Conflicts(value.Code, code)) { return true; } } bool flag = code - 4 <= CrowdControlHostCcEffectCode.AddDayTime; if (flag && CasinoTimedOdds.HasAnyEstimatedSession()) { return true; } if (code - 6 <= CrowdControlHostCcEffectCode.AddDayTime) { if (CasinoTimedOdds.HasAnyMaxBetSession()) { return true; } if (CasinoOopsMaxBetsGate.IsActive()) { return true; } } return false; } private static bool Conflicts(CrowdControlHostCcEffectCode a, CrowdControlHostCcEffectCode b) { if (a == b) { return true; } if (a - 4 <= CrowdControlHostCcEffectCode.AddDayTime) { if (b - 4 <= CrowdControlHostCcEffectCode.AddDayTime) { return true; } return false; } if (a - 6 <= CrowdControlHostCcEffectCode.AddDayTime) { if (b - 6 <= CrowdControlHostCcEffectCode.AddDayTime) { return true; } return false; } return false; } internal static void RegisterHouseCrush(uint requestId, float duration) { CasinoTimedOdds.BeginEstimatedUniformSession(requestId, 0.04f); GameStateManager.LogCrowdControl($"Casino: house crush (~{0.04f} est) {duration:F0}s (host relay)."); AddSession(requestId, CrowdControlHostCcEffectCode.CasinoHouseCrush, duration); } internal static void RegisterHotTable(uint requestId, float duration) { CasinoTimedOdds.BeginEstimatedScaleSession(requestId, 2.15f, 3.25f); GameStateManager.LogCrowdControl($"Casino: hot table x{2.15f} (cap {3.25f}) {duration:F0}s (host relay)."); AddSession(requestId, CrowdControlHostCcEffectCode.CasinoHotTable, duration); } internal static void RegisterMaxBetSurge(uint requestId, float duration) { CasinoTimedOdds.BeginMaxBetScaleSession(requestId, 2.0, 4.0); GameStateManager.LogCrowdControl($"Casino: max-bet surge x{2.0} (cap {4.0}) {duration:F0}s (host relay)."); AddSession(requestId, CrowdControlHostCcEffectCode.CasinoMaxBetSurge, duration); } internal static void RegisterOopsMaxBets(uint requestId, float duration) { CasinoOopsMaxBetsGate.BeginSession(); int num = CasinoBetMaxPusher.PushAllTablesToAffordableMax(); GameStateManager.LogCrowdControl($"Casino: oops max bets — pushed {num} table(s) on start (host relay)."); Sessions[requestId] = new Session { Code = CrowdControlHostCcEffectCode.CasinoOopsMaxBets, RequestId = requestId, TimeLeft = duration, OopsAccum = 0.4f }; } private static void AddSession(uint requestId, CrowdControlHostCcEffectCode code, float duration) { Sessions[requestId] = new Session { Code = code, RequestId = requestId, TimeLeft = duration, OopsAccum = 0f }; } internal static void Stop(uint requestId) { if (Sessions.TryGetValue(requestId, out Session value)) { EndSession(value); Sessions.Remove(requestId); } } private static void EndSession(Session s) { switch (s.Code) { case CrowdControlHostCcEffectCode.CasinoHouseCrush: CasinoTimedOdds.RestoreEstimatedSession(s.RequestId); GameStateManager.LogCrowdControl("Casino: house crush ended (host relay)."); break; case CrowdControlHostCcEffectCode.CasinoHotTable: CasinoTimedOdds.RestoreEstimatedSession(s.RequestId); GameStateManager.LogCrowdControl("Casino: hot table ended (host relay)."); break; case CrowdControlHostCcEffectCode.CasinoMaxBetSurge: CasinoTimedOdds.RestoreMaxBetSession(s.RequestId); GameStateManager.LogCrowdControl("Casino: max-bet surge ended (host relay)."); break; case CrowdControlHostCcEffectCode.CasinoOopsMaxBets: CasinoOopsMaxBetsGate.EndSession(); GameStateManager.LogCrowdControl("Casino: oops max bets window ended (host relay)."); break; } } internal static void Tick(float dt) { if (!NetworkServer.active || Sessions.Count == 0) { return; } List<uint> list = null; foreach (KeyValuePair<uint, Session> session in Sessions) { Session value = session.Value; value.TimeLeft -= dt; if (value.Code == CrowdControlHostCcEffectCode.CasinoOopsMaxBets) { value.OopsAccum += dt; if (value.OopsAccum >= 0.4f) { value.OopsAccum = 0f; CasinoBetMaxPusher.PushAllTablesToAffordableMax(); } } if (value.TimeLeft <= 0f) { (list ?? (list = new List<uint>())).Add(session.Key); } } if (list == null) { return; } foreach (uint item in list) { if (Sessions.TryGetValue(item, out Session value2)) { EndSession(value2); Sessions.Remove(item); } } } } public enum CrowdControlSpawnItemKind : byte { Bat = 1, Basketball = 2, Drink = 3, Microphone = 4, ImmunityCross = 5, CoordinatorCamera = 10, GoldenChip = 11, DevilsReel = 12, AngelsReel = 13, TimeMachine = 14, Taser = 15, QuotaGun = 16, MysteryBox = 17, UpgradeStakeholder = 20, UpgradeInsurance = 21, UpgradeBonusDraw = 22, UpgradeGamblersConfidence = 23, HolyStatue = 30, SleddingFrog = 31, VoiceWand = 32, GachaSphere = 33, Bongo = 34, Dice = 35, ChessPiece = 36, BingBong = 37, DebtBag = 38 } public struct CrowdControlItemGiveRequest : NetworkMessage { public CrowdControlSpawnItemKind Kind; } internal static class CrowdControlItemNetwork { private static bool _serverHandlerInstalled; internal static void InstallSerialization() { Writer<CrowdControlItemGiveRequest>.write = delegate(NetworkWriter w, CrowdControlItemGiveRequest v) { w.WriteByte((byte)v.Kind); }; Reader<CrowdControlItemGiveRequest>.read = delegate(NetworkReader r) { CrowdControlItemGiveRequest result = default(CrowdControlItemGiveRequest); result.Kind = (CrowdControlSpawnItemKind)r.ReadByte(); return result; }; } internal static void RegisterServerHandlerIfNeeded() { InstallSerialization(); if (!_serverHandlerInstalled && NetworkServer.active) { NetworkServer.ReplaceHandler<CrowdControlItemGiveRequest>((Action<NetworkConnectionToClient, CrowdControlItemGiveRequest>)OnServerItemGiveRequest, true); _serverHandlerInstalled = true; CrowdControlMod.Instance.Logger.LogInfo((object)"Crowd Control: registered server item-give handler (non-host clients can request items)."); } } internal static void UnregisterServerHandlerIfNeeded() { if (_serverHandlerInstalled) { NetworkServer.UnregisterHandler<CrowdControlItemGiveRequest>(); _serverHandlerInstalled = false; } } private static void OnServerItemGiveRequest(NetworkConnectionToClient conn, CrowdControlItemGiveRequest msg) { if ((Object)(object)((conn != null) ? ((NetworkConnection)conn).identity : null) == (Object)null) { return; } PlayerInventory component = ((Component)((NetworkConnection)conn).identity).GetComponent<PlayerInventory>(); if ((Object)(object)component == (Object)null) { return; } if (!GwyfItemSpawnHelper.TrySpawnCrowdControlKindNearServer(component, msg.Kind, out Item _, out string errorMessage)) { if (!string.IsNullOrEmpty(errorMessage)) { CrowdControlMod.Instance.Logger.LogWarning((object)$"Crowd Control: item request failed ({msg.Kind}): {errorMessage}"); } } else { GameStateManager.LogCrowdControl($"Item (network): spawned kind {msg.Kind} near conn {conn.connectionId}."); } } internal static bool ClientSendItemRequest(CrowdControlSpawnItemKind kind) { InstallSerialization(); if (!NetworkClient.isConnected) { return false; } if (NetworkClient.connection == null) { return false; } CrowdControlItemGiveRequest crowdControlItemGiveRequest = default(CrowdControlItemGiveRequest); crowdControlItemGiveRequest.Kind = kind; NetworkClient.Send<CrowdControlItemGiveRequest>(crowdControlItemGiveRequest, 0); return true; } } internal static class CrowdControlMirrorWriterBootstrap { internal static void ApplyAllCustomMessageWriters() { CrowdControlHostCcRelay.InstallSerialization(); CrowdControlItemNetwork.InstallSerialization(); CrowdControlStreamerEffectNetwork.InstallSerialization(); CrowdControlGlobalHudMirrorNetwork.InstallSerialization(); } } [BepInPlugin("WarpWorld.CrowdControl.GambleWithYourFriends", "Crowd Control — Gamble With Your Friends", "1.0.0.0")] public class CrowdControlMod : BaseUnityPlugin { public const string MOD_GUID = "WarpWorld.CrowdControl.GambleWithYourFriends"; public const string MOD_NAME = "Crowd Control — Gamble With Your Friends"; public const string MOD_VERSION = "1.0.0.0"; private readonly Harmony harmony = new Harmony("WarpWorld.CrowdControl.GambleWithYourFriends"); private const float GAME_STATUS_UPDATE_INTERVAL = 1f; private float m_gameStatusUpdateTimer; private volatile bool m_pendingCrowdControlGameStateResync; public static float DeltaTime => Time.fixedDeltaTime / Time.timeScale; public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; internal static CrowdControlMod Instance { get; private set; } public GameStateManager GameStateManager { get; private set; } public EffectLoader EffectLoader { get; private set; } public bool ClientConnected => Client.Connected; public NetworkClient Client { get; private set; } public Scheduler Scheduler { get; private set; } internal ConfigEntry<bool> ConfigShowEffectHud { get; private set; } internal ConfigEntry<float> ConfigEffectHudScale { get; private set; } internal ConfigEntry<float> ConfigEffectToastSeconds { get; private set; } internal ConfigEntry<float> ConfigEffectHudRightInset { get; private set; } internal ConfigEntry<float> ConfigTimedHudTicketStripLeftPx { get; private set; } internal ConfigEntry<float> ConfigToastBottomMarginPx { get; private set; } internal ConfigEntry<float> ConfigTimedHudTopOffsetPx { get; private set; } internal ConfigEntry<bool> ConfigLogSpawnableCatalogHintsOnce { get; private set; } internal ConfigEntry<bool> ConfigLogClientHostCcRelay { get; private set; } internal void QueueCrowdControlGameStateResync() { m_pendingCrowdControlGameStateResync = true; } private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) Instance = this; ConfigShowEffectHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Effect UI", "ShowHud", true, "Show Crowd Control on-screen feedback (active timed effects + short toasts for instant effects)."); ConfigEffectHudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "HudScale", 1f, new ConfigDescription("Relative size of the overlay.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); ConfigEffectToastSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "ToastSeconds", 3.5f, new ConfigDescription("How long instant-effect toasts stay visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f), Array.Empty<object>())); ConfigEffectHudRightInset = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "RightEdgeInset", 320f, new ConfigDescription("Unused (legacy). Timed HUD is top-left; safe to ignore.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); ConfigTimedHudTicketStripLeftPx = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "TicketStripLeftPx", 100f, new ConfigDescription("Left edge of timed-effect text (1080p height ref). Lower = further left; raise if it overlaps the ticket UI.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(72f, 520f), Array.Empty<object>())); ConfigToastBottomMarginPx = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "ToastBottomMarginPx", 0f, new ConfigDescription("Lift toasts up from the bottom edge (1080p ref). 0 = flush bottom-right; increase only if they cover ping/emote UI.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>())); ConfigTimedHudTopOffsetPx = ((BaseUnityPlugin)this).Config.Bind<float>("Effect UI", "TimedHudTopOffsetPx", 0f, new ConfigDescription("Distance from the top of the screen for timed-effect text (1080p ref). Lower = higher on screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>())); ConfigLogSpawnableCatalogHintsOnce = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogSpawnableCatalogHintsOnce", false, "On startup, log once any SpawnableSettings row whose spawnableName contains: debt, chess, frog, bing, gacha, voice, sled, dice, bongo. Use BepInEx LogOutput to align name hints; set false to silence after tuning."); ConfigLogClientHostCcRelay = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogClientHostCcRelay", false, "When true, logs each Crowd Control client→host relay message (instant/timed start/stop) on the sending client and when the host receives it (connection id, effect, request id). Enable only while troubleshooting; can be noisy."); Logger.LogInfo((object)"Loaded WarpWorld.CrowdControl.GambleWithYourFriends. Patching."); harmony.PatchAll(); CrowdControlMirrorWriterBootstrap.ApplyAllCustomMessageWriters(); Logger.LogInfo((object)"Initializing Crowd Control"); try { GameStateManager = new GameStateManager(this); Client = new NetworkClient(this); EffectLoader = new EffectLoader(this, Client); Scheduler = new Scheduler(this, Client); GameObject val = new GameObject("CrowdControlEffectHud"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<CrowdControlEffectHud>().Init(this); } catch (Exception arg) { Logger.LogError((object)$"Crowd Control Init Error: {arg}"); } GwyfItemSpawnHelper.LogCatalogHintMatchesOnceIfEnabled(Logger, ConfigLogSpawnableCatalogHintsOnce.Value); Logger.LogInfo((object)"Crowd Control Initialized"); } private void OnApplicationQuit() { try { Client?.Dispose(); } catch { } } private void OnDestroy() { try { Client?.Dispose(); } catch { } } private void OnApplicationFocus(bool hasFocus) { if (GameStateManager != null) { GameStateManager.UpdateGameState(force: true); } } private void FixedUpdate() { if (m_pendingCrowdControlGameStateResync) { m_pendingCrowdControlGameStateResync = false; GameStateManager.UpdateGameState(force: true); } m_gameStatusUpdateTimer += Time.fixedDeltaTime; if (m_gameStatusUpdateTimer >= 1f) { GameStateManager.UpdateGameState(); m_gameStatusUpdateTimer = 0f; } Scheduler?.Tick(); if (NetworkServer.active) { CrowdControlHostTimedRelaySessions.Tick(Time.fixedDeltaTime); } } } internal static class CrowdControlNetworkBootstrap { [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] private static void RegisterMirrorSerialization() { CrowdControlMirrorWriterBootstrap.ApplyAllCustomMessageWriters(); } } internal static class CrowdControlStreamerEffectExecutor { internal static bool TryExecute(NetworkIdentity id, CrowdControlStreamerEffectOp op, out string? error) { error = null; if ((Object)(object)id == (Object)null) { error = "Null identity."; return false; } if (!NetworkServer.active) { error = "Not server."; return false; } PlayerBuff component = ((Component)id).GetComponent<PlayerBuff>(); PlayerProfile component2 = ((Component)id).GetComponent<PlayerProfile>(); switch (op) { case CrowdControlStreamerEffectOp.LuckTipsySurge30s: if ((Object)(object)component == (Object)null || !((NetworkBehaviour)component).isServer) { error = "No server PlayerBuff."; return false; } component.ApplyBuff((PlayerBuffType)0, 0.65f, 30f); return true; case CrowdControlStreamerEffectOp.LuckTipsyHangover30s: if ((Object)(object)component == (Object)null || !((NetworkBehaviour)component).isServer) { error = "No server PlayerBuff."; return false; } component.ApplyBuff((PlayerBuffType)0, -0.45f, 30f); return true; case CrowdControlStreamerEffectOp.BuffDrinkTipsy15s: { if ((Object)(object)component == (Object)null || !((NetworkBehaviour)component).isServer) { error = "No server PlayerBuff."; return false; } component.ApplyBuff((PlayerBuffType)0, 0.38f, 15f); PlayerVoiceFX val = ((Component)id).GetComponent<PlayerVoiceFX>() ?? ((Component)id).GetComponentInChildren<PlayerVoiceFX>(true); if ((Object)(object)val != (Object)null) { val.CmdStartTimedVoiceFX((VoipFX)1, 15f, true); } return true; } case CrowdControlStreamerEffectOp.BuffImmunity15s: if ((Object)(object)component == (Object)null || !((NetworkBehaviour)component).isServer) { error = "No server PlayerBuff."; return false; } component.ApplyBuff((PlayerBuffType)2, 1f, 15f); return true; case CrowdControlStreamerEffectOp.BuffInspiringMelody15s: if ((Object)(object)component == (Object)null || !((NetworkBehaviour)component).isServer) { error = "No server PlayerBuff."; return false; } component.ApplyBuff((PlayerBuffType)1, 0.4f, 15f); return true; case CrowdControlStreamerEffectOp.UpgradeInsurance: case CrowdControlStreamerEffectOp.UpgradeBonusDraw: case CrowdControlStreamerEffectOp.UpgradeStakeholder: case CrowdControlStreamerEffectOp.UpgradeNerfGamblersConfidence: case CrowdControlStreamerEffectOp.UpgradeBuffGamblersConfidence: return TryUpgradeOp(op, component2, out error); case CrowdControlStreamerEffectOp.UpgradeResetRun: return TryResetUpgradesForProfile(component2, out error); default: error = $"Unknown op {(byte)op}."; return false; } } private static bool TryUpgradeOp(CrowdControlStreamerEffectOp op, PlayerProfile? profile, out string? error) { error = null; if ((Object)(object)profile == (Object)null || profile.steamId == 0L) { error = "No PlayerProfile / steam id."; return false; } UpgradeManager instance = NetworkSingleton<UpgradeManager>.Instance; if ((Object)(object)instance == (Object)null) { error = "No UpgradeManager."; return false; } ulong steamId = profile.steamId; switch (op) { case CrowdControlStreamerEffectOp.UpgradeInsurance: instance.ChangeUpgradeData(steamId, (PlayerUpgradeType)1, 0.1f); return true; case CrowdControlStreamerEffectOp.UpgradeBonusDraw: instance.ChangeUpgradeData(steamId, (PlayerUpgradeType)3, 0.06f); return true; case CrowdControlStreamerEffectOp.UpgradeStakeholder: instance.ChangeUpgradeData(steamId, (PlayerUpgradeType)2, 0.18f); return true; case CrowdControlStreamerEffectOp.UpgradeNerfGamblersConfidence: if (instance.GetUpgradeData(steamId, (PlayerUpgradeType)0) - 0.1f < 0.35f) { error = "Gamblers Confidence already near floor."; return false; } instance.ChangeUpgradeData(steamId, (PlayerUpgradeType)0, -0.1f); return true; case CrowdControlStreamerEffectOp.UpgradeBuffGamblersConfidence: instance.ChangeUpgradeData(steamId, (PlayerUpgradeType)0, 0.12f); return true; default: error = "Not an upgrade op."; return false; } } private static bool TryResetUpgradesForProfile(PlayerProfile? profile, out string? error) { //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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) error = null; if ((Object)(object)profile == (Object)null || profile.steamId == 0L) { error = "No PlayerProfile / steam id."; return false; } UpgradeManager instance = NetworkSingleton<UpgradeManager>.Instance; if ((Object)(object)instance == (Object)null) { error = "No UpgradeManager."; return false; } ulong steamId = profile.steamId; PlayerUpgradeData val = new PlayerUpgradeData(); if (RunUpgradesMatchDefaults(instance, steamId, val)) { error = "Run upgrades are already at default values."; GameStateManager.LogCrowdControl($"Upgrades: skip reset for steamId {steamId} — already at run defaults (single streamer)."); return false; } foreach (KeyValuePair<PlayerUpgradeType, float> upgrade in val.Upgrades) { instance.SetUpgradeData(steamId, upgrade.Key, upgrade.Value); } foreach (PlayerUpgradeType key in val.Upgrades.Keys) { instance.ChangeUpgradeData(steamId, key, 0f); } GameStateManager.LogCrowdControl($"Upgrades: reset to defaults for steamId {steamId} (single streamer)."); return true; } private static bool RunUpgradesMatchDefaults(UpgradeManager um, ulong steamId, PlayerUpgradeData defaults) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<PlayerUpgradeType, float> upgrade in defaults.Upgrades) { if (Mathf.Abs(um.GetUpgradeData(steamId, upgrade.Key) - upgrade.Value) > 0.0005f) { return false; } } return true; } } internal static class CrowdControlStreamerEffectNetwork { private static bool _serverHandlerInstalled; internal static void InstallSerialization() { Writer<CrowdControlStreamerEffectRequest>.write = delegate(NetworkWriter w, CrowdControlStreamerEffectRequest v) { w.WriteByte((byte)v.Op); }; Reader<CrowdControlStreamerEffectRequest>.read = delegate(NetworkReader r) { CrowdControlStreamerEffectRequest result = default(CrowdControlStreamerEffectRequest); result.Op = (CrowdControlStreamerEffectOp)r.ReadByte(); return result; }; } internal static void RegisterServerHandlerIfNeeded() { InstallSerialization(); if (!_serverHandlerInstalled && NetworkServer.active) { NetworkServer.ReplaceHandler<CrowdControlStreamerEffectRequest>((Action<NetworkConnectionToClient, CrowdControlStreamerEffectRequest>)OnServerStreamerEffectRequest, true); _serverHandlerInstalled = true; CrowdControlMod.Instance.Logger.LogInfo((object)"Crowd Control: registered client-effect handler (client → host, single connection)."); } } internal static void UnregisterServerHandlerIfNeeded() { if (_serverHandlerInstalled) { NetworkServer.UnregisterHandler<CrowdControlStreamerEffectRequest>(); _serverHandlerInstalled = false; } } private static void OnServerStreamerEffectRequest(NetworkConnectionToClient conn, CrowdControlStreamerEffectRequest msg) { if ((Object)(object)((conn != null) ? ((NetworkConnection)conn).identity : null) == (Object)null) { return; } if (!CrowdControlStreamerEffectExecutor.TryExecute(((NetworkConnection)conn).identity, msg.Op, out string error)) { if (!string.IsNullOrEmpty(error)) { CrowdControlMod.Instance.Logger.LogWarning((object)$"Crowd Control: client effect {msg.Op} failed: {error}"); } } else { GameStateManager.LogCrowdControl($"Client effect {msg.Op} applied for conn {conn.connectionId}."); } } internal static bool TryRunForLocalStreamer(CrowdControlStreamerEffectOp op, out string? error) { error = null; if (!NetworkClient.isConnected || (Object)(object)NetworkClient.localPlayer == (Object)null) { error = "Not connected or no local player."; return false; } NetworkIdentity component = ((Component)NetworkClient.localPlayer).GetComponent<NetworkIdentity>(); if ((Object)(object)component == (Object)null) { error = "Local player has no NetworkIdentity."; return false; } if (NetworkServer.active) { if (!CrowdControlStreamerEffectExecutor.TryExecute(component, op, out error)) { return false; } return true; } InstallSerialization(); if (NetworkClient.connection == null) { error = "No client connection."; return false; } CrowdControlStreamerEffectRequest crowdControlStreamerEffectRequest = default(CrowdControlStreamerEffectRequest); crowdControlStreamerEffectRequest.Op = op; NetworkClient.Send<CrowdControlStreamerEffectRequest>(crowdControlStreamerEffectRequest, 0); return true; } internal static bool ClientSend(CrowdControlStreamerEffectOp op) { string error; return TryRunForLocalStreamer(op, out error); } } public enum CrowdControlStreamerEffectOp : byte { LuckTipsySurge30s = 1, LuckTipsyHangover30s = 2, BuffDrinkTipsy15s = 3, BuffImmunity15s = 4, BuffInspiringMelody15s = 5, UpgradeInsurance = 10, UpgradeBonusDraw = 11, UpgradeStakeholder = 12, UpgradeNerfGamblersConfidence = 13, UpgradeBuffGamblersConfidence = 14, UpgradeResetRun = 15 } public struct CrowdControlStreamerEffectRequest : NetworkMessage { public CrowdControlStreamerEffectOp Op; } internal static class CrowdControlTimedCasinoHud { internal static void AfterHostLocalTimedStart(string code, uint requestId, float durationSeconds) { if (NetworkServer.active && CrowdControlHostCcRelay.TryMapCode(code, out var effectCode)) { NetworkConnection localConnection = (NetworkConnection)(object)NetworkServer.localConnection; CrowdControlGlobalTimedHud.ServerBroadcast(requestId, effectCode, durationSeconds, localConnection); } } } public class DelimitedStreamReader : IDisposable { [CompilerGenerated] private NetworkStream <stream>P; private readonly MemoryStream _memory_stream; public DelimitedStreamReader(NetworkStream stream) { <stream>P = stream; _memory_stream = new MemoryStream(); base..ctor(); } ~DelimitedStreamReader() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (!disposing) { return; } try { _memory_stream.Dispose(); } catch { } } public string ReadUntilNullTerminator() { int num; while ((num = <stream>P.ReadByte()) != -1 && num != 0) { _memory_stream.WriteByte(checked((byte)num)); } if (num == -1) { throw new EndOfStreamException("Reached end of stream without finding a null terminator."); } string @string = Encoding.UTF8.GetString(_memory_stream.ToArray()); _memory_stream.SetLength(0L); return @string; } } public class GameStateManager { [CompilerGenerated] private CrowdControlMod <mod>P; private const string CasinoSceneName = "CasinoScene"; private const string HomeSceneName = "HomeScene"; public const string CasinoPlayRequiredMessage = "Can only be used when in the Casino"; private static readonly HashSet<string> PauseTimedOutsideCasinoRoundCodes = new HashSet<string>(StringComparer.Ordinal) { "player_movement_fast", "player_movement_slow", "player_movement_very_slow" }; private static readonly HashSet<string> LobbySessionOkEffectCodes = new HashSet<string>(StringComparer.Ordinal) { "cosmetic_random_piece", "cosmetic_reset_outfit", "cosmetic_clear_hats", "spawn_bat", "spawn_drink", "spawn_immunity_cross", "spawn_microphone", "spawn_coordinator", "spawn_golden_chip", "spawn_devils_reel", "spawn_angels_reel", "spawn_time_machine", "spawn_taser", "spawn_quota_gun", "spawn_mystery_box", "spawn_upgrade_stakeholder", "spawn_upgrade_insurance", "spawn_upgrade_bonus_draw", "spawn_upgrade_gamblers_confidence", "spawn_holy_statue", "spawn_voice_wand", "spawn_gacha_sphere", "spawn_basketball", "spawn_sledding_frog", "spawn_bongo", "spawn_dice", "spawn_chess_piece", "spawn_bingbong", "spawn_debt_bag", "player_movement_fast", "player_movement_slow", "player_movement_very_slow", "voice_low", "voice_wobble", "voice_radio", "voice_no_mouth_on", "voice_no_mouth_off", "voice_reset" }; private GameState? _lastGameState; public GameStateManager(CrowdControlMod mod) { <mod>P = mod; base..ctor(); } public static void LogCrowdControl(string message) { CrowdControlMod instance = CrowdControlMod.Instance; if (instance != null) { instance.Logger.LogMessage((object)("[Crowd Control] " + message)); } } public string FormatCrowdControlSpawnSnapshot() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) try { GameState gameState = GetGameState(); Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; GameManager instance = NetworkSingleton<GameManager>.Instance; string text = (((Object)(object)instance == (Object)null) ? "(null)" : ((object)(GameState)(ref instance.state)).ToString()); float num = (((Object)(object)instance == (Object)null) ? (-1f) : instance.Network_timer); bool flag = (Object)(object)instance != (Object)null && instance.HasDayStarted; return $"CcGameState={gameState} scene=\"{name}\" vanillaGameState={text} Network_timer={num:F2}s HasDayStarted={flag} " + $"focused={Application.isFocused} host={NetworkServer.active} client={NetworkClient.isConnected} timeScale={Time.timeScale:0.###}"; } catch (Exception ex) { return "CcGameState snapshot error: " + ex.Message; } } public bool IsStrictCasinoGamblingReady() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 try { if (!NetworkClient.isConnected) { return false; } Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; GameManager instance = NetworkSingleton<GameManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } if (Time.timeScale <= 0f) { return false; } if (name != "CasinoScene" || (int)instance.state != 1) { return false; } if (NetworkServer.active) { return instance.HasDayStarted; } return instance.Network_timer > 0.0001f; } catch { return false; } } public bool IsCasinoRoundPlayReady() { return IsStrictCasinoGamblingReady(); } public static bool RequiresActiveCasinoPlay(string? code) { if (!string.IsNullOrEmpty(code)) { return CrowdControlHostOnlyEffectCodes.CodesSet.Contains(code); } return false; } public bool ShouldRejectCasinoOnlyOutsidePlay(string? code, [NotNullWhen(true)] out string? message) { message = null; if (!RequiresActiveCasinoPlay(code)) { return false; } if (IsStrictCasinoGamblingReady()) { return false; } message = "Can only be used when in the Casino"; return true; } public static bool ShouldFreezeTimedOutsideCasinoRound(string code) { if (!string.IsNullOrEmpty(code)) { return PauseTimedOutsideCasinoRoundCodes.Contains(code); } return false; } public bool IsReady(string code = "") { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!Application.isFocused) { return false; } if (IsStrictCasinoGamblingReady()) { return true; } GameState gameState = GetGameState(); if (IsLobbySessionOkEffect(code) && CanRunLobbySessionEffects(gameState)) { return true; } return false; } private static bool IsLobbySessionOkEffect(string code) { if (!string.IsNullOrEmpty(code)) { return LobbySessionOkEffectCodes.Contains(code); } return false; } private static bool CanRunLobbySessionEffects(GameState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((state - -8 <= 3 || (int)state == -1) ? true : false) { return false; } if (!NetworkClient.isConnected) { return false; } return (Object)(object)NetworkSingleton<GameManager>.Instance != (Object)null; } public GameState GetGameState() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) try { if (!NetworkClient.isConnected) { return (GameState)(-8); } Scene activeScene = SceneManager.GetActiveScene(); string name =
BepInEx/plugins/Newtonsoft.Json.dll
Decompiled 2 days 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.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.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(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [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.4.30916")] [assembly: AssemblyInformationalVersion("13.0.4+4e13299d4b0ec96bd4df9954ef646bd2d1b5bf2a")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET Standard 2.0")] [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.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] internal sealed class DynamicallyAccessedMembersAttribute : Attribute { public DynamicallyAccessedMemberTypes MemberTypes { get; } public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) { MemberTypes = memberTypes; } } [Flags] internal enum DynamicallyAccessedMemberTypes { None = 0, PublicParameterlessConstructor = 1, PublicConstructors = 3, NonPublicConstructors = 4, PublicMethods = 8, NonPublicMethods = 0x10, PublicFields = 0x20, NonPublicFields = 0x40, PublicNestedTypes = 0x80, NonPublicNestedTypes = 0x100, PublicProperties = 0x200, NonPublicProperties = 0x400, PublicEvents = 0x800, NonPublicEvents = 0x1000, Interfaces = 0x2000, All = -1 } [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class FeatureGuardAttribute : Attribute { public Type FeatureType { get; } public FeatureGuardAttribute(Type featureType) { FeatureType = featureType; } } [AttributeUsage(AttributeTargets.Property, Inherited = false)] internal sealed class FeatureSwitchDefinitionAttribute : Attribute { public string SwitchName { get; } public FeatureSwitchDefinitionAttribute(string switchName) { SwitchName = switchName; } } [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; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresDynamicCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresDynamicCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresUnreferencedCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresUnreferencedCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] internal sealed class UnconditionalSuppressMessageAttribute : Attribute { public string Category { get; } public string CheckId { get; } public string? Scope { get; set; } public string? Target { get; set; } public string? MessageId { get; set; } public string? Justification { get; set; } public UnconditionalSuppressMessageAttribute(string category, string checkId) { Category = category; CheckId = checkId; } } } 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] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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."); } } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { 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); } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] 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.GetValueOrDefault(DateTimeZoneHandling.RoundtripKind); } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling.GetValueOrDefault(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
BepInEx/plugins/System.Collections.Immutable.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using FxResources.System.Collections.Immutable; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("System.Collections.Immutable.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyDefaultAlias("System.Collections.Immutable")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: CLSCompliant(true)] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyDescription("This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections. Like strings, any methods that perform modifications will not change the existing instance but instead return a new instance. For efficiency reasons, the implementation uses a sharing mechanism to ensure that newly created instances share as much data as possible with the previous instance while ensuring that operations have a predictable time complexity.\r\n\r\nThe System.Collections.Immutable library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks.")] [assembly: AssemblyFileVersion("9.0.925.41916")] [assembly: AssemblyInformationalVersion("9.0.9+893c2ebbd49952ca49e93298148af2d95a61a0a4")] [assembly: AssemblyProduct("Microsoft® .NET")] [assembly: AssemblyTitle("System.Collections.Immutable")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("9.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: System.Runtime.CompilerServices.NullablePublicOnly(true)] 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] internal sealed class ParamCollectionAttribute : 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 NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class ScopedRefAttribute : Attribute { } [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 FxResources.System.Collections.Immutable { internal static class SR { } } namespace System { internal static class SR { private static readonly bool s_usingResourceKeys = GetUsingResourceKeysSwitchValue(); private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR))); internal static string Arg_KeyNotFoundWithKey => GetResourceString("Arg_KeyNotFoundWithKey"); internal static string ArrayInitializedStateNotEqual => GetResourceString("ArrayInitializedStateNotEqual"); internal static string ArrayLengthsNotEqual => GetResourceString("ArrayLengthsNotEqual"); internal static string CannotFindOldValue => GetResourceString("CannotFindOldValue"); internal static string CapacityMustBeGreaterThanOrEqualToCount => GetResourceString("CapacityMustBeGreaterThanOrEqualToCount"); internal static string CapacityMustEqualCountOnMove => GetResourceString("CapacityMustEqualCountOnMove"); internal static string CollectionModifiedDuringEnumeration => GetResourceString("CollectionModifiedDuringEnumeration"); internal static string DuplicateKey => GetResourceString("DuplicateKey"); internal static string InvalidEmptyOperation => GetResourceString("InvalidEmptyOperation"); internal static string InvalidOperationOnDefaultArray => GetResourceString("InvalidOperationOnDefaultArray"); internal static string Arg_HTCapacityOverflow => GetResourceString("Arg_HTCapacityOverflow"); internal static string Arg_RankMultiDimNotSupported => GetResourceString("Arg_RankMultiDimNotSupported"); internal static string Arg_NonZeroLowerBound => GetResourceString("Arg_NonZeroLowerBound"); internal static string Arg_ArrayPlusOffTooSmall => GetResourceString("Arg_ArrayPlusOffTooSmall"); internal static string Argument_IncompatibleArrayType => GetResourceString("Argument_IncompatibleArrayType"); internal static string ArgumentOutOfRange_NeedNonNegNum => GetResourceString("ArgumentOutOfRange_NeedNonNegNum"); internal static string InvalidOperation_IncompatibleComparer => GetResourceString("InvalidOperation_IncompatibleComparer"); private static bool GetUsingResourceKeysSwitchValue() { if (!AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled)) { return false; } return isEnabled; } internal static bool UsingResourceKeys() { return s_usingResourceKeys; } private static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } private static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace System.Linq { public static class ImmutableArrayExtensions { public static IEnumerable<TResult> Select<T, TResult>(this ImmutableArray<T> immutableArray, Func<T, TResult> selector) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Select(selector); } public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this ImmutableArray<TSource> immutableArray, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) { immutableArray.ThrowNullRefIfNotInitialized(); if (collectionSelector == null || resultSelector == null) { return Enumerable.SelectMany(immutableArray, collectionSelector, resultSelector); } if (immutableArray.Length != 0) { return immutableArray.SelectManyIterator(collectionSelector, resultSelector); } return Enumerable.Empty<TResult>(); } public static IEnumerable<T> Where<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Where(predicate); } public static bool Any<T>(this ImmutableArray<T> immutableArray) { return immutableArray.Length > 0; } public static bool Any<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (predicate(arg)) { return true; } } return false; } public static bool All<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (!predicate(arg)) { return false; } } return true; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, ImmutableArray<TDerived> items, IEqualityComparer<TBase>? comparer = null) where TDerived : TBase { immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } if (comparer == null) { comparer = EqualityComparer<TBase>.Default; } for (int i = 0; i < immutableArray.Length; i++) { if (!comparer.Equals(immutableArray.array[i], (TBase)(object)items.array[i])) { return false; } } return true; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, IEnumerable<TDerived> items, IEqualityComparer<TBase>? comparer = null) where TDerived : TBase { Requires.NotNull(items, "items"); if (comparer == null) { comparer = EqualityComparer<TBase>.Default; } int num = 0; int length = immutableArray.Length; foreach (TDerived item in items) { if (num == length) { return false; } if (!comparer.Equals(immutableArray[num], (TBase)(object)item)) { return false; } num++; } return num == length; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, ImmutableArray<TDerived> items, Func<TBase, TBase, bool> predicate) where TDerived : TBase { Requires.NotNull(predicate, "predicate"); immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } int i = 0; for (int length = immutableArray.Length; i < length; i++) { if (!predicate(immutableArray[i], (TBase)(object)items[i])) { return false; } } return true; } public static T? Aggregate<T>(this ImmutableArray<T> immutableArray, Func<T, T, T> func) { Requires.NotNull(func, "func"); if (immutableArray.Length == 0) { return default(T); } T val = immutableArray[0]; int i = 1; for (int length = immutableArray.Length; i < length; i++) { val = func(val, immutableArray[i]); } return val; } public static TAccumulate Aggregate<TAccumulate, T>(this ImmutableArray<T> immutableArray, TAccumulate seed, Func<TAccumulate, T, TAccumulate> func) { Requires.NotNull(func, "func"); TAccumulate val = seed; T[] array = immutableArray.array; foreach (T arg in array) { val = func(val, arg); } return val; } public static TResult Aggregate<TAccumulate, TResult, T>(this ImmutableArray<T> immutableArray, TAccumulate seed, Func<TAccumulate, T, TAccumulate> func, Func<TAccumulate, TResult> resultSelector) { Requires.NotNull(resultSelector, "resultSelector"); return resultSelector(immutableArray.Aggregate(seed, func)); } public static T ElementAt<T>(this ImmutableArray<T> immutableArray, int index) { return immutableArray[index]; } public static T? ElementAtOrDefault<T>(this ImmutableArray<T> immutableArray, int index) { if (index < 0 || index >= immutableArray.Length) { return default(T); } return immutableArray[index]; } public static T First<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return Enumerable.Empty<T>().First(); } public static T First<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.First(); } return immutableArray[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.array.Length == 0) { return default(T); } return immutableArray.array[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return default(T); } public static T Last<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.Last(); } return immutableArray[immutableArray.Length - 1]; } public static T Last<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return Enumerable.Empty<T>().Last(); } public static T? LastOrDefault<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.LastOrDefault(); } public static T? LastOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return default(T); } public static T Single<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Single(); } public static T Single<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } if (flag) { Enumerable.Empty<T>().Single(); } return result; } public static T? SingleOrDefault<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.SingleOrDefault(); } public static T? SingleOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } return result; } public static Dictionary<TKey, T> ToDictionary<TKey, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, EqualityComparer<TKey>.Default); } public static Dictionary<TKey, TElement> ToDictionary<TKey, TElement, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, Func<T, TElement> elementSelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default); } public static Dictionary<TKey, T> ToDictionary<TKey, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, IEqualityComparer<TKey>? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Dictionary<TKey, T> dictionary = new Dictionary<TKey, T>(immutableArray.Length, comparer); ImmutableArray<T>.Enumerator enumerator = immutableArray.GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; dictionary.Add(keySelector(current), current); } return dictionary; } public static Dictionary<TKey, TElement> ToDictionary<TKey, TElement, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, Func<T, TElement> elementSelector, IEqualityComparer<TKey>? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Requires.NotNull(elementSelector, "elementSelector"); Dictionary<TKey, TElement> dictionary = new Dictionary<TKey, TElement>(immutableArray.Length, comparer); T[] array = immutableArray.array; foreach (T arg in array) { dictionary.Add(keySelector(arg), elementSelector(arg)); } return dictionary; } public static T[] ToArray<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); if (immutableArray.array.Length == 0) { return ImmutableArray<T>.Empty.array; } return (T[])immutableArray.array.Clone(); } public static T First<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[0]; } public static T Last<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[builder.Count - 1]; } public static T? LastOrDefault<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[builder.Count - 1]; } public static bool Any<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); return builder.Count > 0; } private static IEnumerable<TResult> SelectManyIterator<TSource, TCollection, TResult>(this ImmutableArray<TSource> immutableArray, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) { TSource[] array = immutableArray.array; foreach (TSource item in array) { foreach (TCollection item2 in collectionSelector(item)) { yield return resultSelector(item, item2); } } } } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class NonVersionableAttribute : Attribute { } } namespace System.Runtime.InteropServices { public static class ImmutableCollectionsMarshal { public static ImmutableArray<T> AsImmutableArray<T>(T[]? array) { return new ImmutableArray<T>(array); } public static T[]? AsArray<T>(ImmutableArray<T> array) { return array.array; } } [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class LibraryImportAttribute : Attribute { public string LibraryName { get; } public string? EntryPoint { get; set; } public StringMarshalling StringMarshalling { get; set; } public Type? StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum StringMarshalling { Custom, Utf8, Utf16 } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } } namespace System.Numerics { internal static class BitOperations { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint RotateLeft(uint value, int offset) { return (value << offset) | (value >> 32 - offset); } } } namespace System.Collections { internal static class ThrowHelper { public static void ThrowIfNull(object arg, [CallerArgumentExpression("arg")] string? paramName = null) { if (arg == null) { ThrowArgumentNullException(paramName); } } [DoesNotReturn] public static void ThrowIfDestinationTooSmall() { throw new ArgumentException(System.SR.CapacityMustBeGreaterThanOrEqualToCount, "destination"); } [DoesNotReturn] public static void ThrowArgumentNullException(string? paramName) { throw new ArgumentNullException(paramName); } [DoesNotReturn] public static void ThrowKeyNotFoundException() { throw new KeyNotFoundException(); } [DoesNotReturn] public static void ThrowKeyNotFoundException<TKey>(TKey key) { throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key)); } [DoesNotReturn] public static void ThrowInvalidOperationException() { throw new InvalidOperationException(); } [DoesNotReturn] internal static void ThrowIncompatibleComparer() { throw new InvalidOperationException(System.SR.InvalidOperation_IncompatibleComparer); } } internal static class HashHelpers { public const uint HashCollisionThreshold = 100u; public const int MaxPrimeArrayLength = 2147483587; public const int HashPrime = 101; internal static ReadOnlySpan<int> Primes { get { object obj = global::<PrivateImplementationDetails>.74BCD6ED20AF2231F2BB1CDE814C5F4FF48E54BAC46029EEF90DDF4A208E2B20_A6; if (obj == null) { obj = new int[72] { 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 }; global::<PrivateImplementationDetails>.74BCD6ED20AF2231F2BB1CDE814C5F4FF48E54BAC46029EEF90DDF4A208E2B20_A6 = (int[])obj; } return new ReadOnlySpan<int>((int[]?)obj); } } public static bool IsPrime(int candidate) { if (((uint)candidate & (true ? 1u : 0u)) != 0) { int num = (int)Math.Sqrt(candidate); for (int i = 3; i <= num; i += 2) { if (candidate % i == 0) { return false; } } return true; } return candidate == 2; } public static int GetPrime(int min) { if (min < 0) { throw new ArgumentException(System.SR.Arg_HTCapacityOverflow); } ReadOnlySpan<int> primes = Primes; for (int i = 0; i < primes.Length; i++) { int num = primes[i]; if (num >= min) { return num; } } for (int j = min | 1; j < int.MaxValue; j += 2) { if (IsPrime(j) && (j - 1) % 101 != 0) { return j; } } return min; } public static int ExpandPrime(int oldSize) { int num = 2 * oldSize; if ((uint)num > 2147483587u && 2147483587 > oldSize) { return 2147483587; } return GetPrime(num); } public static ulong GetFastModMultiplier(uint divisor) { return ulong.MaxValue / (ulong)divisor + 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint FastMod(uint value, uint divisor, ulong multiplier) { return (uint)(((multiplier * value >> 32) + 1) * divisor >> 32); } } } namespace System.Collections.Immutable { internal static class AllocFreeConcurrentStack<T> { private const int MaxSize = 35; private static readonly Type s_typeOfT = typeof(T); private static Stack<RefAsValueType<T>> ThreadLocalStack { get { Dictionary<Type, object> dictionary = AllocFreeConcurrentStack.t_stacks ?? (AllocFreeConcurrentStack.t_stacks = new Dictionary<Type, object>()); if (!dictionary.TryGetValue(s_typeOfT, out var value)) { value = new Stack<RefAsValueType<T>>(35); dictionary.Add(s_typeOfT, value); } return (Stack<RefAsValueType<T>>)value; } } public static void TryAdd(T item) { Stack<RefAsValueType<T>> threadLocalStack = ThreadLocalStack; if (threadLocalStack.Count < 35) { threadLocalStack.Push(new RefAsValueType<T>(item)); } } public static bool TryTake([MaybeNullWhen(false)] out T item) { Stack<RefAsValueType<T>> threadLocalStack = ThreadLocalStack; if (threadLocalStack != null && threadLocalStack.Count > 0) { item = threadLocalStack.Pop().Value; return true; } item = default(T); return false; } } internal static class AllocFreeConcurrentStack { [ThreadStatic] internal static Dictionary<Type, object>? t_stacks; } internal sealed class DictionaryEnumerator<TKey, TValue> : IDictionaryEnumerator, IEnumerator where TKey : notnull { private readonly IEnumerator<KeyValuePair<TKey, TValue>> _inner; public DictionaryEntry Entry => new DictionaryEntry(_inner.Current.Key, _inner.Current.Value); public object Key => _inner.Current.Key; public object? Value => _inner.Current.Value; public object Current => Entry; internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> inner) { Requires.NotNull(inner, "inner"); _inner = inner; } public bool MoveNext() { return _inner.MoveNext(); } public void Reset() { _inner.Reset(); } } internal struct DisposableEnumeratorAdapter<T, TEnumerator> : IDisposable where TEnumerator : struct, IEnumerator<T> { private readonly IEnumerator<T> _enumeratorObject; private TEnumerator _enumeratorStruct; public T Current { get { if (_enumeratorObject == null) { return _enumeratorStruct.Current; } return _enumeratorObject.Current; } } internal DisposableEnumeratorAdapter(TEnumerator enumerator) { _enumeratorStruct = enumerator; _enumeratorObject = null; } internal DisposableEnumeratorAdapter(IEnumerator<T> enumerator) { _enumeratorStruct = default(TEnumerator); _enumeratorObject = enumerator; } public bool MoveNext() { if (_enumeratorObject == null) { return _enumeratorStruct.MoveNext(); } return _enumeratorObject.MoveNext(); } public void Dispose() { if (_enumeratorObject != null) { _enumeratorObject.Dispose(); } else { _enumeratorStruct.Dispose(); } } public DisposableEnumeratorAdapter<T, TEnumerator> GetEnumerator() { return this; } } internal interface IBinaryTree { int Height { get; } bool IsEmpty { get; } int Count { get; } IBinaryTree? Left { get; } IBinaryTree? Right { get; } } internal interface IBinaryTree<out T> : IBinaryTree { T Value { get; } new IBinaryTree<T>? Left { get; } new IBinaryTree<T>? Right { get; } } internal interface IImmutableArray { Array? Array { get; } } public interface IImmutableDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyCollection<KeyValuePair<TKey, TValue>> { IImmutableDictionary<TKey, TValue> Clear(); IImmutableDictionary<TKey, TValue> Add(TKey key, TValue value); IImmutableDictionary<TKey, TValue> AddRange(IEnumerable<KeyValuePair<TKey, TValue>> pairs); IImmutableDictionary<TKey, TValue> SetItem(TKey key, TValue value); IImmutableDictionary<TKey, TValue> SetItems(IEnumerable<KeyValuePair<TKey, TValue>> items); IImmutableDictionary<TKey, TValue> RemoveRange(IEnumerable<TKey> keys); IImmutableDictionary<TKey, TValue> Remove(TKey key); bool Contains(KeyValuePair<TKey, TValue> pair); bool TryGetKey(TKey equalKey, out TKey actualKey); } internal interface IImmutableDictionaryInternal<TKey, TValue> { bool ContainsValue(TValue value); } [CollectionBuilder(typeof(ImmutableList), "Create")] public interface IImmutableList<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T> { IImmutableList<T> Clear(); int IndexOf(T item, int index, int count, IEqualityComparer<T>? equalityComparer); int LastIndexOf(T item, int index, int count, IEqualityComparer<T>? equalityComparer); IImmutableList<T> Add(T value); IImmutableList<T> AddRange(IEnumerable<T> items); IImmutableList<T> Insert(int index, T element); IImmutableList<T> InsertRange(int index, IEnumerable<T> items); IImmutableList<T> Remove(T value, IEqualityComparer<T>? equalityComparer); IImmutableList<T> RemoveAll(Predicate<T> match); IImmutableList<T> RemoveRange(IEnumerable<T> items, IEqualityComparer<T>? equalityComparer); IImmutableList<T> RemoveRange(int index, int count); IImmutableList<T> RemoveAt(int index); IImmutableList<T> SetItem(int index, T value); IImmutableList<T> Replace(T oldValue, T newValue, IEqualityComparer<T>? equalityComparer); } internal interface IImmutableListQueries<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T> { ImmutableList<TOutput> ConvertAll<TOutput>(Func<T, TOutput> converter); void ForEach(Action<T> action); ImmutableList<T> GetRange(int index, int count); void CopyTo(T[] array); void CopyTo(T[] array, int arrayIndex); void CopyTo(int index, T[] array, int arrayIndex, int count); bool Exists(Predicate<T> match); T? Find(Predicate<T> match); ImmutableList<T> FindAll(Predicate<T> match); int FindIndex(Predicate<T> match); int FindIndex(int startIndex, Predicate<T> match); int FindIndex(int startIndex, int count, Predicate<T> match); T? FindLast(Predicate<T> match); int FindLastIndex(Predicate<T> match); int FindLastIndex(int startIndex, Predicate<T> match); int FindLastIndex(int startIndex, int count, Predicate<T> match); bool TrueForAll(Predicate<T> match); int BinarySearch(T item); int BinarySearch(T item, IComparer<T>? comparer); int BinarySearch(int index, int count, T item, IComparer<T>? comparer); } [CollectionBuilder(typeof(ImmutableQueue), "Create")] public interface IImmutableQueue<T> : IEnumerable<T>, IEnumerable { bool IsEmpty { get; } IImmutableQueue<T> Clear(); T Peek(); IImmutableQueue<T> Enqueue(T value); IImmutableQueue<T> Dequeue(); } [CollectionBuilder(typeof(ImmutableHashSet), "Create")] public interface IImmutableSet<T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable { IImmutableSet<T> Clear(); bool Contains(T value); IImmutableSet<T> Add(T value); IImmutableSet<T> Remove(T value); bool TryGetValue(T equalValue, out T actualValue); IImmutableSet<T> Intersect(IEnumerable<T> other); IImmutableSet<T> Except(IEnumerable<T> other); IImmutableSet<T> SymmetricExcept(IEnumerable<T> other); IImmutableSet<T> Union(IEnumerable<T> other); bool SetEquals(IEnumerable<T> other); bool IsProperSubsetOf(IEnumerable<T> other); bool IsProperSupersetOf(IEnumerable<T> other); bool IsSubsetOf(IEnumerable<T> other); bool IsSupersetOf(IEnumerable<T> other); bool Overlaps(IEnumerable<T> other); } [CollectionBuilder(typeof(ImmutableStack), "Create")] public interface IImmutableStack<T> : IEnumerable<T>, IEnumerable { bool IsEmpty { get; } IImmutableStack<T> Clear(); IImmutableStack<T> Push(T value); IImmutableStack<T> Pop(); T Peek(); } [CollectionBuilder(typeof(ImmutableHashSet), "Create")] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] public sealed class ImmutableHashSet<T> : IImmutableSet<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable, IHashKeyCollection<T>, ICollection<T>, ISet<T>, ICollection, IStrongEnumerable<T, ImmutableHashSet<T>.Enumerator> { private sealed class HashBucketByValueEqualityComparer : IEqualityComparer<HashBucket> { private static readonly IEqualityComparer<HashBucket> s_defaultInstance = new HashBucketByValueEqualityComparer(EqualityComparer<T>.Default); private readonly IEqualityComparer<T> _valueComparer; internal static IEqualityComparer<HashBucket> DefaultInstance => s_defaultInstance; internal HashBucketByValueEqualityComparer(IEqualityComparer<T> valueComparer) { Requires.NotNull(valueComparer, "valueComparer"); _valueComparer = valueComparer; } public bool Equals(HashBucket x, HashBucket y) { return x.EqualsByValue(y, _valueComparer); } public int GetHashCode(HashBucket obj) { throw new NotSupportedException(); } } private sealed class HashBucketByRefEqualityComparer : IEqualityComparer<HashBucket> { private static readonly IEqualityComparer<HashBucket> s_defaultInstance = new HashBucketByRefEqualityComparer(); internal static IEqualityComparer<HashBucket> DefaultInstance => s_defaultInstance; private HashBucketByRefEqualityComparer() { } public bool Equals(HashBucket x, HashBucket y) { return x.EqualsByRef(y); } public int GetHashCode(HashBucket obj) { throw new NotSupportedException(); } } [DebuggerDisplay("Count = {Count}")] public sealed class Builder : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable, ISet<T>, ICollection<T> { private SortedInt32KeyNode<HashBucket> _root = SortedInt32KeyNode<HashBucket>.EmptyNode; private IEqualityComparer<T> _equalityComparer; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; private int _count; private ImmutableHashSet<T> _immutable; private int _version; public int Count => _count; bool ICollection<T>.IsReadOnly => false; public IEqualityComparer<T> KeyComparer { get { return _equalityComparer; } set { Requires.NotNull(value, "value"); if (value != _equalityComparer) { MutationResult mutationResult = ImmutableHashSet<T>.Union((IEnumerable<T>)this, new MutationInput(SortedInt32KeyNode<HashBucket>.EmptyNode, value, _hashBucketEqualityComparer, 0)); _immutable = null; _equalityComparer = value; Root = mutationResult.Root; _count = mutationResult.Count; } } } internal int Version => _version; private MutationInput Origin => new MutationInput(Root, _equalityComparer, _hashBucketEqualityComparer, _count); private SortedInt32KeyNode<HashBucket> Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } internal Builder(ImmutableHashSet<T> set) { Requires.NotNull(set, "set"); _root = set._root; _count = set._count; _equalityComparer = set._equalityComparer; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; _immutable = set; } public Enumerator GetEnumerator() { return new Enumerator(_root, this); } public ImmutableHashSet<T> ToImmutable() { return _immutable ?? (_immutable = ImmutableHashSet<T>.Wrap(_root, _equalityComparer, _count)); } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public bool Add(T item) { MutationResult result = ImmutableHashSet<T>.Add(item, Origin); Apply(result); return result.Count != 0; } public bool Remove(T item) { MutationResult result = ImmutableHashSet<T>.Remove(item, Origin); Apply(result); return result.Count != 0; } public bool Contains(T item) { return ImmutableHashSet<T>.Contains(item, Origin); } public void Clear() { _count = 0; Root = SortedInt32KeyNode<HashBucket>.EmptyNode; } public void ExceptWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Except(other, _equalityComparer, _hashBucketEqualityComparer, _root); Apply(result); } public void IntersectWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Intersect(other, Origin); Apply(result); } public bool IsProperSubsetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable<T> other) { return ImmutableHashSet<T>.Overlaps(other, Origin); } public bool SetEquals(IEnumerable<T> other) { if (this == other) { return true; } return ImmutableHashSet<T>.SetEquals(other, Origin); } public void SymmetricExceptWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.SymmetricExcept(other, Origin); Apply(result); } public void UnionWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Union(other, Origin); Apply(result); } void ICollection<T>.Add(T item) { Add(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void Apply(MutationResult result) { Root = result.Root; if (result.CountType == CountType.Adjustment) { _count += result.Count; } else { _count = result.Count; } } } public struct Enumerator : IEnumerator<T>, IEnumerator, IDisposable, IStrongEnumerator<T> { private readonly Builder _builder; private SortedInt32KeyNode<HashBucket>.Enumerator _mapEnumerator; private HashBucket.Enumerator _bucketEnumerator; private int _enumeratingBuilderVersion; public T Current { get { _mapEnumerator.ThrowIfDisposed(); return _bucketEnumerator.Current; } } object? IEnumerator.Current => Current; internal Enumerator(SortedInt32KeyNode<HashBucket> root, Builder? builder = null) { _builder = builder; _mapEnumerator = new SortedInt32KeyNode<HashBucket>.Enumerator(root); _bucketEnumerator = default(HashBucket.Enumerator); _enumeratingBuilderVersion = builder?.Version ?? (-1); } public bool MoveNext() { ThrowIfChanged(); if (_bucketEnumerator.MoveNext()) { return true; } if (_mapEnumerator.MoveNext()) { _bucketEnumerator = new HashBucket.Enumerator(_mapEnumerator.Current.Value); return _bucketEnumerator.MoveNext(); } return false; } public void Reset() { _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _mapEnumerator.Reset(); _bucketEnumerator.Dispose(); _bucketEnumerator = default(HashBucket.Enumerator); } public void Dispose() { _mapEnumerator.Dispose(); _bucketEnumerator.Dispose(); } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } } internal enum OperationResult { SizeChanged, NoChangeRequired } internal readonly struct HashBucket { internal struct Enumerator : IEnumerator<T>, IEnumerator, IDisposable { private enum Position { BeforeFirst, First, Additional, End } private readonly HashBucket _bucket; private bool _disposed; private Position _currentPosition; private ImmutableList<T>.Enumerator _additionalEnumerator; object? IEnumerator.Current => Current; public T Current { get { ThrowIfDisposed(); return _currentPosition switch { Position.First => _bucket._firstValue, Position.Additional => _additionalEnumerator.Current, _ => throw new InvalidOperationException(), }; } } internal Enumerator(HashBucket bucket) { _disposed = false; _bucket = bucket; _currentPosition = Position.BeforeFirst; _additionalEnumerator = default(ImmutableList<T>.Enumerator); } public bool MoveNext() { ThrowIfDisposed(); if (_bucket.IsEmpty) { _currentPosition = Position.End; return false; } switch (_currentPosition) { case Position.BeforeFirst: _currentPosition = Position.First; return true; case Position.First: if (_bucket._additionalElements.IsEmpty) { _currentPosition = Position.End; return false; } _currentPosition = Position.Additional; _additionalEnumerator = new ImmutableList<T>.Enumerator(_bucket._additionalElements); return _additionalEnumerator.MoveNext(); case Position.Additional: return _additionalEnumerator.MoveNext(); case Position.End: return false; default: throw new InvalidOperationException(); } } public void Reset() { ThrowIfDisposed(); _additionalEnumerator.Dispose(); _currentPosition = Position.BeforeFirst; } public void Dispose() { _disposed = true; _additionalEnumerator.Dispose(); } private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } private readonly T _firstValue; private readonly ImmutableList<T>.Node _additionalElements; internal bool IsEmpty => _additionalElements == null; private HashBucket(T firstElement, ImmutableList<T>.Node additionalElements = null) { _firstValue = firstElement; _additionalElements = additionalElements ?? ImmutableList<T>.Node.EmptyNode; } public Enumerator GetEnumerator() { return new Enumerator(this); } public override bool Equals(object? obj) { throw new NotSupportedException(); } public override int GetHashCode() { throw new NotSupportedException(); } internal bool EqualsByRef(HashBucket other) { if ((object)_firstValue == (object)other._firstValue) { return _additionalElements == other._additionalElements; } return false; } internal bool EqualsByValue(HashBucket other, IEqualityComparer<T> valueComparer) { if (valueComparer.Equals(_firstValue, other._firstValue)) { return _additionalElements == other._additionalElements; } return false; } internal HashBucket Add(T value, IEqualityComparer<T> valueComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.SizeChanged; return new HashBucket(value); } if (valueComparer.Equals(value, _firstValue) || _additionalElements.IndexOf(value, valueComparer) >= 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.Add(value)); } internal bool Contains(T value, IEqualityComparer<T> valueComparer) { if (IsEmpty) { return false; } if (!valueComparer.Equals(value, _firstValue)) { return _additionalElements.IndexOf(value, valueComparer) >= 0; } return true; } internal bool TryExchange(T value, IEqualityComparer<T> valueComparer, out T existingValue) { if (!IsEmpty) { if (valueComparer.Equals(value, _firstValue)) { existingValue = _firstValue; return true; } int num = _additionalElements.IndexOf(value, valueComparer); if (num >= 0) { existingValue = _additionalElements.ItemRef(num); return true; } } existingValue = value; return false; } internal HashBucket Remove(T value, IEqualityComparer<T> equalityComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.NoChangeRequired; return this; } if (equalityComparer.Equals(_firstValue, value)) { if (_additionalElements.IsEmpty) { result = OperationResult.SizeChanged; return default(HashBucket); } int count = _additionalElements.Left.Count; result = OperationResult.SizeChanged; return new HashBucket(_additionalElements.Key, _additionalElements.RemoveAt(count)); } int num = _additionalElements.IndexOf(value, equalityComparer); if (num < 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.RemoveAt(num)); } internal void Freeze() { _additionalElements?.Freeze(); } } private readonly struct MutationInput { private readonly SortedInt32KeyNode<HashBucket> _root; private readonly IEqualityComparer<T> _equalityComparer; private readonly int _count; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; internal SortedInt32KeyNode<HashBucket> Root => _root; internal IEqualityComparer<T> EqualityComparer => _equalityComparer; internal int Count => _count; internal IEqualityComparer<HashBucket> HashBucketEqualityComparer => _hashBucketEqualityComparer; internal MutationInput(ImmutableHashSet<T> set) { Requires.NotNull(set, "set"); _root = set._root; _equalityComparer = set._equalityComparer; _count = set._count; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; } internal MutationInput(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, IEqualityComparer<HashBucket> hashBucketEqualityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); Requires.NotNull(hashBucketEqualityComparer, "hashBucketEqualityComparer"); _root = root; _equalityComparer = equalityComparer; _count = count; _hashBucketEqualityComparer = hashBucketEqualityComparer; } } private enum CountType { Adjustment, FinalValue } private readonly struct MutationResult { private readonly SortedInt32KeyNode<HashBucket> _root; private readonly int _count; private readonly CountType _countType; internal SortedInt32KeyNode<HashBucket> Root => _root; internal int Count => _count; internal CountType CountType => _countType; internal MutationResult(SortedInt32KeyNode<HashBucket> root, int count, CountType countType = CountType.Adjustment) { Requires.NotNull(root, "root"); _root = root; _count = count; _countType = countType; } internal ImmutableHashSet<T> Finalize(ImmutableHashSet<T> priorSet) { Requires.NotNull(priorSet, "priorSet"); int num = Count; if (CountType == CountType.Adjustment) { num += priorSet._count; } return priorSet.Wrap(Root, num); } } private readonly struct NodeEnumerable : IEnumerable<T>, IEnumerable { private readonly SortedInt32KeyNode<HashBucket> _root; internal NodeEnumerable(SortedInt32KeyNode<HashBucket> root) { Requires.NotNull(root, "root"); _root = root; } public Enumerator GetEnumerator() { return new Enumerator(_root); } [ExcludeFromCodeCoverage] IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static readonly ImmutableHashSet<T> Empty = new ImmutableHashSet<T>(SortedInt32KeyNode<HashBucket>.EmptyNode, EqualityComparer<T>.Default, 0); private static readonly Action<KeyValuePair<int, HashBucket>> s_FreezeBucketAction = delegate(KeyValuePair<int, HashBucket> kv) { kv.Value.Freeze(); }; private readonly IEqualityComparer<T> _equalityComparer; private readonly int _count; private readonly SortedInt32KeyNode<HashBucket> _root; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; public int Count => _count; public bool IsEmpty => Count == 0; public IEqualityComparer<T> KeyComparer => _equalityComparer; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; internal IBinaryTree Root => _root; private MutationInput Origin => new MutationInput(this); bool ICollection<T>.IsReadOnly => true; internal ImmutableHashSet(IEqualityComparer<T> equalityComparer) : this(SortedInt32KeyNode<HashBucket>.EmptyNode, equalityComparer, 0) { } private ImmutableHashSet(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); root.Freeze(s_FreezeBucketAction); _root = root; _count = count; _equalityComparer = equalityComparer; _hashBucketEqualityComparer = GetHashBucketEqualityComparer(equalityComparer); } public ImmutableHashSet<T> Clear() { if (!IsEmpty) { return Empty.WithComparer(_equalityComparer); } return this; } IImmutableSet<T> IImmutableSet<T>.Clear() { return Clear(); } public Builder ToBuilder() { return new Builder(this); } public ImmutableHashSet<T> Add(T item) { return Add(item, Origin).Finalize(this); } public ImmutableHashSet<T> Remove(T item) { return Remove(item, Origin).Finalize(this); } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public ImmutableHashSet<T> Union(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Union(other, avoidWithComparer: false); } internal ImmutableHashSet<T> Union(ReadOnlySpan<T> other) { return Union(other, Origin).Finalize(this); } public ImmutableHashSet<T> Intersect(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Intersect(other, Origin).Finalize(this); } public ImmutableHashSet<T> Except(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Except(other, _equalityComparer, _hashBucketEqualityComparer, _root).Finalize(this); } public ImmutableHashSet<T> SymmetricExcept(IEnumerable<T> other) { Requires.NotNull(other, "other"); return SymmetricExcept(other, Origin).Finalize(this); } public bool SetEquals(IEnumerable<T> other) { Requires.NotNull(other, "other"); if (this == other) { return true; } return SetEquals(other, Origin); } public bool IsProperSubsetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Overlaps(other, Origin); } IImmutableSet<T> IImmutableSet<T>.Add(T item) { return Add(item); } IImmutableSet<T> IImmutableSet<T>.Remove(T item) { return Remove(item); } IImmutableSet<T> IImmutableSet<T>.Union(IEnumerable<T> other) { return Union(other); } IImmutableSet<T> IImmutableSet<T>.Intersect(IEnumerable<T> other) { return Intersect(other); } IImmutableSet<T> IImmutableSet<T>.Except(IEnumerable<T> other) { return Except(other); } IImmutableSet<T> IImmutableSet<T>.SymmetricExcept(IEnumerable<T> other) { return SymmetricExcept(other); } public bool Contains(T item) { return Contains(item, Origin); } public ImmutableHashSet<T> WithComparer(IEqualityComparer<T>? equalityComparer) { if (equalityComparer == null) { equalityComparer = EqualityComparer<T>.Default; } if (equalityComparer == _equalityComparer) { return this; } return new ImmutableHashSet<T>(equalityComparer).Union(this, avoidWithComparer: true); } bool ISet<T>.Add(T item) { throw new NotSupportedException(); } void ISet<T>.ExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.IntersectWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.SymmetricExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.UnionWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } public Enumerator GetEnumerator() { return new Enumerator(_root); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty<T>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static bool IsSupersetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (!Contains(item, origin)) { return false; } } return true; } private static MutationResult Add(T item, MutationInput origin) { int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = origin.Root.GetValueOrDefault(num).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } return new MutationResult(UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket), 1); } private static MutationResult Remove(T item, MutationInput origin) { OperationResult result = OperationResult.NoChangeRequired; int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); SortedInt32KeyNode<HashBucket> root = origin.Root; if (origin.Root.TryGetValue(num, out var value)) { HashBucket newBucket = value.Remove(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } root = UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket); } return new MutationResult(root, (result == OperationResult.SizeChanged) ? (-1) : 0); } private static bool Contains(T item, MutationInput origin) { int key = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); if (origin.Root.TryGetValue(key, out var value)) { return value.Contains(item, origin.EqualityComparer); } return false; } private static MutationResult Union(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); int num = 0; SortedInt32KeyNode<HashBucket> sortedInt32KeyNode = origin.Root; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { int num2 = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(num2).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.SizeChanged) { sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, origin.HashBucketEqualityComparer, newBucket); num++; } } return new MutationResult(sortedInt32KeyNode, num); } private static MutationResult Union(ReadOnlySpan<T> other, MutationInput origin) { int num = 0; SortedInt32KeyNode<HashBucket> sortedInt32KeyNode = origin.Root; ReadOnlySpan<T> readOnlySpan = other; for (int i = 0; i < readOnlySpan.Length; i++) { T val = readOnlySpan[i]; int num2 = ((val != null) ? origin.EqualityComparer.GetHashCode(val) : 0); OperationResult result; HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(num2).Add(val, origin.EqualityComparer, out result); if (result == OperationResult.SizeChanged) { sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, origin.HashBucketEqualityComparer, newBucket); num++; } } return new MutationResult(sortedInt32KeyNode, num); } private static bool Overlaps(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (Contains(item, origin)) { return true; } } return false; } private static bool SetEquals(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); if (origin.Count != hashSet.Count) { return false; } foreach (T item in hashSet) { if (!Contains(item, origin)) { return false; } } return true; } private static SortedInt32KeyNode<HashBucket> UpdateRoot(SortedInt32KeyNode<HashBucket> root, int hashCode, IEqualityComparer<HashBucket> hashBucketEqualityComparer, HashBucket newBucket) { bool mutated; if (newBucket.IsEmpty) { return root.Remove(hashCode, out mutated); } bool mutated2; return root.SetItem(hashCode, newBucket, hashBucketEqualityComparer, out mutated, out mutated2); } private static MutationResult Intersect(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); SortedInt32KeyNode<HashBucket> root = SortedInt32KeyNode<HashBucket>.EmptyNode; int num = 0; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (Contains(item, origin)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static MutationResult Except(IEnumerable<T> other, IEqualityComparer<T> equalityComparer, IEqualityComparer<HashBucket> hashBucketEqualityComparer, SortedInt32KeyNode<HashBucket> root) { Requires.NotNull(other, "other"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.NotNull(root, "root"); int num = 0; SortedInt32KeyNode<HashBucket> sortedInt32KeyNode = root; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { int num2 = ((item != null) ? equalityComparer.GetHashCode(item) : 0); if (sortedInt32KeyNode.TryGetValue(num2, out var value)) { OperationResult result; HashBucket newBucket = value.Remove(item, equalityComparer, out result); if (result == OperationResult.SizeChanged) { num--; sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, hashBucketEqualityComparer, newBucket); } } } return new MutationResult(sortedInt32KeyNode, num); } private static MutationResult SymmetricExcept(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); ImmutableHashSet<T> immutableHashSet = ImmutableHashSet.CreateRange(origin.EqualityComparer, other); int num = 0; SortedInt32KeyNode<HashBucket> root = SortedInt32KeyNode<HashBucket>.EmptyNode; foreach (T item in new NodeEnumerable(origin.Root)) { if (!immutableHashSet.Contains(item)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } foreach (T item2 in immutableHashSet) { if (!Contains(item2, origin)) { MutationResult mutationResult2 = Add(item2, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult2.Root; num += mutationResult2.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static bool IsProperSubsetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return other.Any(); } HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); if (origin.Count >= hashSet.Count) { return false; } int num = 0; bool flag = false; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } else { flag = true; } if (num == origin.Count && flag) { return true; } } return false; } private static bool IsProperSupersetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } int num = 0; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { num++; if (!Contains(item, origin)) { return false; } } return origin.Count > num; } private static bool IsSubsetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return true; } HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); int num = 0; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } } return num == origin.Count; } private static ImmutableHashSet<T> Wrap(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); return new ImmutableHashSet<T>(root, equalityComparer, count); } private static IEqualityComparer<HashBucket> GetHashBucketEqualityComparer(IEqualityComparer<T> valueComparer) { if (!ImmutableExtensions.IsValueType<T>()) { return HashBucketByRefEqualityComparer.DefaultInstance; } if (valueComparer == EqualityComparer<T>.Default) { return HashBucketByValueEqualityComparer.DefaultInstance; } return new HashBucketByValueEqualityComparer(valueComparer); } private ImmutableHashSet<T> Wrap(SortedInt32KeyNode<HashBucket> root, int adjustedCountIfDifferentRoot) { if (root == _root) { return this; } return new ImmutableHashSet<T>(root, _equalityComparer, adjustedCountIfDifferentRoot); } private ImmutableHashSet<T> Union(IEnumerable<T> items, bool avoidWithComparer) { Requires.NotNull(items, "items"); if (IsEmpty && !avoidWithComparer && items is ImmutableHashSet<T> immutableHashSet) { return immutableHashSet.WithComparer(KeyComparer); } return Union(items, Origin).Finalize(this); } } internal interface IStrongEnumerable<out T, TEnumerator> where TEnumerator : struct, IStrongEnumerator<T> { TEnumerator GetEnumerator(); } internal interface IStrongEnumerator<T> { T Current { get; } bool MoveNext(); } internal interface IOrderedCollection<out T> : IEnumerable<T>, IEnumerable { int Count { get; } T this[int index] { get; } } public static class ImmutableArray { internal static readonly byte[] TwoElementArray = new byte[2]; public static ImmutableArray<T> Create<T>() { return ImmutableArray<T>.Empty; } public static ImmutableArray<T> Create<T>(T item) { return new ImmutableArray<T>(new T[1] { item }); } public static ImmutableArray<T> Create<T>(T item1, T item2) { return new ImmutableArray<T>(new T[2] { item1, item2 }); } public static ImmutableArray<T> Create<T>(T item1, T item2, T item3) { return new ImmutableArray<T>(new T[3] { item1, item2, item3 }); } public static ImmutableArray<T> Create<T>(T item1, T item2, T item3, T item4) { return new ImmutableArray<T>(new T[4] { item1, item2, item3, item4 }); } public static ImmutableArray<T> Create<T>([ParamCollection] scoped ReadOnlySpan<T> items) { if (items.IsEmpty) { return ImmutableArray<T>.Empty; } return new ImmutableArray<T>(items.ToArray()); } public static ImmutableArray<T> Create<T>(Span<T> items) { return Create((ReadOnlySpan<T>)items); } public static ImmutableArray<T> ToImmutableArray<T>(this ReadOnlySpan<T> items) { return Create(items); } public static ImmutableArray<T> ToImmutableArray<T>(this Span<T> items) { return Create((ReadOnlySpan<T>)items); } public static ImmutableArray<T> CreateRange<T>(IEnumerable<T> items) { Requires.NotNull(items, "items"); if (items is IImmutableArray immutableArray) { return new ImmutableArray<T>((T[])(immutableArray.Array ?? throw new InvalidOperationException(System.SR.InvalidOperationOnDefaultArray))); } if (items.TryGetCount(out var count)) { return new ImmutableArray<T>(items.ToArray(count)); } return new ImmutableArray<T>(items.ToArray()); } public static ImmutableArray<T> Create<T>(params T[]? items) { if (items == null || items.Length == 0) { return ImmutableArray<T>.Empty; } T[] array = new T[items.Length]; Array.Copy(items, array, items.Length); return new ImmutableArray<T>(array); } public static ImmutableArray<T> Create<T>(T[] items, int start, int length) { Requires.NotNull(items, "items"); Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create<T>(); } T[] array = new T[length]; for (int i = 0; i < array.Length; i++) { array[i] = items[start + i]; } return new ImmutableArray<T>(array); } public static ImmutableArray<T> Create<T>(ImmutableArray<T> items, int start, int length) { Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create<T>(); } if (start == 0 && length == items.Length) { return items; } T[] array = new T[length]; Array.Copy(items.array, start, array, 0, length); return new ImmutableArray<T>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TResult>(ImmutableArray<TSource> items, Func<TSource, TResult> selector) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i]); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TResult>(ImmutableArray<TSource> items, int start, int length, Func<TSource, TResult> selector) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start]); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TArg, TResult>(ImmutableArray<TSource> items, Func<TSource, TArg, TResult> selector, TArg arg) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i], arg); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TArg, TResult>(ImmutableArray<TSource> items, int start, int length, Func<TSource, TArg, TResult> selector, TArg arg) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start], arg); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<T>.Builder CreateBuilder<T>() { return Create<T>().ToBuilder(); } public static ImmutableArray<T>.Builder CreateBuilder<T>(int initialCapacity) { return new ImmutableArray<T>.Builder(initialCapacity); } public static ImmutableArray<TSource> ToImmutableArray<TSource>(this IEnumerable<TSource> items) { if (items is ImmutableArray<TSource>) { return (ImmutableArray<TSource>)(object)items; } return CreateRange(items); } public static ImmutableArray<TSource> ToImmutableArray<TSource>(this ImmutableArray<TSource>.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static int BinarySearch<T>(this ImmutableArray<T> array, T value) { return Array.BinarySearch(array.array, value); } public static int BinarySearch<T>(this ImmutableArray<T> array, T value, IComparer<T>? comparer) { return Array.BinarySearch(array.array, value, comparer); } public static int BinarySearch<T>(this ImmutableArray<T> array, int index, int length, T value) { return Array.BinarySearch(array.array, index, length, value); } public static int BinarySearch<T>(this ImmutableArray<T> array, int index, int length, T value, IComparer<T>? comparer) { return Array.BinarySearch(array.array, index, length, value, comparer); } } [CollectionBuilder(typeof(ImmutableArray), "Create")] [DebuggerDisplay("{DebuggerDisplay,nq}")] [System.Runtime.Versioning.NonVersionable] public readonly struct ImmutableArray<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T>, IList<T>, ICollection<T>, IEquatable<ImmutableArray<T>>, IList, ICollection, IImmutableArray, IStructuralComparable, IStructuralEquatable, IImmutableList<T> { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableArrayBuilderDebuggerProxy<>))] public sealed class Builder : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IReadOnlyList<T>, IReadOnlyCollection<T> { private T[] _elements; private int _count; public int Capacity { get { return _elements.Length; } set { if (value < _count) { throw new ArgumentException(System.SR.CapacityMustBeGreaterThanOrEqualToCount, "value"); } if (value == _elements.Length) { return; } if (value > 0) { T[] array = new T[value]; if (_count > 0) { Array.Copy(_elements, array, _count); } _elements = array; } else { _elements = ImmutableArray<T>.Empty.array; } } } public int Count { get { return _count; } set { Requires.Range(value >= 0, "value"); if (value < _count) { if (_count - value > 64) { Array.Clear(_elements, value, _count - value); } else { for (int i = value; i < Count; i++) { _elements[i] = default(T); } } } else if (value > _count) { EnsureCapacity(value); } _count = value; } } public T this[int index] { get { if (index >= Count) { ThrowIndexOutOfRangeException(); } return _elements[index]; } set { if (index >= Count) { ThrowIndexOutOfRangeException(); } _elements[index] = value; } } bool ICollection<T>.IsReadOnly => false; internal Builder(int capacity) { Requires.Range(capacity >= 0, "capacity"); _elements = new T[capacity]; _count = 0; } internal Builder() : this(8) { } private static void ThrowIndexOutOfRangeException() { throw new IndexOutOfRangeException(); } public ref readonly T ItemRef(int index) { if (index >= Count) { ThrowIndexOutOfRangeException(); } return ref _elements[index]; } public ImmutableArray<T> ToImmutable() { return new ImmutableArray<T>(ToArray()); } public ImmutableArray<T> MoveToImmutable() { if (Capacity != Count) { throw new InvalidOperationException(System.SR.CapacityMustEqualCountOnMove); } T[] elements = _elements; _elements = ImmutableArray<T>.Empty.array; _count = 0; return new ImmutableArray<T>(elements); } public ImmutableArray<T> DrainToImmutable() { T[] array = _elements; if (array.Length != _count) { array = ToArray(); } _elements = ImmutableArray<T>.Empty.array; _count = 0; return new ImmutableArray<T>(array); } public void Clear() { Count = 0; } public void Insert(int index, T item) { Requires.Range(index >= 0 && index <= Count, "index"); EnsureCapacity(Count + 1); if (index < Count) { Array.Copy(_elements, index, _elements, index + 1, Count - index); } _count++; _elements[index] = item; } public void InsertRange(int index, IEnumerable<T> items) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.NotNull(items, "items"); int count = ImmutableExtensions.GetCount(ref items); EnsureCapacity(Count + count); if (index != Count) { Array.Copy(_elements, index, _elements, index + count, _count - index); } if (!items.TryCopyTo(_elements, index)) { foreach (T item in items) { _elements[index++] = item; } } _count += count; } public void InsertRange(int index, ImmutableArray<T> items) { Requires.Range(index >= 0 && index <= Count, "index"); if (!items.IsEmpty) { EnsureCapacity(Count + items.Length); if (index != Count) { Array.Copy(_elements, index, _elements, index + items.Length, _count - index); } Array.Copy(items.array, 0, _elements, index, items.Length); _count += items.Length; } } public void Add(T item) { int num = _count + 1; EnsureCapacity(num); _elements[_count] = item; _count = num; } public void AddRange(IEnumerable<T> items) { Requires.NotNull(items, "items"); if (items.TryGetCount(out var count)) { EnsureCapacity(Count + count); if (items.TryCopyTo(_elements, _count)) { _count += count; return; } } foreach (T item in items) { Add(item); } } public void AddRange(params T[] items) { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange<TDerived>(TDerived[] items) where TDerived : T { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange(T[] items, int length) { Requires.NotNull(items, "items"); Requires.Range(length >= 0 && length <= items.Length, "length"); int count = Count; Count += length; Array.Copy(items, 0, _elements, count, length); } public void AddRange(ImmutableArray<T> items) { AddRange(items, items.Length); } public void AddRange(ImmutableArray<T> items, int length) { Requires.Range(length >= 0, "length"); if (items.array != null) { AddRange(items.array, length); } } public void AddRange([ParamCollection] scoped ReadOnlySpan<T> items) { int count = Count; Count += items.Length; items.CopyTo(new Span<T>(_elements, count, items.Length)); } public void AddRange<TDerived>([ParamCollection] scoped ReadOnlySpan<TDerived> items) where TDerived : T { int count = Count; Count += items.Length; Span<T> span = new Span<T>(_elements, count, items.Length); for (int i = 0; i < items.Length; i++) { span[i] = (T)(object)items[i]; } } public void AddRange<TDerived>(ImmutableArray<TDerived> items) where TDerived : T { if (items.array != null) { this.AddRange<TDerived>(items.array); } } public void AddRange(Builder items) { Requires.NotNull(items, "items"); AddRange(items._elements, items.Count); } public void AddRange<TDerived>(ImmutableArray<TDerived>.Builder items) where TDerived : T { Requires.NotNull(items, "items"); AddRange<TDerived>(items._elements, items.Count); } public bool Remove(T element) { int num = IndexOf(element); if (num >= 0) { RemoveAt(num); return true; } return false; } public bool Remove(T element, IEqualityComparer<T>? equalityComparer) { int num = IndexOf(element, 0, _count, equalityComparer); if (num >= 0) { RemoveAt(num); return true; } return false; } public void RemoveAll(Predicate<T> match) { List<int> list = null; for (int i = 0; i < _count; i++) { if (match(_elements[i])) { if (list == null) { list = new List<int>(); } list.Add(i); } } if (list != null) { RemoveAtRange(list); } } public void RemoveAt(int index) { Requires.Range(index >= 0 && index < Count, "index"); if (index < Count - 1) { Array.Copy(_elements, index + 1, _elements, index, Count - index - 1); } Count--; } public void RemoveRange(int index, int length) { Requires.Range(index >= 0 && index <= _count, "index"); Requires.Range(length >= 0 && index <= _count - length, "length"); if (length != 0) { if (index + length < _count) { Array.Copy(_elements, index + length, _elements, index, Count - index - length); } _count -= length; } } public void RemoveRange(IEnumerable<T> items) { RemoveRange(items, EqualityComparer<T>.Default); } public void RemoveRange(IEnumerable<T> items, IEqualityComparer<T>? equalityComparer) { Requires.NotNull(items, "items"); SortedSet<int> sortedSet = new SortedSet<int>(); foreach (T item in items) { int num = IndexOf(item, 0, _count, equalityComparer); while (num >= 0 && !sortedSet.Add(num) && num + 1 < _count) { num = IndexOf(item, num + 1, equalityComparer); } } RemoveAtRange(sortedSet); } public void Replace(T oldValue, T newValue) { Replace(oldValue, newValue, EqualityComparer<T>.Default); } public void Replace(T oldValue, T newValue, IEqualityComparer<T>? equalityComparer) { int num = IndexOf(oldValue, 0, _count, equalityComparer); if (num >= 0) { _elements[num] = newValue; } } public bool Contains(T item) { return IndexOf(item) >= 0; } public T[] ToArray() { if (Count == 0) { return ImmutableArray<T>.Empty.array; } T[] array = new T[Count]; Array.Copy(_elements, array, Count); return array; } public void CopyTo(T[] array, int index) { Requires.NotNull(array, "array"); Requires.Range(index >= 0 && index + Count <= array.Length, "index"); Array.Copy(_elements, 0, array, index, Count); } public void CopyTo(T[] destination) { Requires.NotNull(destination, "destination"); Array.Copy(_elements, 0, destination, 0, Count); } public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { Requires.NotNull(destination, "destination"); Requires.Range(length >= 0, "length"); Requires.Range(sourceIndex >= 0 && sourceIndex + length <= Count, "sourceIndex"); Requires.Range(destinationIndex >= 0 && destinationIndex + length <= destination.Length, "destinationIndex"); Array.Copy(_elements, sourceIndex, destination, destinationIndex, length); } private void EnsureCapacity(int capacity) { if (_elements.Length < capacity) { int newSize = Math.Max(_elements.Length * 2, capacity); Array.Resize(ref _elements, newSize); } } public int IndexOf(T item) { return IndexOf(item, 0, _count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex) { return IndexOf(item, startIndex, Count - startIndex, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= Count, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer<T>.Default; } if (equalityComparer == EqualityComparer<T>.Default) { return Array.IndexOf(_elements, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(_elements[i], item)) { return i; } } return -1; } public int IndexOf(T item, int startIndex, IEqualityComparer<T>? equalityComparer) { return IndexOf(item, startIndex, Count - startIndex, equalityComparer); } public int LastIndexOf(T item) { if (Count == 0) { return -1; } return LastIndexOf(item, Count - 1, Count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex) { if (Count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); return LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex - count + 1 >= 0, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer<T>.Default; } if (equalityComparer == EqualityComparer<T>.Default) { return Array.LastIndexOf(_elements, item, startIndex, count); } for (int num = startIndex; num >= startIndex - count + 1; num--) { if (equalityComparer.Equals(item, _elements[num])) { return num; } } return -1; } public void Reverse() { int num = 0; int num2 = _count - 1; T[] elements = _elements; while (num < num2) { T val = elements[num]; elements[num] = elements[num2]; elements[num2] = val; num++; num2--; } } public void Sort() { if (Count > 1) { Array.Sort(_elements, 0, Count, Comparer<T>.Default); } } public void Sort(Comparison<T> comparison) { Requires.NotNull(comparison, "comparison"); if (Count > 1) { Array.Sort(_elements, 0, _count, Comparer<T>.Create(comparison)); } } public void Sort(IComparer<T>? comparer) { if (Count > 1) { Array.Sort(_elements, 0, _count, comparer); } } public void Sort(int index, int count, IComparer<T>? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && index + count <= Count, "count"); if (count > 1) { Array.Sort(_elements, index, count, comparer); } } public void CopyTo(Span<T> destination) { Requires.Range(Count <= destination.Length, "destination"); new ReadOnlySpan<T>(_elements, 0, Count).CopyTo(destination); } public IEnumerator<T> GetEnumerator() { for (int i = 0; i < Count; i++) { yield return this[i]; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void AddRange<TDerived>(TDerived[] items, int length) where TDerived : T { EnsureCapacity(Count + length); int count = Count; Count += length; T[] elements = _elements; for (int i = 0; i < length; i++) { elements[count + i] = (T)(object)items[i]; } } private void RemoveAtRange(ICollection<int> indicesToRemove) { Requires.NotNull(indicesToRemove, "indicesToRemove"); if (indicesToRemove.Count == 0) { return; } int num = 0; int num2 = 0; int num3 = -1; foreach (int item in indicesToRemove) { int num4 = ((num3 == -1) ? item : (item - num3 - 1)); Array.Copy(_elements, num + num2, _elements, num, num4); num2++; num += num4; num3 = item; } Array.Copy(_elements, num + num2, _elements, num, _elements.Length - (num + num2)); _count -= indicesToRemove.Count; } } public struct Enumerator { private readonly T[] _array; private int _index; public T Current => _array[_index]; internal Enumerator(T[] array) { _array = array; _index = -1; } public bool MoveNext() { return ++_index < _array.Length; } } private sealed class EnumeratorObject : IEnumerator<T>, IEnumerator, IDisposable { private static readonly IEnumerator<T> s_EmptyEnumerator = new EnumeratorObject(ImmutableArray<T>.Empty.array); private readonly T[] _array; private int _index; public T Current { get { if ((uint)_index < (uint)_array.Length) { return _array[_index]; } throw new InvalidOperationException(); } } object IEnumerator.Current => Current; private EnumeratorObject(T[] array) { _index = -1; _array = array; } public bool MoveNext() { int num = _index + 1; int num2 = _array.Length; if ((uint)num <= (uint)num2) { _index = num; return (uint)num < (uint)num2; } return false; } void IEnumerator.Reset() { _index = -1; } public void Dispose() { } internal static IEnumerator<T> Create(T[] array) { if (array.Length != 0) { return new EnumeratorObject(array); } return s_EmptyEnumerator; } } public static readonly ImmutableArray<T> Empty = new ImmutableArray<T>(new T[0]); [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] internal readonly T[]? array; T IList<T>.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection<T>.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection<T>.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] int IReadOnlyCollection<T>.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } T IReadOnlyList<T>.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsFixedSize => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { throw new NotSupportedException(); } } object? IList.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } public T this[int index] { [System.Runtime.Versioning.NonVersionable] get { return array[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsEmpty { [System.Runtime.Versioning.NonVersionable] get { return array.Length == 0; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int Length { [System.Runtime.Versioning.NonVersionable] get { return array.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefault => array == null; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefaultOrEmpty { get { ImmutableArray<T> immutableArray = this; if (immutableArray.array != null) { return immutableArray.array.Length == 0; } return true; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] Array? IImmutableArray.Array => array; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { ImmutableArray<T> immutableArray = this; if (!immutableArray.IsDefault) { return $"Length = {immutableArray.Length}"; } return "Uninitialized"; } } public ReadOnlySpan<T> AsSpan() { return new ReadOnlySpan<T>(array); } public ReadOnlyMemory<T> AsMemory() { return new ReadOnlyMemory<T>(array); } public int IndexOf(T item) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, 0, immutableArray.Length, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, equalityComparer); } public int IndexOf(T item, int startIndex) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < immutableArray.Length, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= immutableArray.Length, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer<T>.Default; } if (equalityComparer == EqualityComparer<T>.Default) { return Array.IndexOf(immutableArray.array, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(immutableArray.array[i], item)) { return i; } } return -1; } public int LastIndexOf(T item) { ImmutableArray<T> immutableArray = this; if (immutableArray.IsEmpty) { return -1; } return immutableArray.LastIndexOf(item, immutableArray.Length - 1, immutableArray.Length, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex) { ImmutableArray<T> immutableArray = this; if (immutableArray.IsEmpty && startIndex == 0) { return -1; } return immutableArray.LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equal