The BepInEx console will not appear when launching like it does for other games on Thunderstore. This is normal (and helps prevent crashes during startup). You can turn it back on in your BepInEx.cfg file.
Decompiled source of CrowdControl PEAK v1.0.7
BepInEx/plugins/ConnectorLib.JSON.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Warp World, Inc.")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("© 2025 Warp World, Inc.")] [assembly: AssemblyFileVersion("5.0.9299.32646")] [assembly: AssemblyInformationalVersion("5.0.9299.32646+e2a6a5d40e916037290e0657900cfb663ef7bafa")] [assembly: AssemblyProduct("ConnectorLib.JSON")] [assembly: AssemblyTitle("ConnectorLib.JSON")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.0.9299.32646")] [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() { T[] source = (T[])Enum.GetValues(typeof(T)); _attributes = source.Select((T m) => new KeyValuePair<T, JsonValueAttribute>(m, GetAttributeOfType<JsonValueAttribute>(m))).ToDictionary(); } private static T? GetAttributeOfType<T>(Enum enumVal) where T : Attribute { Enum enumVal2 = enumVal; Type type = enumVal2.GetType(); MemberInfo memberInfo = type.GetTypeInfo().DeclaredMembers.First((MemberInfo m) => string.Equals(m.Name, enumVal2.ToString(), StringComparison.Ordinal)); object[] array = memberInfo.GetCustomAttributes(typeof(T), inherit: false).ToArray(); return (array.Length != 0) ? ((T)array[0]) : null; } public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) { JsonValueAttribute jsonValueAttribute = _attributes[value]; if (jsonValueAttribute != null) { serializer.Serialize(writer, (object)jsonValueAttribute.Value); } else { serializer.Serialize(writer, (object)Enum.GetName(typeof(T), value)); } } public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer) { string value = serializer.Deserialize<string>(reader); if (value == null) { return default(T); } KeyValuePair<T, JsonValueAttribute>? keyValuePair = _attributes.Cast<KeyValuePair<T, JsonValueAttribute>?>().FirstOrDefault((KeyValuePair<T, JsonValueAttribute>? a) => (a?.Value?.Value?.Equals(value, StringComparison.OrdinalIgnoreCase)).GetValueOrDefault()); if (keyValuePair.HasValue) { return keyValuePair.Value.Key; } if (Enum.TryParse<T>(value, ignoreCase: true, out var result)) { return result; } return default(T); } } public class CamelCaseStringEnumConverter : JsonConverter<Enum> { public override void WriteJson(JsonWriter writer, Enum? value, JsonSerializer serializer) { if (value == null) { serializer.Serialize(writer, (object)null); } else { serializer.Serialize(writer, (object)value.ToCamelCase()); } } public override Enum ReadJson(JsonReader reader, Type objectType, Enum? existingValue, bool hasExistingValue, JsonSerializer serializer) { return ReadJToken(JToken.ReadFrom(reader), objectType); } public static Enum ReadJToken(JToken reader, Type objectType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 JTokenType type = reader.Type; JTokenType val = type; if ((int)val != 6) { if ((int)val == 8) { string text = Extensions.Value<string>((IEnumerable<JToken>)reader); if (text == null) { throw new SerializationException("The value was null."); } 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 Success(string key, object? value, string? message = null) { 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, null, 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (value == null) { serializer.Serialize(writer, (object)null); return; } JObject val = new JObject(); foreach (KeyValuePair<string, 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown JObject val = (JObject)serializer.Deserialize(reader); if (val == null) { return null; } Dictionary<string, 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, StandardErrors messageID) : this(id, status, 0L, messageID) { } public EffectResponse(uint id, EffectStatus status, string? message = null) : this(id, status, 0L, message) { } 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 = null) : this(id, status, checked((long)timeRemaining.TotalMilliseconds), message) { } 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 = null) { 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 Converter Instance = new Converter(); public override IEffectSourceDetails? ReadJson(JsonReader reader, Type objectType, IEffectSourceDetails? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)reader.TokenType == 11) { return null; } JObject val = JObject.Load(reader); JToken obj = val["type"]; string text = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null); if (1 == 0) { } IEffectSourceDetails result = text switch { "twitch-channel-reward" => ((JToken)val).ToObject<TwitchChannelRewardSourceDetails>(), "stream-labs-donation" => ((JToken)val).ToObject<StreamLabsDonationSourceDetails>(), "event-hype-train" => ((JToken)val).ToObject<HypeTrainSourceDetails>(), "tiktok-gift" => ((JToken)val).ToObject<TikTokGiftSourceDetails>(), "tiktok-like" => ((JToken)val).ToObject<TikTokLikeSourceDetails>(), "tiktok-follow" => ((JToken)val).ToObject<TikTokFollowSourceDetails>(), "tiktok-share" => ((JToken)val).ToObject<TikTokShareSourceDetails>(), "pulsoid-trigger" => ((JToken)val).ToObject<PulsoidTriggerSourceDetails>(), "crowd-control-test" => ((JToken)val).ToObject<CrowdControlTestSourceDetails>(), "crowd-control-chaos-mode" => ((JToken)val).ToObject<CrowdControlChaosModeSourceDetails>(), "crowd-control-retry" => ((JToken)val).ToObject<CrowdControlRetrySourceDetails>(), _ => null, }; if (1 == 0) { } return result; } public override void WriteJson(JsonWriter writer, IEffectSourceDetails? value, JsonSerializer serializer) { serializer.Serialize(writer, (object)((value == null) ? null : JObject.FromObject((object)value))); } } [JsonProperty("type")] string Type { get; } } 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 string 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 { public static string ToCamelCase(this Enum value) { return value.ToString("G").ToCamelCase(); } } [JsonConverter(typeof(CamelCaseStringEnumConverter))] public enum GameState { Unknown = 0, Ready = 1, Error = -1, Unmodded = -2, 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() { type = RequestType.GenericEvent; } } [Serializable] public class GenericEventResponse : SimpleJSONResponse { [JsonProperty(PropertyName = "internal")] public bool @internal; public string eventType; public Dictionary<string, object> data; public GenericEventResponse() { type = ResponseType.GenericEvent; } } internal class HexColorConverter : JsonConverter<ParameterColorValue> { private static readonly Dictionary<char, byte> CHAR_LOOKUP = new Dictionary<char, byte> { { '0', 0 }, { '1', 1 }, { '2', 2 }, { '3', 3 }, { '4', 4 }, { '5', 5 }, { '6', 6 }, { '7', 7 }, { '8', 8 }, { '9', 9 }, { 'A', 10 }, { 'B', 11 }, { 'C', 12 }, { 'D', 13 }, { 'E', 14 }, { 'F', 15 } }; public override void WriteJson(JsonWriter writer, ParameterColorValue value, JsonSerializer serializer) { serializer.Serialize(writer, (object)string.Format("#{0}{1:X2}{2:X2}{3:X2}", (value.A != byte.MaxValue) ? value.A.ToString("X2") : string.Empty, value.R, value.G, value.B)); } public override ParameterColorValue ReadJson(JsonReader reader, Type objectType, ParameterColorValue existingValue, bool hasExistingValue, JsonSerializer serializer) { string value = serializer.Deserialize<string>(reader); if (TryParse(value, out var color)) { return color; } throw new SerializationException("Unrecognized color code."); } public static bool TryParse(string value, out ParameterColorValue color) { if (value == null) { color = default(ParameterColorValue); return false; } value = value.TrimStart('#'); switch (value.Length) { case 6: { string[] array2 = Chop(value, 2); byte result2; byte red3 = (byte)(byte.TryParse(array2[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); byte green3 = (byte)(byte.TryParse(array2[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); byte blue3 = (byte)(byte.TryParse(array2[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0); color = ParameterColorValue.FromArgb(red3, green3, blue3); return true; } case 8: { string[] array = Chop(value, 2); byte result; byte alpha2 = (byte)(byte.TryParse(array[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte red2 = (byte)(byte.TryParse(array[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte green2 = (byte)(byte.TryParse(array[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); byte blue2 = (byte)(byte.TryParse(array[3], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0); color = ParameterColorValue.FromArgb(alpha2, red2, green2, blue2); return true; } case 3: { byte value3; byte red4 = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value3) ? checked((byte)(value3 * 16)) : 0); byte green4 = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value3) ? checked((byte)(value3 * 16)) : 0); byte blue4 = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value3) ? checked((byte)(value3 * 16)) : 0); color = ParameterColorValue.FromArgb(red4, green4, blue4); return true; } case 4: { byte value2; byte alpha = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value2) ? checked((byte)(value2 * 16)) : 0); byte red = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value2) ? checked((byte)(value2 * 16)) : 0); byte green = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value2) ? checked((byte)(value2 * 16)) : 0); byte blue = (byte)(CHAR_LOOKUP.TryGetValue(value[3], out value2) ? checked((byte)(value2 * 16)) : 0); color = ParameterColorValue.FromArgb(alpha, red, green, blue); return true; } default: color = default(ParameterColorValue); return false; } } private unsafe static string[] Chop(string value, int chopLength) { int length = value.Length; char* ptr = stackalloc char[chopLength]; string[] array = new string[length]; for (int i = 0; i < length; i = checked(i + chopLength)) { int j; for (j = 0; j < chopLength; j = checked(j + 1)) { int num = checked(i + j); if (num >= length) { break; } *(char*)((byte*)ptr + checked(unchecked((nint)j) * (nint)2)) = value[num]; } array[i / chopLength] = new string(ptr, 0, j); } return array; } } internal static class IEnumerableEx { public static Dictionary<K, V> ToDictionary<K, V>(this IEnumerable<KeyValuePair<K, V>> values) where K : notnull { Dictionary<K, V> dictionary = new Dictionary<K, V>(); foreach (KeyValuePair<K, V> value in values) { dictionary.Add(value.Key, value.Value); } return dictionary; } } [Serializable] public class LoginRequest : SimpleJSONRequest { public string? login; public string? password; } [Serializable] public class MessageRequest : SimpleJSONRequest { public string? message; } [Serializable] public class MessageResponse : SimpleJSONResponse { public string? message; } internal static class ObjectEx { public static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : class { return (value != null) ? selector(value) : null; } } public class ParameterColor : ParameterBase, IParameterValue { [JsonProperty(PropertyName = "value")] [JsonConverter(typeof(HexColorConverter))] public ParameterColorValue Value; [JsonIgnore] string IParameterValue.ID => ID; [JsonIgnore] string IParameterValue.Name => Name; [JsonIgnore] ParameterType IParameterValue.Type => Type; [JsonIgnore] object? IParameterValue.Value => Value; [JsonConstructor] public ParameterColor(string name, string id, ParameterColorValue value) : base(name, id, ParameterType.HexColor) { Value = value; } [JsonConstructor] public ParameterColor(string name, string id, string value) : base(name, id, ParameterType.HexColor) { if (!HexColorConverter.TryParse(value, out Value)) { throw new ArgumentException("Unknown color code.", "value"); } } } [Serializable] [DebuggerDisplay("{NameAndARGBValue}")] [TypeForwardedFrom("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public readonly struct ParameterColorValue : IEquatable<ParameterColorValue> { public static readonly ParameterColorValue Empty = default(ParameterColorValue); private const short StateARGBValueValid = 2; private const short StateValueMask = 2; private const short StateNameValid = 8; private const long NotDefinedValue = 0L; internal const int ARGBAlphaShift = 24; internal const int ARGBRedShift = 16; internal const int ARGBGreenShift = 8; internal const int ARGBBlueShift = 0; internal const uint ARGBAlphaMask = 4278190080u; internal const uint ARGBRedMask = 16711680u; internal const uint ARGBGreenMask = 65280u; internal const uint ARGBBlueMask = 255u; private readonly long value; private readonly short state; public byte R => (byte)(Value >> 16); public byte G => (byte)(Value >> 8); public byte B => (byte)Value; public byte A => (byte)(Value >> 24); public bool IsEmpty => state == 0; private long Value { get { if (((uint)state & 2u) != 0) { return value; } return 0L; } } private ParameterColorValue(long value, short state) { this.value = value; this.state = state; } private static ParameterColorValue FromArgb(uint argb) { return new ParameterColorValue(argb, 2); } public static ParameterColorValue FromArgb(int argb) { return FromArgb((uint)argb); } public static ParameterColorValue FromArgb(byte alpha, byte red, byte green, byte blue) { return FromArgb((uint)((alpha << 24) | (red << 16) | (green << 8) | blue)); } public static ParameterColorValue FromArgb(int alpha, ParameterColorValue baseColor) { return FromArgb(checked(((uint)alpha << 24) | ((uint)baseColor.Value & 0xFFFFFFu))); } public static ParameterColorValue FromArgb(byte red, byte green, byte blue) { return FromArgb(byte.MaxValue, red, green, blue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void GetRgbValues(out byte r, out byte g, out byte b) { checked { uint num = (uint)Value; r = (byte)((num & 0xFF0000) >> 16); g = (byte)((num & 0xFF00) >> 8); b = (byte)(num & 0xFFu); } } public float GetBrightness() { GetRgbValues(out var r, out var g, out var b); int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); return (float)checked(num2 + num) / 510f; } public float GetHue() { GetRgbValues(out var r, out var g, out var b); if (r == g && g == b) { return 0f; } int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); checked { float num3 = num2 - num; float num4 = ((r == num2) ? ((float)(g - b) / num3) : ((g != num2) ? ((float)(r - g) / num3 + 4f) : ((float)(b - r) / num3 + 2f))); num4 *= 60f; if (num4 < 0f) { num4 += 360f; } return num4; } } public float GetSaturation() { GetRgbValues(out var r, out var g, out var b); if (r == g && g == b) { return 0f; } int num = Math.Min(Math.Min(r, g), b); int num2 = Math.Max(Math.Max(r, g), b); checked { int num3 = num2 + num; if (num3 > 255) { num3 = 510 - num2 - num; } return (float)(num2 - num) / (float)num3; } } public int ToArgb() { return (int)Value; } public override string ToString() { if (((uint)state & 2u) != 0) { return "ParameterColorValue [A=" + A + ", R=" + R + ", G=" + G + ", B=" + B + "]"; } return "ParameterColorValue [Empty]"; } public static bool operator ==(ParameterColorValue left, ParameterColorValue right) { return left.value == right.value && left.state == right.state; } public static bool operator !=(ParameterColorValue left, ParameterColorValue right) { return !(left == right); } public override bool Equals(object? obj) { return obj is ParameterColorValue other && Equals(other); } public bool Equals(ParameterColorValue other) { return this == other; } public override int GetHashCode() { return (value.GetHashCode() * 397) ^ state.GetHashCode(); } } public class ParameterValue<T> : ParameterBase, IParameterValue { [JsonProperty(PropertyName = "value")] public T? Value; [JsonIgnore] string IParameterValue.ID => ID; [JsonIgnore] string IParameterValue.Name => Name; [JsonIgnore] ParameterType IParameterValue.Type => Type; [JsonIgnore] object? IParameterValue.Value => Value; [JsonConstructor] public ParameterValue(string name, string id, T? value) : base(name, id, ParameterType.Options) { Value = value; } public override string ToString() { return Name; } } [Serializable] public class PlayerInfo : SimpleJSONRequest { public JObject? player; public PlayerInfo() { type = RequestType.Start; } } [Serializable] [JsonConverter(typeof(Converter))] public class RequestParameters : IReadOnlyList<string>, IEnumerable<string>, IEnumerable, IReadOnlyCollection<string>, IReadOnlyDictionary<string, IParameterValue>, IEnumerable<KeyValuePair<string, IParameterValue>>, IReadOnlyCollection<KeyValuePair<string, IParameterValue>> { private class Converter : JsonConverter<RequestParameters> { public override void WriteJson(JsonWriter writer, RequestParameters? value, JsonSerializer serializer) { serializer.Serialize(writer, (object)value?._parameters); } public override RequestParameters? ReadJson(JsonReader reader, Type objectType, RequestParameters? existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); List<IParameterValue> list = new List<IParameterValue>(); foreach (KeyValuePair<string, JToken> item in val) { string key = item.Key; string name = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"name"]); switch (Extensions.Value<ParameterBase.ParameterType>((IEnumerable<JToken>)item.Value[(object)"type"])) { case ParameterBase.ParameterType.Options: { string value2 = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]); list.Add(new ParameterValue<string>(name, key, value2)); break; } case ParameterBase.ParameterType.HexColor: { string value = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]); if (HexColorConverter.TryParse(value, out var color)) { list.Add(new ParameterColor(name, key, color)); } break; } default: throw new SerializationException(); } } return new RequestParameters(list); } } private readonly Dictionary<string, IParameterValue> _parameters; private readonly List<string> _parameter_list; int IReadOnlyCollection<string>.Count => _parameters.Count; int IReadOnlyCollection<KeyValuePair<string, IParameterValue>>.Count => _parameters.Count; public string this[int index] => _parameter_list[index]; public IParameterValue this[string key] => _parameters[key]; public IEnumerable<string> Keys => _parameters.Keys; public IEnumerable<IParameterValue> Values => _parameters.Values; public int Count => _parameters.Count; private RequestParameters() { _parameters = new Dictionary<string, IParameterValue>(); _parameter_list = new List<string>(); } public RequestParameters(IEnumerable<IParameterValue> list) { list = list.ToArray(); _parameters = list.ToDictionary((IParameterValue d) => d.ID); _parameter_list = list.Select((IParameterValue v) => v.Value.ToString()).ToList(); } public RequestParameters(IEnumerable<KeyValuePair<string, IParameterValue>> parameters) { _parameters = parameters.ToDictionary(); _parameter_list = _parameters.Values.Select((IParameterValue p) => p.Value.ToString()).ToList(); } IEnumerator<KeyValuePair<string, IParameterValue>> IEnumerable<KeyValuePair<string, IParameterValue>>.GetEnumerator() { return _parameters.GetEnumerator(); } IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _parameters.Values.Select((IParameterValue v) => v.Value?.ToString()).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } public bool ContainsKey(string key) { return _parameters.ContainsKey(key); } public bool TryGetValue(string key, out IParameterValue value) { return _parameters.TryGetValue(key, out value); } public IEnumerable<string> Where(Func<string, bool> predicate) { return Enumerable.Where(this, predicate); } public IEnumerable<TResult> Select<TResult>(Func<string, TResult> selector) { return Enumerable.Select(this, selector); } public IEnumerable<TResult> SelectMany<TResult>(Func<string, IEnumerable<TResult>> selector) { return Enumerable.SelectMany(this, selector); } public IEnumerable<TResult> SelectMany<TResult>(Func<string, int, IEnumerable<TResult>> selector) { return Enumerable.SelectMany(this, selector); } public string First() { return this.First<string>(); } public string First(Func<string, bool> predicate) { return Enumerable.First(this, predicate); } public string? FirstOrDefault() { return this.FirstOrDefault<string>(); } public string FirstOrDefault(string defaultValue) { return this.FirstOrDefault<string>() ?? defaultValue; } public string? FirstOrDefault(Func<string, bool> predicate) { return Enumerable.FirstOrDefault(this, predicate); } public string FirstOrDefault(Func<string, bool> predicate, string defaultValue) { return Enumerable.FirstOrDefault(this, predicate) ?? defaultValue; } public bool Any() { return this.Any<string>(); } public bool Any(Func<string, bool> predicate) { return Enumerable.Any(this, predicate); } } public interface IParameterValue { string ID { get; } string Name { get; } ParameterBase.ParameterType Type { get; } object? Value { get; } } public abstract class ParameterBase { [JsonConverter(typeof(AnnotatedEnumConverter<ParameterType>))] public enum ParameterType { [AnnotatedEnumConverter<ParameterType>.JsonValue("options")] Options, [AnnotatedEnumConverter<ParameterType>.JsonValue("hex-color")] HexColor } [JsonIgnore] public readonly string ID; [JsonProperty(PropertyName = "title")] public readonly string Name; [JsonProperty(PropertyName = "type")] public readonly ParameterType Type; protected ParameterBase(string name, string id, ParameterType type) { ID = id; Name = name; Type = type; } } 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; } [Serializable] public class RpcResponse : SimpleJSONRequest { public object? value; public RpcResponse() { type = RequestType.RpcResponse; } } public abstract class SimpleJSONMessage { public static readonly JsonSerializerSettings JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, MissingMemberHandling = (MissingMemberHandling)0, Formatting = (Formatting)0 }; public static readonly JsonSerializer JSON_SERIALIZER = new JsonSerializer { NullValueHandling = JSON_SERIALIZER_SETTINGS.NullValueHandling, MissingMemberHandling = JSON_SERIALIZER_SETTINGS.MissingMemberHandling, Formatting = JSON_SERIALIZER_SETTINGS.Formatting }; private static int _next_id = 0; public static uint NextID { get { uint result; while ((result = (uint)Interlocked.Increment(ref _next_id)) == 0) { } return result; } } public abstract uint ID { get; } public abstract bool IsKeepAlive { get; } 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); RequestType requestType2 = requestType; RequestType requestType3 = requestType2; switch (requestType3) { case RequestType.Stop: if (requestType3 != 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); ResponseType responseType2 = responseType; ResponseType responseType3 = responseType2; switch (responseType3) { case ResponseType.EffectStatus: if (responseType3 != 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, AlreadyMaximum = 17153, AlreadyMinimum = 17154, EffectNotImplemented = 24576, PackResourceMissing = 24577, ConflictingEffectRunning = 32768, UnqueueablePending = 32769, EmulatorNotSupported = 28672, EmulatorInvalidSetting = 28673 } internal static class StringEx { public static string ToCamelCase(this string input) { bool flag = false; string text = ""; checked { for (int i = 0; i < input.Length; i++) { if (char.IsUpper(input[i])) { if (flag) { text += input.Substring(i); break; } text += char.ToLower(input[i]); } else { flag = true; text = ((i <= 1 || !char.IsUpper(input[i - 1]) || !char.IsUpper(input[i - 2])) ? (text + input[i]) : (text.Substring(0, text.Length - 1) + char.ToUpper(input[i - 1]) + input[i])); } } return text; } } } }
BepInEx/plugins/CrowdControl.dll
Decompiled 5 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.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.Logging; using BepinControl; using ConnectorLib.JSON; using CrowdControl; using CrowdControl.Delegates.Effects; using CrowdControl.Delegates.Metadata; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using UnityEngine; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: 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 BepinControl { public class RPCCommands { public class MessageHandler : MonoBehaviourPunCallbacks, IPunObservable { public class NetworkMessage { public string type; public int id; public int targetActor; public int senderID; public Dictionary<string, object> payload; public NetworkMessage(string type, int id = 0, int senderID = 0, int targetActor = 0, Dictionary<string, object> payload = null) { this.type = type; this.payload = payload ?? new Dictionary<string, object>(); this.id = id; this.senderID = senderID; this.targetActor = targetActor; } } private class RequestMessage { public string type { get; set; } public Dictionary<string, object> payload { get; set; } public int id { get; set; } public int senderID { get; set; } public int targetActor { get; set; } public bool random { get; set; } } private class ResponseMessage { public string type { get; set; } = "response"; public int id { get; set; } public int senderID { get; set; } public int targetActor { get; set; } public string status { get; set; } public string message { get; set; } public string version { get; set; } public Dictionary<string, object> payload { get; set; } } [CompilerGenerated] private sealed class <SendDelayedResponse>d__14 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int id; public int senderID; public bool success; public MessageHandler <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendDelayedResponse>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; SendResponse(id, senderID, (EffectStatus)((!success) ? 1 : 0)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static MessageHandler instance; public static PhotonView networkView; private static ConcurrentQueue<NetworkMessage> messageQueue = new ConcurrentQueue<NetworkMessage>(); public static void Initialize() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)instance != (Object)null) { return; } CrowdControlMod.Instance.Logger.LogInfo((object)"Initializing MessageHandler..."); GameObject val = new GameObject("MessageHandler"); instance = val.AddComponent<MessageHandler>(); networkView = val.AddComponent<PhotonView>(); if ((Object)(object)networkView != (Object)null) { networkView.ViewID = 6767; networkView.Synchronization = (ViewSynchronization)3; networkView.ObservedComponents = new List<Component> { (Component)(object)instance }; CrowdControlMod.Instance.Logger.LogInfo((object)$"MessageHandler initialized with PhotonView {networkView.ViewID}"); Object.DontDestroyOnLoad((Object)(object)val); lock (networkLock) { _isNetworkReady = null; _isViewValid = null; return; } } CrowdControlMod.Instance.Logger.LogError((object)"Failed to add PhotonView to MessageHandler"); CrowdControlMod.modActivated = false; } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)("Error in Initialize: " + ex.Message)); CrowdControlMod.Instance.Logger.LogError((object)("Stack trace: " + ex.StackTrace)); } } private void OnLevelWasLoaded(int level) { lock (networkLock) { _isNetworkReady = null; _isViewValid = null; } if ((Object)(object)networkView == (Object)null || !networkView.ViewID.Equals(6767)) { Initialize(); } } private void Update() { if (messageQueue.TryDequeue(out NetworkMessage result)) { SendQueuedMessage(result); } } private static void SendQueuedMessage(NetworkMessage message) { if (IsNetworkReady()) { try { string text = JsonConvert.SerializeObject((object)message); Player player = PhotonNetwork.CurrentRoom.GetPlayer(message.senderID, false); networkView.RPC("OnNetworkMessageRPC", (RpcTarget)0, new object[1] { text }); } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)("Failed to send message: " + ex.Message)); CrowdControlMod.Instance.Logger.LogError((object)("Stack trace: " + ex.StackTrace)); } } } public static void SendMessageToHost(string type, int id = 0, int senderID = 0, int targetActor = 0, Dictionary<string, object> payload = null) { try { if (!IsNetworkReady()) { return; } NetworkMessage item = new NetworkMessage(type, id, senderID, targetActor, payload); if (id > 0) { lock (pendingRequestIDs) { pendingRequestIDs.Add(id.ToString()); } } messageQueue.Enqueue(item); } catch (Exception arg) { CrowdControlMod.Instance.Logger.LogInfo((object)$"Failed to queue message: {arg}"); } } public override void OnEnable() { ((MonoBehaviourPunCallbacks)this).OnEnable(); } public override void OnJoinedRoom() { ((MonoBehaviourPunCallbacks)this).OnJoinedRoom(); lock (networkLock) { _isNetworkReady = null; _isViewValid = null; } CrowdControlMod.modActivated = false; if (PhotonNetwork.IsMasterClient) { CrowdControlMod.modActivated = true; } } [PunRPC] public void OnNetworkMessageRPC(string jsonMessage) { try { NetworkMessage networkMessage = JsonConvert.DeserializeObject<NetworkMessage>(jsonMessage); if (networkMessage == null) { CrowdControlMod.Instance.Logger.LogError((object)"Failed to deserialize message"); return; } if (networkMessage.type == "custom_event") { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HOST] Received custom event message from player {networkMessage.senderID}"); CrowdControlMod.Instance.Logger.LogInfo((object)("[HOST] Message payload: " + JsonConvert.SerializeObject((object)networkMessage.payload))); if (networkMessage.payload.TryGetValue("eventName", out object value)) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HOST] Event name: {value}"); } if (networkMessage.payload.TryGetValue("data", out object value2)) { CrowdControlMod.Instance.Logger.LogInfo((object)("[HOST] Event data: " + JsonConvert.SerializeObject(value2))); } } if (networkMessage.type == "response") { ProcessMessage(jsonMessage); } else if (networkMessage.type == "CC_CONNECT") { ModVersionCheck(networkMessage); } else if (networkMessage.type == "override_voice") { CrowdControlMod.Instance.Logger.LogInfo((object)"Voice override effect triggered (not implemented)"); } else { if (!PhotonNetwork.IsMasterClient) { return; } string type = networkMessage.type; string text = type; if (text == "custom_event") { if (networkMessage.payload.TryGetValue("eventName", out object value3) && networkMessage.payload.TryGetValue("data", out object value4)) { string text2 = value3.ToString(); JObject val = (JObject)((value4 is JObject) ? value4 : null); Dictionary<string, object> dictionary2 = ((val != null) ? ((JToken)val).ToObject<Dictionary<string, object>>() : ((!(value4 is Dictionary<string, object> dictionary)) ? new Dictionary<string, object>() : dictionary)); string requestId = networkMessage.id.ToString(); CrowdControlMod.Instance.Logger.LogInfo((object)("[HOST] Processing custom event '" + text2 + "' with data: " + JsonConvert.SerializeObject((object)dictionary2))); CustomEventSystem.Instance.OnCustomEventRequest(text2, dictionary2, requestId, networkMessage.senderID); } else { CrowdControlMod.Instance.Logger.LogError((object)("[HOST] Missing required fields in custom event message. Payload: " + JsonConvert.SerializeObject((object)networkMessage.payload))); } } else { CrowdControlMod.Instance.Logger.LogWarning((object)("Unknown message type: " + networkMessage.type)); } } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)("Failed to process message: " + ex.Message)); CrowdControlMod.Instance.Logger.LogError((object)("Stack trace: " + ex.StackTrace)); } } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { } public static void SendResponse(int id, int senderID, EffectStatus status, string message = "", Dictionary<string, object> payload = null) { try { int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; Dictionary<string, object> dictionary = new Dictionary<string, object> { { "status", ((object)(EffectStatus)(ref status)).ToString() }, { "message", message.ToString() }, { "cmd", "response" } }; if (payload != null && payload.ContainsKey("version") && payload["version"] != null) { dictionary["version"] = payload["version"].ToString(); } NetworkMessage networkMessage = new NetworkMessage("response", id, senderID, actorNumber, dictionary); string text = JsonConvert.SerializeObject((object)networkMessage); Player player = PhotonNetwork.CurrentRoom.GetPlayer(senderID, false); if (id == 0) { networkView.RPC("OnNetworkMessageRPC", (RpcTarget)0, new object[1] { text }); } else { networkView.RPC("OnNetworkMessageRPC", player, new object[1] { text }); } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogInfo((object)("SEND RESPONSE CRASHED " + ex)); } } [IteratorStateMachine(typeof(<SendDelayedResponse>d__14))] private IEnumerator SendDelayedResponse(int id, int senderID, bool success) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendDelayedResponse>d__14(0) { <>4__this = this, id = id, senderID = senderID, success = success }; } public static bool IsHost() { return PhotonNetwork.IsMasterClient; } public static void SendRequest(string type, int id, int senderID, int targetActor, Dictionary<string, object> payload) { try { RequestMessage requestMessage = new RequestMessage { type = type, id = id, senderID = senderID, targetActor = targetActor, payload = payload }; string text = JsonConvert.SerializeObject((object)requestMessage, jsonSettings); if ((Object)(object)networkView != (Object)null) { pendingRequestIDs.Add(id.ToString()); networkView.RPC("OnNetworkMessageRPC", (RpcTarget)2, new object[1] { text }); } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogInfo((object)("SEND REQUEST " + ex)); } } public static void SendResponse(int id, int senderID, EffectStatus status, Dictionary<string, object> payload) { try { ResponseMessage responseMessage = new ResponseMessage { id = id, senderID = senderID, status = ((object)(EffectStatus)(ref status)).ToString(), payload = payload }; string text = JsonConvert.SerializeObject((object)responseMessage, jsonSettings); if ((Object)(object)networkView != (Object)null) { Player player = PhotonNetwork.CurrentRoom.GetPlayer(senderID, false); if (id == 0) { networkView.RPC("OnNetworkMessageRPC", (RpcTarget)3, new object[1] { text }); } else { networkView.RPC("OnNetworkMessageRPC", player, new object[1] { text }); } } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogInfo((object)("SEND RESPONSE2 " + ex)); } } public static void AddResponder(int msgID, Action<EffectStatus> responder) { rspResponders[msgID] = responder; } public static void RemoveResponder(int msgID) { rspResponders.TryRemove(msgID, out Action<EffectStatus> _); } public static void ProcessMessage(string message) { try { if (string.IsNullOrEmpty(message)) { return; } JObject val = JObject.Parse(message); if (val == null) { CrowdControlMod.Instance.Logger.LogWarning((object)("Received malformed message: " + message)); return; } string text = ((object)val["type"])?.ToString(); if (text == "response") { ResponseMessage responseMessage = new ResponseMessage(); JToken obj = val["id"]; responseMessage.id = ((obj != null) ? Extensions.Value<int>((IEnumerable<JToken>)obj) : 0); JToken obj2 = val["senderID"]; responseMessage.senderID = ((obj2 != null) ? Extensions.Value<int>((IEnumerable<JToken>)obj2) : 0); JToken obj3 = val["targetActor"]; responseMessage.targetActor = ((obj3 != null) ? Extensions.Value<int>((IEnumerable<JToken>)obj3) : 0); JToken obj4 = val["payload"]; responseMessage.payload = ((obj4 != null) ? obj4.ToObject<Dictionary<string, object>>() : null) ?? new Dictionary<string, object>(); JToken obj5 = val["payload"]; responseMessage.status = ((obj5 == null) ? null : ((object)obj5[(object)"status"])?.ToString()); JToken obj6 = val["payload"]; responseMessage.version = ((obj6 == null) ? null : ((object)obj6[(object)"version"])?.ToString()); ResponseMessage responseMessage2 = responseMessage; if (responseMessage2.payload.TryGetValue("custom_event_response", out object _)) { if (responseMessage2.payload.TryGetValue("requestId", out object value2) && responseMessage2.payload.TryGetValue("message", out object value3) && responseMessage2.payload.TryGetValue("data", out object value4)) { string requestId = value2.ToString(); string message2 = value3.ToString(); Dictionary<string, object> data = (value4 as Dictionary<string, object>) ?? new Dictionary<string, object>(); bool success = responseMessage2.status == "Success"; CustomEventSystem.Instance.OnEventResponse(requestId, success, message2, data); } } else { ProcessResponse(responseMessage2); } return; } try { RequestMessage requestMessage = JsonConvert.DeserializeObject<RequestMessage>(message, jsonSettings); } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)("Error processing message2: " + ex.Message)); } } catch (Exception ex2) { CrowdControlMod.Instance.Logger.LogError((object)("Error processing message: " + ex2.Message)); CrowdControlMod.Instance.Logger.LogError((object)("Stack trace: " + ex2.StackTrace)); } } private static void ProcessResponse(ResponseMessage message) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (message.senderID != PhotonNetwork.LocalPlayer.ActorNumber) { return; } if (message.id == 0 && message.version == "1.0.7.0") { CrowdControlMod.modActivated = true; } if (!rspResponders.TryGetValue(message.id, out Action<EffectStatus> value) || !pendingRequestIDs.Remove(message.id.ToString()) || !Enum.TryParse<EffectStatus>(message.status, out EffectStatus result)) { return; } try { value(result); } catch (Exception arg) { CrowdControlMod.Instance.Logger.LogInfo((object)$"Error processing response for message ID {message.id}: {arg}"); } } public static async Task ModVersionCheck(NetworkMessage message) { Convert.ToString(message.payload["version"]); _ = message.senderID; } } internal static HashSet<string> pendingRequestIDs = new HashSet<string>(); private static readonly ConcurrentDictionary<int, Action<EffectStatus>> rspResponders = new ConcurrentDictionary<int, Action<EffectStatus>>(); private static readonly JsonSerializerSettings jsonSettings = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; private static readonly object networkLock = new object(); private static bool? _isNetworkReady = null; private static bool? _isViewValid = null; private static readonly Dictionary<string, string> PlayerVersions = new Dictionary<string, string>(); private static bool IsViewValid() { lock (networkLock) { if (_isViewValid.HasValue) { return _isViewValid.Value; } PhotonView networkView = MessageHandler.networkView; if ((Object)(object)networkView == (Object)null) { _isViewValid = false; CrowdControlMod.Instance.Logger.LogWarning((object)"NetworkView is null"); return false; } _isViewValid = networkView.ViewID != 0; return _isViewValid.Value; } } private static bool IsNetworkReady() { lock (networkLock) { if (_isNetworkReady.HasValue) { return _isNetworkReady.Value; } bool flag = IsViewValid(); _isNetworkReady = PhotonNetwork.IsConnected && PhotonNetwork.InRoom && flag && MessageHandler.networkView.ObservedComponents != null; return _isNetworkReady.Value; } } } } namespace CrowdControl { [BepInPlugin("WarpWorld.CrowdControl", "Crowd Control", "1.0.7.0")] public class CrowdControlMod : BaseUnityPlugin { public const string MOD_GUID = "WarpWorld.CrowdControl"; public const string MOD_NAME = "Crowd Control"; public const string MOD_VERSION = "1.0.7.0"; private readonly Harmony harmony = new Harmony("WarpWorld.CrowdControl"); internal static bool modActivated; private const float GAME_STATUS_UPDATE_INTERVAL = 1f; private float m_gameStatusUpdateTimer; public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; internal static CrowdControlMod Instance { get; private set; } public GameStateManager GameStateManager { get; private set; } = null; public EffectLoader EffectLoader { get; private set; } = null; public bool ClientConnected => Client.Connected; public NetworkClient Client { get; private set; } public Scheduler Scheduler { get; private set; } private void Awake() { Instance = this; Logger.LogInfo((object)"Loaded WarpWorld.CrowdControl. Patching."); harmony.PatchAll(); 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); _ = CustomEventSystem.Instance; RPCCommands.MessageHandler.Initialize(); } catch (Exception arg) { Logger.LogError((object)$"Crowd Control Init Error: {arg}"); } Logger.LogInfo((object)"Crowd Control Initialized"); } private void FixedUpdate() { m_gameStatusUpdateTimer += Time.fixedDeltaTime; if (m_gameStatusUpdateTimer >= 1f) { GameStateManager.UpdateGameState(); m_gameStatusUpdateTimer = 0f; } Scheduler?.Tick(); } } public class CustomEventSystem : MonoBehaviourPunCallbacks { public static bool EnableDebugLogging; private static CustomEventSystem _instance; private readonly ConcurrentDictionary<string, CustomEventHandler> _registeredEvents = new ConcurrentDictionary<string, CustomEventHandler>(); private readonly ConcurrentQueue<EventRequest> _pendingRequests = new ConcurrentQueue<EventRequest>(); private readonly ConcurrentDictionary<string, Action<EventResponse>> _responseCallbacks = new ConcurrentDictionary<string, Action<EventResponse>>(); public static CustomEventSystem Instance { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("CustomEventSystem"); _instance = val.AddComponent<CustomEventSystem>(); Object.DontDestroyOnLoad((Object)(object)val); } return _instance; } } private void Awake() { if ((Object)(object)_instance == (Object)null) { _instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } else if ((Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void Update() { EventRequest result; while (_pendingRequests.TryDequeue(out result)) { ProcessEventRequest(result); } } public bool RegisterEvent(string eventName, CustomEventHandler handler) { if (!PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)("Cannot register event '" + eventName + "' - not the host")); } return false; } if (_registeredEvents.TryAdd(eventName, handler)) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("Registered custom event: " + eventName)); } return true; } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)("Event '" + eventName + "' is already registered")); } return false; } public bool UnregisterEvent(string eventName) { if (!PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)("Cannot unregister event '" + eventName + "' - not the host")); } return false; } if (_registeredEvents.TryRemove(eventName, out CustomEventHandler _)) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("Unregistered custom event: " + eventName)); } return true; } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)("Event '" + eventName + "' was not registered")); } return false; } public bool TriggerEvent(string eventName, Dictionary<string, object> data = null, Action<EventResponse> callback = null) { if (PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)("Cannot trigger event '" + eventName + "' - you are the host")); } return false; } int id = Random.Range(1000000, 9999999); string text = id.ToString(); EventRequest eventRequest = new EventRequest { Id = text, EventName = eventName, Data = (data ?? new Dictionary<string, object>()), SenderId = PhotonNetwork.LocalPlayer.ActorNumber }; if (callback != null) { _responseCallbacks[text] = callback; } Dictionary<string, object> dictionary = new Dictionary<string, object> { ["eventName"] = eventName, ["data"] = data ?? new Dictionary<string, object>() }; if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Sending event '" + eventName + "' to host with payload: " + JsonConvert.SerializeObject((object)dictionary))); } RPCCommands.MessageHandler.SendMessageToHost("custom_event", id, PhotonNetwork.LocalPlayer.ActorNumber, 0, dictionary); if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("Triggered custom event: " + eventName)); } return true; } private void ProcessEventRequest(EventRequest request) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Processing event request: " + request.EventName)); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Request data: " + JsonConvert.SerializeObject((object)request.Data))); } if (!PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogWarning((object)"Received event request but not the host"); } return; } if (!_registeredEvents.TryGetValue(request.EventName, out CustomEventHandler value)) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("[CustomEventSystem] Event '" + request.EventName + "' not found in registered events")); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Available events: " + string.Join(", ", _registeredEvents.Keys))); } SendEventResponse(request.Id, request.SenderId, success: false, "Event '" + request.EventName + "' not found"); return; } try { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Executing handler for event: " + request.EventName)); } EventResult eventResult = value(request.Data); if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[CustomEventSystem] Handler result: Success={eventResult.Success}, Message={eventResult.Message}"); } SendEventResponse(request.Id, request.SenderId, eventResult.Success, eventResult.Message, eventResult.Data); } catch (Exception ex) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("[CustomEventSystem] Error processing event '" + request.EventName + "': " + ex.Message)); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("[CustomEventSystem] Stack trace: " + ex.StackTrace)); } SendEventResponse(request.Id, request.SenderId, success: false, "Error: " + ex.Message); } } private void SendEventResponse(string requestId, int senderId, bool success, string message = "", Dictionary<string, object> data = null) { Dictionary<string, object> payload = new Dictionary<string, object> { ["custom_event_response"] = true, ["requestId"] = requestId, ["message"] = message, ["data"] = data ?? new Dictionary<string, object>() }; RPCCommands.MessageHandler.SendResponse(int.Parse(requestId), senderId, (EffectStatus)((!success) ? 1 : 0), payload); } public void OnEventResponse(string requestId, bool success, string message, Dictionary<string, object> data) { if (_responseCallbacks.TryRemove(requestId, out Action<EventResponse> callback)) { EventResponse response = new EventResponse { Success = success, Message = message, Data = (data ?? new Dictionary<string, object>()) }; UnityMainThreadDispatcher.Instance.Enqueue(delegate { callback?.Invoke(response); }); } } public void OnCustomEventRequest(string eventName, Dictionary<string, object> data, string requestId, int senderId) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Received event request: " + eventName)); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Request ID: " + requestId)); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[CustomEventSystem] Sender ID: {senderId}"); } if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[CustomEventSystem] Data: " + JsonConvert.SerializeObject((object)data))); } EventRequest item = new EventRequest { Id = requestId, EventName = eventName, Data = (data ?? new Dictionary<string, object>()), SenderId = senderId }; _pendingRequests.Enqueue(item); if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)"[CustomEventSystem] Queued event request for processing"); } } public List<string> GetRegisteredEvents() { return new List<string>(_registeredEvents.Keys); } public void ClearAllEvents() { _registeredEvents.Clear(); if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)"Cleared all registered custom events"); } } public override void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)"Became host - ready to register custom events"); } HostEventHandlers.RegisterAllHandlers(); } else { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)"No longer host - clearing registered events"); } ClearAllEvents(); } } public override void OnJoinedRoom() { if (PhotonNetwork.IsMasterClient) { if (EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)"Joined room as host - ready to register custom events"); } HostEventHandlers.RegisterAllHandlers(); } } } public delegate EventResult CustomEventHandler(Dictionary<string, object> data); public class EventRequest { public string Id { get; set; } public string EventName { get; set; } public Dictionary<string, object> Data { get; set; } public int SenderId { get; set; } } public class EventResult { public bool Success { get; set; } public string Message { get; set; } public Dictionary<string, object> Data { get; set; } public static EventResult SuccessResult(string message = "", Dictionary<string, object> data = null) { return new EventResult { Success = true, Message = message, Data = (data ?? new Dictionary<string, object>()) }; } public static EventResult FailureResult(string message = "", Dictionary<string, object> data = null) { return new EventResult { Success = false, Message = message, Data = (data ?? new Dictionary<string, object>()) }; } } public class EventResponse { public bool Success { get; set; } public string Message { get; set; } public Dictionary<string, object> Data { get; set; } } public class UnityMainThreadDispatcher : MonoBehaviour { private static UnityMainThreadDispatcher _instance; private readonly Queue<Action> _executionQueue = new Queue<Action>(); public static UnityMainThreadDispatcher Instance { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("UnityMainThreadDispatcher"); _instance = val.AddComponent<UnityMainThreadDispatcher>(); Object.DontDestroyOnLoad((Object)(object)val); } return _instance; } } public void Enqueue(Action action) { lock (_executionQueue) { _executionQueue.Enqueue(action); } } private void Update() { lock (_executionQueue) { while (_executionQueue.Count > 0) { _executionQueue.Dequeue()(); } } } } public class DelimitedStreamReader : IDisposable { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] 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] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private CrowdControlMod <mod>P; public static bool? isHostLastStatus; private GameState? _last_game_state; public GameStateManager(CrowdControlMod mod) { <mod>P = mod; base..ctor(); } public static async Task DialogMsgAsync(string message, bool playSound) { } public static void updateEffects() { bool isMasterClient = PhotonNetwork.IsMasterClient; if (!isHostLastStatus.HasValue || isHostLastStatus != isMasterClient) { isHostLastStatus = isMasterClient; string[] codes = new string[16] { "spawn_item_rope", "spawn_item_marshmallow", "spawn_item_appleberryred", "spawn_item_appleberryyellow", "spawn_item_appleberrygreen", "spawn_item_bandage", "spawn_item_ropecannon", "spawn_item_backpack", "spawn_item_bugle", "spawn_item_flare", "spawn_item_book", "spawn_item_toy", "spawn_item_energydrink", "spawn_item_compass", "spawn_item_piratecompass", "spawn_item_warpcompass" }; if (isMasterClient) { CrowdControlMod.Instance.Client.ShowEffects(codes); } else { CrowdControlMod.Instance.Client.ShowEffects(codes); } } } public bool IsReady(string code = "") { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 return (int)GetGameState() == 1; } public GameState GetGameState() { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0159: 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_002d: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) try { if (LoadingScreenHandler.loading) { return (GameState)(-6); } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return (GameState)(-12); } CharacterAfflictions component = ((Component)localCharacter).GetComponent<CharacterAfflictions>(); if ((Object)(object)component == (Object)null) { return (GameState)(-13); } FieldInfo field = typeof(CharacterAfflictions).GetField("m_inAirport", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { return (GameState)(-13); } if ((bool)field.GetValue(component)) { return (GameState)(-13); } GUIManager val = Object.FindObjectOfType<GUIManager>(); if (!Object.op_Implicit((Object)(object)val)) { return (GameState)(-13); } if ((Object)(object)val != (Object)null && (Object)(object)val.pauseMenu != (Object)null && val.pauseMenu.isOpen) { return (GameState)(-7); } if ((Object)(object)Singleton<RunManager>.Instance != (Object)null) { if ((double)Singleton<RunManager>.Instance.timeSinceRunStarted <= 8.0) { return (GameState)(-6); } return (GameState)1; } return (GameState)(-6); } catch (Exception arg) { CrowdControlMod.Instance.Logger.LogError((object)$"ERROR {arg}"); return (GameState)(-1); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool UpdateGameState(bool force = false) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return UpdateGameState(GetGameState(), force); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool UpdateGameState(GameState newState, bool force) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return UpdateGameState(newState, null, force); } public bool UpdateGameState(GameState newState, string? message = null, bool force = false) { //IL_000b: 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_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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (force || _last_game_state != (GameState?)newState) { _last_game_state = newState; return <mod>P.Client.Send((SimpleJSONResponse?)new GameUpdate(newState, message)); } return true; } } public static class HostEventHandlers { public static void RegisterAllHandlers() { if (!PhotonNetwork.IsMasterClient) { CrowdControlMod.Instance.Logger.LogWarning((object)"Cannot register host handlers - not the host"); return; } CustomEventSystem.Instance.RegisterEvent("spawn_item", HandleSpawnItem); CustomEventSystem.Instance.RegisterEvent("custom_effect", HandleCustomEffect); CrowdControlMod.Instance.Logger.LogInfo((object)"Registered all host event handlers"); } public static void UnregisterAllHandlers() { if (PhotonNetwork.IsMasterClient) { CustomEventSystem.Instance.UnregisterEvent("spawn_item"); CustomEventSystem.Instance.UnregisterEvent("custom_effect"); CrowdControlMod.Instance.Logger.LogInfo((object)"Unregistered all host event handlers"); } } private static EventResult HandleSpawnItem(Dictionary<string, object> data) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[HostEventHandlers] HandleSpawnItem called with data: " + JsonConvert.SerializeObject((object)data))); } try { if (!data.TryGetValue("prefabPath", out object value)) { if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("[HostEventHandlers] Missing prefabPath parameter. Available keys: " + string.Join(", ", data.Keys))); } return EventResult.FailureResult("Missing prefabPath parameter"); } string text = value.ToString(); if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)("[HostEventHandlers] Prefab path: " + text)); } Vector3 val = Vector3.zero; if (data.TryGetValue("spawnPosition", out object value2)) { Dictionary<string, object> dictionary = null; JObject val2 = (JObject)((value2 is JObject) ? value2 : null); if (val2 != null) { dictionary = ((JToken)val2).ToObject<Dictionary<string, object>>(); } else if (value2 is Dictionary<string, object> dictionary2) { dictionary = dictionary2; } if (dictionary != null && dictionary.TryGetValue("x", out var value3) && dictionary.TryGetValue("y", out var value4) && dictionary.TryGetValue("z", out var value5)) { ((Vector3)(ref val))..ctor(Convert.ToSingle(value3), Convert.ToSingle(value4), Convert.ToSingle(value5)); if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HostEventHandlers] Using provided spawn position: {val}"); } } else if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)"[HostEventHandlers] spawnPosition present but could not parse x/y/z."); } } else { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter != (Object)null) { val = ((Component)localCharacter).transform.position + ((Component)localCharacter).transform.forward * 1.5f + Vector3.up; if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HostEventHandlers] Using default spawn position: {val}"); } } else { val = Vector3.up * 2f; if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HostEventHandlers] Using fallback spawn position: {val}"); } } } if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"[HostEventHandlers] Attempting to spawn item '{text}' at {val}"); } GameObject val3 = ((!text.Contains("Character_")) ? PhotonNetwork.InstantiateItemRoom(text, val, Quaternion.identity) : PhotonNetwork.InstantiateRoomObject(text, val, Quaternion.identity, (byte)0, (object[])null)); if ((Object)(object)val3 == (Object)null) { if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("[HostEventHandlers] Failed to instantiate item: " + text)); } return EventResult.FailureResult("Failed to instantiate item: " + text); } if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogInfo((object)$"Host spawned item '{text}' at {val} for client"); } return EventResult.SuccessResult("Successfully spawned " + text, new Dictionary<string, object> { ["spawnedItem"] = text, ["position"] = val }); } catch (Exception ex) { if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("Error in HandleSpawnItem: " + ex.Message)); } if (CustomEventSystem.EnableDebugLogging) { CrowdControlMod.Instance.Logger.LogError((object)("Stack trace: " + ex.StackTrace)); } return EventResult.FailureResult("Error: " + ex.Message); } } private static EventResult HandleCustomEffect(Dictionary<string, object> data) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) try { if (!data.TryGetValue("effectType", out object value)) { return EventResult.FailureResult("Missing effectType parameter"); } string text = value.ToString(); string text2 = text.ToLower(); string text3 = text2; if (!(text3 == "explosion")) { if (text3 == "weather") { if (data.TryGetValue("weatherType", out object value2)) { string text4 = value2.ToString(); CrowdControlMod.Instance.Logger.LogInfo((object)("Host changed weather to " + text4)); return EventResult.SuccessResult("Weather changed to " + text4); } return EventResult.FailureResult("Missing weatherType parameter"); } return EventResult.FailureResult("Unknown effect type: " + text); } Vector3 zero = Vector3.zero; if (data.TryGetValue("position", out object value3) && value3 is Dictionary<string, object> dictionary) { ((Vector3)(ref zero))..ctor(float.Parse(dictionary["x"].ToString()), float.Parse(dictionary["y"].ToString()), float.Parse(dictionary["z"].ToString())); } CrowdControlMod.Instance.Logger.LogInfo((object)$"Host created explosion effect at {zero}"); return EventResult.SuccessResult("Explosion effect created"); } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)("Error in HandleCustomEffect: " + ex.Message)); return EventResult.FailureResult("Error: " + ex.Message); } } } public class NetworkClient : IDisposable { public static readonly string CV_HOST = "127.0.0.1"; public static readonly int CV_PORT = 51337; private TcpClient? m_client; private DelimitedStreamReader? m_streamReader; private readonly CrowdControlMod m_mod; private readonly CancellationTokenSource m_quitting = new CancellationTokenSource(); private readonly Thread m_readLoop; private readonly Thread m_maintenanceLoop; private static readonly EmptyResponse KEEPALIVE = new EmptyResponse { type = (ResponseType)255 }; public bool Connected => m_client?.Connected ?? false; ~NetworkClient() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { try { m_client?.Dispose(); } catch { } try { m_quitting.Cancel(); } catch { } GC.SuppressFinalize(this); } public NetworkClient(CrowdControlMod mod) { m_mod = mod; (m_readLoop = new Thread(NetworkLoop)).Start(); (m_maintenanceLoop = new Thread(MaintenanceLoop)).Start(); } private void NetworkLoop() { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; while (!m_quitting.IsCancellationRequested) { CrowdControlMod.Instance.Logger.LogInfo((object)"Attempting to connect to Crowd Control"); try { m_client = new TcpClient(); m_client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, optionValue: true); m_client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true); if (m_client.BeginConnect(CV_HOST, CV_PORT, null, null).AsyncWaitHandle.WaitOne(2000, exitContext: true) && m_client.Connected) { ClientLoop(); } else { CrowdControlMod.Instance.Logger.LogInfo((object)"Failed to connect to Crowd Control"); } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)ex); CrowdControlMod.Instance.Logger.LogError((object)"Failed to connect to Crowd Control"); } finally { try { m_client?.Close(); } catch { } } Thread.Sleep(2000); } } private void MaintenanceLoop() { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; while (!m_quitting.IsCancellationRequested) { try { TcpClient? client = m_client; if (client != null && client.Connected) { KeepAlive(); } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)ex); } Thread.Sleep(2000); } } private void ClientLoop() { m_streamReader = new DelimitedStreamReader(m_client.GetStream()); CrowdControlMod.Instance.Logger.LogInfo((object)"Connected to Crowd Control"); try { while (!m_quitting.IsCancellationRequested) { string text = m_streamReader.ReadUntilNullTerminator(); OnMessage(text.Trim()); } } catch (EndOfStreamException) { CrowdControlMod.Instance.Logger.LogInfo((object)"Disconnected from Crowd Control"); m_client?.Close(); } catch (Exception ex2) { CrowdControlMod.Instance.Logger.LogError((object)ex2); m_client?.Close(); } } private void OnMessage(string message) { if (string.IsNullOrWhiteSpace(message)) { return; } try { SimpleJSONRequest request = default(SimpleJSONRequest); if (SimpleJSONRequest.TryParse(message, ref request)) { m_mod.Scheduler.ProcessRequest(request); } } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)ex); } } public bool Send(SimpleJSONResponse? response) { try { if (response == null) { return false; } if (!Connected) { return false; } byte[] bytes = Encoding.UTF8.GetBytes(((SimpleJSONMessage)response).Serialize()); int num = 0; byte[] array = new byte[1 + bytes.Length]; ReadOnlySpan<byte> readOnlySpan = new ReadOnlySpan<byte>(bytes); readOnlySpan.CopyTo(new Span<byte>(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array[num] = 0; byte[] array2 = array; m_client.GetStream().Write(array2, 0, array2.Length); return true; } catch (Exception arg) { CrowdControlMod.Instance.Logger.LogError((object)$"Error sending a message to the Crowd Control client: {arg}"); return false; } } public Task<bool> SendAsync(SimpleJSONResponse? response) { SimpleJSONResponse response2 = response; return Task.Run(() => Send(response2)); } public void Stop(string? message = null) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (message != null) { Send((SimpleJSONResponse?)new MessageResponse { type = (ResponseType)254, message = message }); } m_client?.Close(); } public Task StopAsync(string? message = null) { string message2 = message; return Task.Run(delegate { Stop(message2); }); } public bool KeepAlive() { return Send((SimpleJSONResponse?)(object)KEEPALIVE); } public Task<bool> KeepAliveAsync() { return Task.Run((Func<bool>)KeepAlive); } public void AttachMetadata(EffectResponse response) { response.metadata = new Dictionary<string, DataResponse>(); string[] commonMetadata = MetadataDelegates.CommonMetadata; foreach (string text in commonMetadata) { if (MetadataLoader.Metadata.TryGetValue(text, out MetadataDelegate value)) { response.metadata.Add(text, value(m_mod)); } else { CrowdControlMod.Instance.Logger.LogError((object)("Metadata delegate \"" + text + "\" could not be found. Available delegates: " + string.Join(", ", MetadataLoader.Metadata.Keys))); } } } public bool ShowEffects(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)128, (string)null)); } public bool ShowEffects([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)128, (string)null)); } public Task<bool> ShowEffectsAsync(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)128, (string)null)); } public Task<bool> ShowEffectsAsync([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)128, (string)null)); } public bool ShowAllEffects() { return ShowEffects(m_mod.EffectLoader.Effects.Keys); } public Task<bool> ShowAllEffectsAsync() { return ShowEffectsAsync(m_mod.EffectLoader.Effects.Keys); } public bool HideEffects(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)129, (string)null)); } public bool HideEffects([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)129, (string)null)); } public Task<bool> HideEffectsAsync(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)129, (string)null)); } public Task<bool> HideEffectsAsync([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)129, (string)null)); } public bool HideAllEffects() { return HideEffects(m_mod.EffectLoader.Effects.Keys); } public Task<bool> HideAllEffectsAsync() { return HideEffectsAsync(m_mod.EffectLoader.Effects.Keys); } public bool EnableEffects(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)130, (string)null)); } public bool EnableEffects([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)130, (string)null)); } public Task<bool> EnableEffectsAsync(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)130, (string)null)); } public Task<bool> EnableEffectsAsync([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)130, (string)null)); } public bool EnableAllEffects() { return ShowEffects(m_mod.EffectLoader.Effects.Keys); } public Task<bool> EnableAllEffectsAsync() { return ShowEffectsAsync(m_mod.EffectLoader.Effects.Keys); } public bool DisableEffects(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)131, (string)null)); } public bool DisableEffects([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return Send((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)131, (string)null)); } public Task<bool> DisableEffectsAsync(params string[] codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)131, (string)null)); } public Task<bool> DisableEffectsAsync([ParamCollection] IEnumerable<string> codes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return SendAsync((SimpleJSONResponse?)new EffectUpdate(codes, (EffectStatus)131, (string)null)); } public bool DisableAllEffects() { return ShowEffects(m_mod.EffectLoader.Effects.Keys); } public Task<bool> DisableAllEffectsAsync() { return ShowEffectsAsync(m_mod.EffectLoader.Effects.Keys); } } internal static class ReflectionEx { private const BindingFlags BINDING_FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static void SetField(this object obj, string prop, object val) { FieldInfo field = obj.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); field.SetValue(obj, val); } public static T GetField<T>(this object obj, string prop) { FieldInfo field = obj.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return (T)field.GetValue(obj); } public static void SetProperty(this object obj, string prop, object val) { FieldInfo field = obj.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); field.SetValue(obj, val); } public static T GetProperty<T>(this object obj, string prop) { FieldInfo field = obj.GetType().GetField(prop, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return (T)field.GetValue(obj); } public static void CallMethod(this object obj, string methodName, params object[] vals) { MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); method.Invoke(obj, vals); } public static T CallMethod<T>(this object obj, string methodName, params object[] vals) { MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return (T)method.Invoke(obj, vals); } } public class Scheduler { private class RequestState { private IEnumerator? m_enumerator; public EffectRequest Request { get; } public Effect Effect { get; } public TimedEffectState? TimedEffectState { get; } public bool MoveNext() { if (m_enumerator != null) { if (m_enumerator.MoveNext()) { return true; } (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; } switch (TimedEffectState?.State) { case CrowdControl.Delegates.Effects.TimedEffectState.EffectState.NotStarted: if (m_enumerator == null) { m_enumerator = TimedEffectState.Start(); } break; case CrowdControl.Delegates.Effects.TimedEffectState.EffectState.Running: if (m_enumerator == null) { m_enumerator = TimedEffectState.Tick(); } break; case CrowdControl.Delegates.Effects.TimedEffectState.EffectState.Finished: return false; } return m_enumerator?.MoveNext() ?? false; } public void Pause() { (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if (valueOrDefault == CrowdControl.Delegates.Effects.TimedEffectState.EffectState.Running) { m_enumerator = TimedEffectState.Pause(); } } } public void Resume() { (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if (valueOrDefault == CrowdControl.Delegates.Effects.TimedEffectState.EffectState.Paused) { m_enumerator = TimedEffectState.Resume(); } } } public void Stop() { (m_enumerator as IDisposable)?.Dispose(); m_enumerator = null; TimedEffectState.EffectState? effectState = TimedEffectState?.State; TimedEffectState.EffectState? effectState2 = effectState; if (effectState2.HasValue) { TimedEffectState.EffectState valueOrDefault = effectState2.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 1u) { m_enumerator = TimedEffectState.Stop(); } } } public RequestState(EffectRequest request, Effect effect) { Request = request; Effect = effect; if (Effect.IsTimed) { TimedEffectState = new TimedEffectState(effect, request, SITimeSpan.FromMilliseconds(request.duration.GetValueOrDefault())); } } } private CrowdControlMod m_mod; private NetworkClient m_networkClient; private readonly ConcurrentQueue<RequestState> m_requestQueue; private readonly ConcurrentDictionary<uint, RequestState> m_runningEffects; public Scheduler(CrowdControlMod mod, NetworkClient networkClient) { m_mod = mod; m_networkClient = networkClient; m_requestQueue = new ConcurrentQueue<RequestState>(); m_runningEffects = new ConcurrentDictionary<uint, RequestState>(); base..ctor(); } public bool IsRunning(string id) { foreach (TimedEffectState item in m_requestQueue.Select((RequestState p) => p.TimedEffectState).OfType<TimedEffectState>()) { if (item.Effect.EffectAttribute.IDs.Contains(id)) { return true; } } return false; } public void ProcessRequest(SimpleJSONRequest? request) { //IL_0011: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected I4, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown RequestType? val = request?.type; RequestType? val2 = val; if (!val2.HasValue) { return; } RequestType valueOrDefault = val2.GetValueOrDefault(); switch ((int)valueOrDefault) { default: if ((int)valueOrDefault == 253) { m_mod.GameStateManager.UpdateGameState(force: true); } break; case 0: { EffectRequest val6 = (EffectRequest)(object)((request is EffectRequest) ? request : null); if (val6 != null) { EffectRequest val5 = val6; if (val5.code == null) { val5.code = string.Empty; } if (!m_mod.EffectLoader.Effects.ContainsKey(val6.code)) { m_networkClient.Send((SimpleJSONResponse?)new EffectResponse(((SimpleJSONRequest)val6).id, (EffectStatus)2, (StandardErrors)4097)); CrowdControlMod.Instance.Logger.LogError((object)(StandardErrors)4097); } else { m_networkClient.Send((SimpleJSONResponse?)new EffectResponse(((SimpleJSONRequest)val6).id, (EffectStatus)((!m_mod.GameStateManager.IsReady(val6.code)) ? 1 : 0), (string)null)); } } break; } case 1: { EffectRequest val4 = (EffectRequest)(object)((request is EffectRequest) ? request : null); if (val4 != null) { EffectRequest val5 = val4; if (val5.code == null) { val5.code = string.Empty; } if (!m_mod.EffectLoader.Effects.TryGetValue(val4.code, out Effect value2)) { m_networkClient.Send((SimpleJSONResponse?)new EffectResponse(((SimpleJSONRequest)val4).id, (EffectStatus)2, (StandardErrors)4097)); CrowdControlMod.Instance.Logger.LogError((object)(StandardErrors)4097); } else { m_requestQueue.Enqueue(new RequestState(val4, value2)); } } break; } case 2: { EffectRequest val3 = (EffectRequest)(object)((request is EffectRequest) ? request : null); if (val3 != null) { if (!m_runningEffects.TryGetValue(((SimpleJSONRequest)val3).id, out RequestState value)) { m_networkClient.Send((SimpleJSONResponse?)new EffectResponse(((SimpleJSONRequest)val3).id, (EffectStatus)1, (StandardErrors)16899)); CrowdControlMod.Instance.Logger.LogError((object)(StandardErrors)16899); } else { value.Stop(); } } break; } } } public void Enqueue(EffectRequest request, Effect effect) { m_requestQueue.Enqueue(new RequestState(request, effect)); } public void PauseAll() { foreach (KeyValuePair<uint, RequestState> runningEffect in m_runningEffects) { runningEffect.Value.Pause(); } } public void ResumeAll() { foreach (KeyValuePair<uint, RequestState> runningEffect in m_runningEffects) { runningEffect.Value.Resume(); } } public void Tick() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown RequestState result; while (m_requestQueue.TryDequeue(out result)) { if (!m_mod.GameStateManager.IsReady(result.Request.code)) { m_networkClient.SendAsync((SimpleJSONResponse?)new EffectResponse(((SimpleJSONRequest)result.Request).id, (EffectStatus)3, (string)null)).Forget(); continue; } if (result.TimedEffectState != null) { m_runningEffects.TryAdd(((SimpleJSONRequest)result.Request).id, result); continue; } EffectResponse response; try { response = result.Effect.Start(result.Request); } catch (Exception ex) { response = EffectResponse.Failure(((SimpleJSONRequest)result.Request).id, (StandardErrors)1); CrowdControlMod.Instance.Logger.LogError((object)ex.Message); } m_networkClient.AttachMetadata(response); m_networkClient.SendAsync((SimpleJSONResponse?)(object)response).Forget(); } ConsumeEnumerators(); } private void ConsumeEnumerators() { foreach (KeyValuePair<uint, RequestState> runningEffect in m_runningEffects) { if (!runningEffect.Value.MoveNext()) { m_runningEffects.TryRemove(runningEffect.Key, out RequestState _); } } } } [Serializable] [JsonConverter(typeof(Converter))] public struct SITimeSpan : IEquatable<SITimeSpan>, IEquatable<TimeSpan>, IEquatable<double>, IComparable<SITimeSpan>, IComparable<TimeSpan>, IComparable<double>, IFormattable { private class Converter : JsonConverter<SITimeSpan> { public override void WriteJson(JsonWriter writer, SITimeSpan value, JsonSerializer serializer) { writer.WriteValue(value._value.TotalSeconds); } public override SITimeSpan ReadJson(JsonReader reader, Type objectType, SITimeSpan existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value is TimeSpan timeSpan) { return timeSpan; } if (reader.Value is string s) { if (TimeSpan.TryParse(s, out var result)) { return result; } if (double.TryParse(s, out var result2)) { return result2; } } return Convert.ToDouble(reader.Value); } } public static readonly SITimeSpan Zero = new SITimeSpan(TimeSpan.Zero); public static readonly SITimeSpan MinValue = new SITimeSpan(TimeSpan.MinValue); public static readonly SITimeSpan MaxValue = new SITimeSpan(TimeSpan.MaxValue); private readonly TimeSpan _value; public long Ticks => _value.Ticks; public int Milliseconds => _value.Milliseconds; public int Seconds => _value.Seconds; public int Minutes => _value.Minutes; public int Hours => _value.Hours; public int Days => _value.Days; public double TotalMilliseconds => _value.TotalMilliseconds; public double TotalSeconds => _value.TotalSeconds; public double TotalMinutes => _value.TotalMinutes; public double TotalHours => _value.TotalHours; public double TotalDays => _value.TotalDays; public override string ToString() { return _value.ToString(); } public string ToString(string? format) { return _value.ToString(format); } public string ToString(string? format, IFormatProvider? formatProvider) { return _value.ToString(format, formatProvider); } public static SITimeSpan Parse(string input) { if (input.Contains('.')) { return new SITimeSpan(TimeSpan.ParseExact(input, "mm\\:ss\\.fff", null)); } return new SITimeSpan(TimeSpan.Parse(input)); } public static bool TryParse(string s, out SITimeSpan result) { TimeSpan result2; bool result3 = TimeSpan.TryParse(s, out result2); result = new SITimeSpan(result2); return result3; } public static int Compare(SITimeSpan t1, SITimeSpan t2) { return TimeSpan.Compare(t1._value, t2._value); } public static int Compare(TimeSpan t1, SITimeSpan t2) { return TimeSpan.Compare(t1, t2._value); } public static int Compare(SITimeSpan t1, TimeSpan t2) { return TimeSpan.Compare(t1._value, t2); } public static int Compare(double t1, SITimeSpan t2) { if (t1 > t2.TotalSeconds) { return 1; } return (t1 < t2.TotalSeconds) ? (-1) : 0; } public static int Compare(SITimeSpan t1, double t2) { if (t1.TotalSeconds > t2) { return 1; } return (t1.TotalSeconds < t2) ? (-1) : 0; } public static bool Equals(SITimeSpan t1, SITimeSpan t2) { return TimeSpan.Equals(t1._value, t2._value); } public static bool Equals(TimeSpan t1, SITimeSpan t2) { return TimeSpan.Equals(t1, t2._value); } public static bool Equals(SITimeSpan t1, TimeSpan t2) { return TimeSpan.Equals(t1._value, t2); } public static bool Equals(double t1, SITimeSpan t2) { return object.Equals(t1, (double)t2); } public static bool Equals(SITimeSpan t1, double t2) { return object.Equals((double)t1, t2); } public static SITimeSpan FromTicks(long value) { return new SITimeSpan(TimeSpan.FromTicks(value)); } public static SITimeSpan FromMilliseconds(double value) { return new SITimeSpan(TimeSpan.FromMilliseconds(value)); } public static SITimeSpan FromSeconds(double value) { return new SITimeSpan(TimeSpan.FromSeconds(value)); } public static SITimeSpan FromMinutes(double value) { return new SITimeSpan(TimeSpan.FromMinutes(value)); } public static SITimeSpan FromHours(double value) { return new SITimeSpan(TimeSpan.FromHours(value)); } public static SITimeSpan FromDays(double value) { return new SITimeSpan(TimeSpan.FromDays(value)); } public SITimeSpan Duration() { return new SITimeSpan(_value.Duration()); } public SITimeSpan Add(SITimeSpan other) { return new SITimeSpan(_value.Add(other._value)); } public SITimeSpan Subtract(SITimeSpan other) { return new SITimeSpan(_value.Subtract(other._value)); } public SITimeSpan Negate() { return new SITimeSpan(_value.Negate()); } private SITimeSpan(TimeSpan value) { _value = value; } private SITimeSpan(double value) { _value = TimeSpan.FromSeconds(value); } private SITimeSpan(long value) { _value = TimeSpan.FromSeconds(value); } public SITimeSpan? NullIfZero() { return (_value == TimeSpan.Zero) ? null : new SITimeSpan?(this); } public static implicit operator SITimeSpan(double value) { return new SITimeSpan(value); } public static implicit operator SITimeSpan?(double? value) { if (!value.HasValue) { return null; } return new SITimeSpan(value.Value); } public static implicit operator SITimeSpan(TimeSpan value) { return new SITimeSpan(value); } public static implicit operator SITimeSpan?(TimeSpan? value) { if (!value.HasValue) { return null; } return new SITimeSpan(value.Value); } public static implicit operator SITimeSpan(Func<TimeSpan> value) { return new SITimeSpan(value()); } public static implicit operator SITimeSpan?(Func<TimeSpan>? value) { if (value == null) { return null; } return new SITimeSpan(value()); } public static implicit operator SITimeSpan(Func<SITimeSpan> value) { return new SITimeSpan(value()._value); } public static implicit operator SITimeSpan?(Func<SITimeSpan>? value) { if (value == null) { return null; } return new SITimeSpan(value()._value); } public static explicit operator double(SITimeSpan value) { return value._value.TotalSeconds; } public static explicit operator double?(SITimeSpan? value) { return value?._value.TotalSeconds; } public static explicit operator float(SITimeSpan value) { return (float)value._value.TotalSeconds; } public static explicit operator float?(SITimeSpan? value) { return (float?)value?._value.TotalSeconds; } public static explicit operator long(SITimeSpan value) { return checked((long)value._value.TotalSeconds); } public static explicit operator long?(SITimeSpan? value) { return checked((long?)value?._value.TotalSeconds); } public static explicit operator TimeSpan(SITimeSpan value) { return value._value; } public static explicit operator TimeSpan?(SITimeSpan? value) { return value?._value; } public static explicit operator Func<TimeSpan>(SITimeSpan value) { return () => value._value; } public static explicit operator Func<TimeSpan?>(SITimeSpan? value) { return () => value?._value; } public static explicit operator Func<SITimeSpan>(SITimeSpan value) { return () => value; } public static explicit operator Func<SITimeSpan?>(SITimeSpan? value) { return () => value; } public override bool Equals(object? obj) { if (obj is SITimeSpan other) { return Equals(other); } if (obj is TimeSpan other2) { return Equals(other2); } if (obj is double other3) { return Equals(other3); } return false; } public override int GetHashCode() { return _value.GetHashCode(); } public bool Equals(SITimeSpan other) { return _value.Equals(other._value); } public int CompareTo(SITimeSpan other) { return _value.CompareTo(other._value); } public static bool operator ==(SITimeSpan a, SITimeSpan b) { return a._value.Equals(b._value); } public static bool operator !=(SITimeSpan a, SITimeSpan b) { return !a._value.Equals(b._value); } public static bool operator <(SITimeSpan a, SITimeSpan b) { return a._value < b._value; } public static bool operator <=(SITimeSpan a, SITimeSpan b) { return a._value <= b._value; } public static bool operator >(SITimeSpan a, SITimeSpan b) { return a._value > b._value; } public static bool operator >=(SITimeSpan a, SITimeSpan b) { return a._value >= b._value; } public bool Equals(TimeSpan other) { return _value.Equals(other); } public int CompareTo(TimeSpan other) { return _value.CompareTo(other); } public static bool operator ==(SITimeSpan a, TimeSpan b) { return a.Equals(b); } public static bool operator ==(TimeSpan a, SITimeSpan b) { return b.Equals(a); } public static bool operator !=(SITimeSpan a, TimeSpan b) { return !a.Equals(b); } public static bool operator !=(TimeSpan a, SITimeSpan b) { return !b.Equals(a); } public static bool operator <(SITimeSpan a, TimeSpan b) { return a._value < b; } public static bool operator <(TimeSpan a, SITimeSpan b) { return a < b._value; } public static bool operator <=(SITimeSpan a, TimeSpan b) { return a._value <= b; } public static bool operator <=(TimeSpan a, SITimeSpan b) { return a <= b._value; } public static bool operator >(SITimeSpan a, TimeSpan b) { return a._value > b; } public static bool operator >(TimeSpan a, SITimeSpan b) { return a > b._value; } public static bool operator >=(SITimeSpan a, TimeSpan b) { return a._value >= b; } public static bool operator >=(TimeSpan a, SITimeSpan b) { return a >= b._value; } public static SITimeSpan operator -(SITimeSpan a) { return -a._value; } public static SITimeSpan operator +(TimeSpan a, SITimeSpan b) { return a + b._value; } public static SITimeSpan operator -(TimeSpan a, SITimeSpan b) { return a - b._value; } public static SITimeSpan operator +(SITimeSpan a, TimeSpan b) { return a._value + b; } public static SITimeSpan operator -(SITimeSpan a, TimeSpan b) { return a._value - b; } public static SITimeSpan operator +(SITimeSpan a, SITimeSpan b) { return a._value + b._value; } public static SITimeSpan operator -(SITimeSpan a, SITimeSpan b) { return a._value - b._value; } public static DateTime operator +(DateTime a, SITimeSpan b) { return a + b._value; } public static DateTime operator -(DateTime a, SITimeSpan b) { return a - b._value; } public static DateTimeOffset operator +(DateTimeOffset a, SITimeSpan b) { return a + b._value; } public static DateTimeOffset operator -(DateTimeOffset a, SITimeSpan b) { return a - b._value; } public static SITimeSpan operator +(double a, SITimeSpan b) { return a + b._value.TotalSeconds; } public static SITimeSpan operator -(double a, SITimeSpan b) { return a - b._value.TotalSeconds; } public static SITimeSpan operator *(double a, SITimeSpan b) { return a * b._value.TotalSeconds; } public static SITimeSpan operator +(SITimeSpan a, double b) { return a._value.TotalSeconds + b; } public static SITimeSpan operator -(SITimeSpan a, double b) { return a._value.TotalSeconds - b; } public static SITimeSpan operator *(SITimeSpan a, double b) { return a._value.TotalSeconds * b; } public static SITimeSpan operator /(SITimeSpan a, double b) { return a._value.TotalSeconds / b; } public static SITimeSpan operator %(SITimeSpan a, double b) { return a._value.TotalSeconds % b; } public bool Equals(double other) { return _value.TotalSeconds.Equals(other); } public int CompareTo(double other) { return _value.TotalSeconds.CompareTo(other); } public static bool operator ==(SITimeSpan a, double b) { return a.Equals(b); } public static bool operator ==(double a, SITimeSpan b) { return b.Equals(a); } public static bool operator !=(SITimeSpan a, double b) { return !a.Equals(b); } public static bool operator !=(double a, SITimeSpan b) { return !b.Equals(a); } public static bool operator <(SITimeSpan a, double b) { return a._value.TotalSeconds < b; } public static bool operator <(double a, SITimeSpan b) { return a < b._value.TotalSeconds; } public static bool operator <=(SITimeSpan a, double b) { return a._value.TotalSeconds <= b; } public static bool operator >=(SITimeSpan a, double b) { return a._value.TotalSeconds >= b; } public static bool operator >(SITimeSpan a, double b) { return a._value.TotalSeconds > b; } public static bool operator >(double a, SITimeSpan b) { return a > b._value.TotalSeconds; } public static bool operator <=(double a, SITimeSpan b) { return a <= b._value.TotalSeconds; } public static bool operator >=(double a, SITimeSpan b) { return a >= b._value.TotalSeconds; } } public static class TaskEx { public static async void Forget(this Task task) { try { await task.ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex2) { Exception ex = ex2; CrowdControlMod.Instance.Logger.LogError((object)ex); } } public static async void Forget(this Task task, bool silent) { try { await task.ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex2) { Exception ex = ex2; if (!silent) { CrowdControlMod.Instance.Logger.LogError((object)ex); } } } } } namespace CrowdControl.Harmony { [HarmonyPatch] public static class Player { } } namespace CrowdControl.Delegates.Metadata { [AttributeUsage(AttributeTargets.Method)] public class MetadataAttribute : Attribute { public string[] IDs { get; } public MetadataAttribute(params string[] ids) { IDs = ids; base..ctor(); } public MetadataAttribute(string ids) : this(new string[1] { ids }) { } public MetadataAttribute([ParamCollection] IEnumerable<string> ids) : this(ids.ToArray()) { } } public delegate DataResponse MetadataDelegate(CrowdControlMod mod); public static class MetadataDelegates { public static readonly string[] CommonMetadata = Array.Empty<string>(); } public static class MetadataLoader { private const BindingFlags BINDING_FLAGS = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static readonly Dictionary<string, MetadataDelegate> Metadata; static MetadataLoader() { Metadata = new Dictionary<string, MetadataDelegate>(); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { try { MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { try { foreach (MetadataAttribute customAttribute in methodInfo.GetCustomAttributes<MetadataAttribute>()) { string[] iDs = customAttribute.IDs; foreach (string key in iDs) { try { Metadata[key] = (MetadataDelegate)Delegate.CreateDelegate(typeof(MetadataDelegate), methodInfo); } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)ex); } } } } catch { } } } catch { } } } } } namespace CrowdControl.Delegates.Effects { public abstract class Effect { public EffectAttribute EffectAttribute { get; } public bool IsTimed => EffectAttribute.DefaultDuration > 0.0; public CrowdControlMod Mod { get; } public NetworkClient Client { get; } protected Effect(CrowdControlMod mod, NetworkClient client) { Mod = mod; Client = client; EffectAttribute = GetType().GetCustomAttributes<EffectAttribute>(inherit: false).First(); } public abstract EffectResponse Start(EffectRequest request); public virtual EffectResponse? Tick(EffectRequest request) { return null; } public virtual EffectResponse? Pause(EffectRequest request) { return null; } public virtual EffectResponse? Resume(EffectRequest request) { return null; } public virtual EffectResponse? Stop(EffectRequest request) { return null; } } [AttributeUsage(AttributeTargets.Class)] public class EffectAttribute : Attribute { public IReadOnlyList<string> IDs { get; } public SITimeSpan DefaultDuration { get; } public IReadOnlyList<string> Conflicts { get; } public EffectAttribute(string[] ids, SITimeSpan defaultDuration, string[] conflicts) { IDs = ids; DefaultDuration = defaultDuration; Conflicts = conflicts; base..ctor(); } public EffectAttribute([ParamCollection] IEnumerable<string> ids) : this(ids.ToArray(), SITimeSpan.Zero, Array.Empty<string>()) { } public EffectAttribute(params string[] ids) : this(ids.ToArray(), SITimeSpan.Zero, Array.Empty<string>()) { } public EffectAttribute(string[] ids, float defaultDuration, string[] conflicts) : this(ids, (SITimeSpan)defaultDuration, conflicts) { } public EffectAttribute(string[] ids, float defaultDuration, string conflict) : this(ids, defaultDuration, new string[1] { conflict }) { } public EffectAttribute(string id) : this(new string[1] { id }, SITimeSpan.Zero, Array.Empty<string>()) { } public EffectAttribute(string id, float defaultDuration) : this(new string[1] { id }, defaultDuration, (!(SITimeSpan.Zero > 0.0)) ? Array.Empty<string>() : new string[1] { id }) { } public EffectAttribute(string id, float defaultDuration, string conflict) : this(new string[1] { id }, defaultDuration, new string[1] { conflict }) { } public EffectAttribute(string id, float defaultDuration, string[] conflicts) : this(new string[1] { id }, defaultDuration, conflicts) { } public EffectAttribute(string id, float defaultDuration, bool selfConflict) : this(new string[1] { id }, defaultDuration, (!selfConflict) ? Array.Empty<string>() : new string[1] { id }) { } public EffectAttribute(string[] ids, float defaultDuration, bool selfConflict) : this(ids, defaultDuration, selfConflict ? ids : Array.Empty<string>()) { } public EffectAttribute(string id, bool selfConflict) : this(new string[1] { id }, SITimeSpan.Zero, (!selfConflict) ? Array.Empty<string>() : new string[1] { id }) { } public EffectAttribute(string[] ids, bool selfConflict) : this(ids, SITimeSpan.Zero, selfConflict ? ids : Array.Empty<string>()) { } } public class EffectLoader { private const BindingFlags BINDING_FLAGS = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public readonly Dictionary<string, Effect> Effects = new Dictionary<string, Effect>(); public EffectLoader(CrowdControlMod mod, NetworkClient client) { foreach (Type item in from type in Assembly.GetExecutingAssembly().GetTypes() where type.IsSubclassOf(typeof(Effect)) select type) { try { foreach (EffectAttribute customAttribute in item.GetCustomAttributes<EffectAttribute>()) { foreach (string iD in customAttribute.IDs) { try { Effects[iD] = (Effect)Activator.CreateInstance(item, mod, client); } catch (Exception ex) { CrowdControlMod.Instance.Logger.LogError((object)ex); } } } } catch (Exception ex2) { CrowdControlMod.Instance.Logger.LogError((object)ex2); } } } } public class TimedEffectState { public enum EffectState { NotStarted, Running, Paused, Finished, Errored } [CompilerGenerated] private sealed class <Pause>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TimedEffectState <>4__this; private EffectResponse <response>5__1; private bool <locked>5__2; private Exception <e>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Pause>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <response>5__1 = null; <e>5__3 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <response>5__1 = null; <locked>5__2 = false; <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<locked>5__2 = <>4__this.TryGetLock()) { <>2__current = null; <>1__state = 1; result = true; } else if (<>4__this.State != EffectState.Running) { result = false; <>m__Finally1(); } else { try { <response>5__1 = <>4__this.Effect.Pause(<>4__this.Request); <>4__this.State = EffectState.Paused; } catch (Exception ex) { <e>5__3 = ex; <response>5__1 = EffectResponse.Failure(((SimpleJSONRequest)<>4__this.Request).id, (StandardErrors)1); CrowdControlMod.Instance.Logger.LogError((object)<e>5__3.Message); <>4__this.State = EffectState.Errored; } <>m__Finally1(); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<locked>5__2) { <>4__this.ReleaseLock(); <>4__this.Client.Send((SimpleJSONResponse?)(object)<response>5__1); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <Resume>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TimedEffectState <>4__this; private EffectResponse <response>5__1; private bool <locked>5__2; private Exception <e>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Resume>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <response>5__1 = null; <e>5__3 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <response>5__1 = null; <locked>5__2 = false; <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<locked>5__2 = <>4__this.TryGetLock()) { <>2__current = null; <>1__state = 1; result = true; } else if (<>4__this.State != EffectState.Paused) { result = false; <>m__Finally1(); } else { try { <response>5__1 = <>4__this.Effect.Resume(<>4__this.Request); <>4__this.State = EffectState.Running; } catch (Exception ex) { <e>5__3 = ex; <response>5__1 = EffectResponse.Failure(((SimpleJSONRequest)<>4__this.Request).id, (StandardErrors)1); CrowdControlMod.Instance.Logger.LogError((object)<e>5__3.Message); <>4__this.State = EffectState.Errored; } <>m__Finally1(); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<locked>5__2) { <>4__this.ReleaseLock(); <>4__this.Client.Send((SimpleJSONResponse?)(object)<response>5__1); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <Start>d__14 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TimedEffectState <>4__this; private EffectResponse <response>5__1; private bool <locked>5__2; private Exception <e>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Start>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <response>5__1 = null; <e>5__3 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <response>5__1 = null; <locked>5__2 = false; <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<locked>5__2 = <>4__this.TryGetLock()) { <>2__current = null; <>1__state = 1; result = true; } else if (<>4__this.State != 0) { result = false; <>m__Finally1(); } else { try { <response>5__1 = <>4__this.Effect.Start(<>4__this.Request); <>4__this.TimeRemaining = <>4__this.Duration; <>4__this.State = EffectState.Running; } catch (Exception ex) { <e>5__3 = ex; <response>5__1 = EffectResponse.Failure(((SimpleJSONRequest)<>4__this.Request).id, (StandardErrors)1); CrowdControlMod.Instance.Logger.LogError((object)<e>5__3.Message); <>4__this.State = EffectState.Errored; } <>m__Finally1(); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<locked>5__2) { <>4__this.ReleaseLock(); <>4__this.Client.Send((SimpleJSONResponse?)(object)<response>5__1); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <Stop>d__17 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TimedEffectState <>4__this; private EffectResponse <response>5__1; private bool <locked>5__2; private Exception <e>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Stop>d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <response>5__1 = null; <e>5__3 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <response>5__1 = null; <locked>5__2 = false; <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<locked>5__2 = <>4__this.TryGetLock()) { <>2__current = null; <>1__state = 1; result = true; } else if (<>4__this.State == EffectState.Finished) { result = false; <>m__Finally1(); } else { try { <response>5__1 = <>4__this.Effect.Stop(<>4__this.Request); <>4__this.State = EffectState.Finished; } catch (Exception ex) { <e>5__3 = ex; <response>5__1 = EffectResponse.Failure(((SimpleJSONRequest)<>4__this.Request).id, (StandardErrors)1); CrowdControlMod.Instance.Logger.LogError((object)<e>5__3.Message); <>4__this.State = EffectState.Errored; } <>m__Finally1(