Decompiled source of Archipelago v2.2.2
Archipelago.MultiClient.Net.dll
Decompiled 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.WebSockets; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using Archipelago.MultiClient.Net.ConcurrentCollection; using Archipelago.MultiClient.Net.Converters; using Archipelago.MultiClient.Net.DataPackage; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Exceptions; using Archipelago.MultiClient.Net.Extensions; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.MessageLog.Messages; using Archipelago.MultiClient.Net.MessageLog.Parts; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: ComVisible(false)] [assembly: Guid("35a803ad-85ed-42e9-b1e3-c6b72096f0c1")] [assembly: InternalsVisibleTo("Archipelago.MultiClient.Net.Tests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Jarno Westhof, Hussein Farran, Zach Parks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")] [assembly: AssemblyFileVersion("6.0.0.0")] [assembly: AssemblyInformationalVersion("6.0.0-rc5")] [assembly: AssemblyProduct("Archipelago.MultiClient.Net")] [assembly: AssemblyTitle("Archipelago.MultiClient.Net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")] [assembly: AssemblyVersion("6.0.0.0")] internal interface IConcurrentHashSet<T> { bool TryAdd(T item); bool Contains(T item); void UnionWith(T[] otherSet); T[] ToArray(); ReadOnlyCollection<T> AsToReadOnlyCollection(); ReadOnlyCollection<T> AsToReadOnlyCollectionExcept(IConcurrentHashSet<T> otherSet); } namespace Archipelago.MultiClient.Net { [Serializable] public abstract class ArchipelagoPacketBase { [JsonIgnore] internal JObject jobject; [JsonProperty("cmd")] [JsonConverter(typeof(StringEnumConverter))] public abstract ArchipelagoPacketType PacketType { get; } public JObject ToJObject() { return jobject; } } public class ArchipelagoSession { private const int ArchipelagoConnectionTimeoutInSeconds = 4; private ConnectionInfoHelper connectionInfo; private TaskCompletionSource<LoginResult> loginResultTask = new TaskCompletionSource<LoginResult>(); private TaskCompletionSource<RoomInfoPacket> roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>(); public IArchipelagoSocketHelper Socket { get; } public IReceivedItemsHelper Items { get; } public ILocationCheckHelper Locations { get; } public IPlayerHelper Players { get; } public IDataStorageHelper DataStorage { get; } public IConnectionInfoProvider ConnectionInfo => connectionInfo; public IRoomStateHelper RoomState { get; } public IMessageLogHelper MessageLog { get; } internal ArchipelagoSession(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog) { Socket = socket; Items = items; Locations = locations; Players = players; RoomState = roomState; connectionInfo = connectionInfoHelper; DataStorage = dataStorage; MessageLog = messageLog; socket.PacketReceived += Socket_PacketReceived; } private void Socket_PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket) && !(packet is ConnectionRefusedPacket)) { if (packet is RoomInfoPacket result) { roomInfoPacketTask.TrySetResult(result); } return; } if (packet is ConnectedPacket && RoomState.Version != null && RoomState.Version >= new Version(0, 3, 8)) { LogUsedVersion(); } loginResultTask.TrySetResult(LoginResult.FromPacket(packet)); } private void LogUsedVersion() { try { string fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; Socket.SendPacketAsync(new SetPacket { Key = ".NetUsedVersions", DefaultValue = (JToken)(object)JObject.FromObject((object)new Dictionary<string, bool>()), Operations = new OperationSpecification[1] { Operation.Update(new Dictionary<string, bool> { { ConnectionInfo.Game + ":" + fileVersion + ":NET45", true } }) } }); } catch { } } public Task<RoomInfoPacket> ConnectAsync() { roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>(); Task.Factory.StartNew(delegate { try { Task task = Socket.ConnectAsync(); task.Wait(TimeSpan.FromSeconds(4.0)); if (!task.IsCompleted) { roomInfoPacketTask.TrySetCanceled(); } } catch (AggregateException) { roomInfoPacketTask.TrySetCanceled(); } }); return roomInfoPacketTask.Task; } public Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true) { loginResultTask = new TaskCompletionSource<LoginResult>(); if (!roomInfoPacketTask.Task.IsCompleted) { loginResultTask = new TaskCompletionSource<LoginResult>(); loginResultTask.TrySetResult(new LoginFailure("You are not connected, run ConnectAsync() first")); return loginResultTask.Task; } connectionInfo.SetConnectionParameters(game, tags, itemsHandlingFlags, uuid); try { Socket.SendPacket(BuildConnectPacket(name, password, version, requestSlotData)); } catch (ArchipelagoSocketClosedException) { loginResultTask.TrySetResult(new LoginFailure("You are not connected, run ConnectAsync() first")); return loginResultTask.Task; } SetResultAfterTimeout(loginResultTask, 4, new LoginFailure("Connection timed out.")); return loginResultTask.Task; } private static void SetResultAfterTimeout<T>(TaskCompletionSource<T> task, int timeoutInSeconds, T result) { new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds)).Token.Register(delegate { task.TrySetResult(result); }); } public LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true) { Task<RoomInfoPacket> task = ConnectAsync(); try { task.Wait(TimeSpan.FromSeconds(4.0)); } catch (AggregateException ex) { if (ex.GetBaseException() is OperationCanceledException) { return new LoginFailure("Connection timed out."); } return new LoginFailure(ex.GetBaseException().Message); } if (!task.IsCompleted) { return new LoginFailure("Connection timed out."); } return LoginAsync(game, name, itemsHandlingFlags, version, tags, uuid, password, requestSlotData).Result; } private ConnectPacket BuildConnectPacket(string name, string password, Version version, bool requestSlotData) { return new ConnectPacket { Game = ConnectionInfo.Game, Name = name, Password = password, Tags = ConnectionInfo.Tags, Uuid = ConnectionInfo.Uuid, Version = ((version != null) ? new NetworkVersion(version) : new NetworkVersion(0, 4, 0)), ItemsHandling = ConnectionInfo.ItemsHandlingFlags, RequestSlotData = requestSlotData }; } public void Say(string message) { Socket.SendPacket(new SayPacket { Text = message }); } public void SetClientState(ArchipelagoClientState state) { Socket.SendPacket(new StatusUpdatePacket { Status = state }); } public void SetGoalAchieved() { SetClientState(ArchipelagoClientState.ClientGoal); } } public static class ArchipelagoSessionFactory { public static ArchipelagoSession CreateSession(Uri uri) { ArchipelagoSocketHelper socket = new ArchipelagoSocketHelper(uri); DataPackageCache cache = new DataPackageCache(socket); ConnectionInfoHelper connectionInfoHelper = new ConnectionInfoHelper(socket); PlayerHelper playerHelper = new PlayerHelper(socket, connectionInfoHelper); ItemInfoResolver itemInfoResolver = new ItemInfoResolver(cache, connectionInfoHelper); LocationCheckHelper locationCheckHelper = new LocationCheckHelper(socket, itemInfoResolver, connectionInfoHelper, playerHelper); ReceivedItemsHelper items = new ReceivedItemsHelper(socket, locationCheckHelper, itemInfoResolver, connectionInfoHelper, playerHelper); RoomStateHelper roomState = new RoomStateHelper(socket, locationCheckHelper); DataStorageHelper dataStorage = new DataStorageHelper(socket, connectionInfoHelper); MessageLogHelper messageLog = new MessageLogHelper(socket, itemInfoResolver, playerHelper, connectionInfoHelper); return new ArchipelagoSession(socket, items, locationCheckHelper, playerHelper, roomState, connectionInfoHelper, dataStorage, messageLog); } public static ArchipelagoSession CreateSession(string hostname, int port = 38281) { return CreateSession(ParseUri(hostname, port)); } internal static Uri ParseUri(string hostname, int port) { string text = hostname; if (!text.StartsWith("ws://") && !text.StartsWith("wss://")) { text = "unspecified://" + text; } if (!text.Substring(text.IndexOf("://", StringComparison.Ordinal) + 3).Contains(":")) { text += $":{port}"; } if (text.EndsWith(":")) { text += port; } return new Uri(text); } } public abstract class LoginResult { public abstract bool Successful { get; } public static LoginResult FromPacket(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket)) { if (packet is ConnectionRefusedPacket connectionRefusedPacket) { return new LoginFailure(connectionRefusedPacket); } throw new ArgumentOutOfRangeException("packet", "packet is not a connection result packet"); } return new LoginSuccessful(connectedPacket); } } public class LoginSuccessful : LoginResult { public override bool Successful => true; public int Team { get; } public int Slot { get; } public Dictionary<string, object> SlotData { get; } public LoginSuccessful(ConnectedPacket connectedPacket) { Team = connectedPacket.Team; Slot = connectedPacket.Slot; SlotData = connectedPacket.SlotData; } } public class LoginFailure : LoginResult { public override bool Successful => false; public ConnectionRefusedError[] ErrorCodes { get; } public string[] Errors { get; } public LoginFailure(ConnectionRefusedPacket connectionRefusedPacket) { if (connectionRefusedPacket.Errors != null) { ErrorCodes = connectionRefusedPacket.Errors.ToArray(); Errors = ErrorCodes.Select(GetErrorMessage).ToArray(); } else { ErrorCodes = new ConnectionRefusedError[0]; Errors = new string[0]; } } public LoginFailure(string message) { ErrorCodes = new ConnectionRefusedError[0]; Errors = new string[1] { message }; } private static string GetErrorMessage(ConnectionRefusedError errorCode) { return errorCode switch { ConnectionRefusedError.InvalidSlot => "The slot name did not match any slot on the server.", ConnectionRefusedError.InvalidGame => "The slot is set to a different game on the server.", ConnectionRefusedError.SlotAlreadyTaken => "The slot already has a connection with a different uuid established.", ConnectionRefusedError.IncompatibleVersion => "The client and server version mismatch.", ConnectionRefusedError.InvalidPassword => "The password is invalid.", ConnectionRefusedError.InvalidItemsHandling => "The item handling flags provided are invalid.", _ => $"Unknown error: {errorCode}.", }; } } internal class TwoWayLookup<TA, TB> : IEnumerable<KeyValuePair<TB, TA>>, IEnumerable { private readonly Dictionary<TA, TB> aToB = new Dictionary<TA, TB>(); private readonly Dictionary<TB, TA> bToA = new Dictionary<TB, TA>(); public TA this[TB b] => bToA[b]; public TB this[TA a] => aToB[a]; public void Add(TA a, TB b) { aToB[a] = b; bToA[b] = a; } public void Add(TB b, TA a) { Add(a, b); } public bool TryGetValue(TA a, out TB b) { return aToB.TryGetValue(a, out b); } public bool TryGetValue(TB b, out TA a) { return bToA.TryGetValue(b, out a); } public IEnumerator<KeyValuePair<TB, TA>> GetEnumerator() { return bToA.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } namespace Archipelago.MultiClient.Net.Packets { public class BouncedPacket : BouncePacket { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounced; } public class BouncePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounce; [JsonProperty("games")] public List<string> Games { get; set; } = new List<string>(); [JsonProperty("slots")] public List<int> Slots { get; set; } = new List<int>(); [JsonProperty("tags")] public List<string> Tags { get; set; } = new List<string>(); [JsonProperty("data")] public Dictionary<string, JToken> Data { get; set; } } public class ConnectedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connected; [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("missing_locations")] public long[] MissingChecks { get; set; } [JsonProperty("checked_locations")] public long[] LocationsChecked { get; set; } [JsonProperty("slot_data")] public Dictionary<string, object> SlotData { get; set; } [JsonProperty("slot_info")] public Dictionary<int, NetworkSlot> SlotInfo { get; set; } [JsonProperty("hint_points")] public int? HintPoints { get; set; } } public class ConnectionRefusedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectionRefused; [JsonProperty("errors", ItemConverterType = typeof(StringEnumConverter))] public ConnectionRefusedError[] Errors { get; set; } } public class ConnectPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connect; [JsonProperty("password")] public string Password { get; set; } [JsonProperty("game")] public string Game { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("uuid")] public string Uuid { get; set; } [JsonProperty("version")] public NetworkVersion Version { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("items_handling")] public ItemsHandlingFlags ItemsHandling { get; set; } [JsonProperty("slot_data")] public bool RequestSlotData { get; set; } } public class ConnectUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectUpdate; [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("items_handling")] public ItemsHandlingFlags? ItemsHandling { get; set; } } public class DataPackagePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.DataPackage; [JsonProperty("data")] public Archipelago.MultiClient.Net.Models.DataPackage DataPackage { get; set; } } public class GetDataPackagePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.GetDataPackage; [JsonProperty("games")] public string[] Games { get; set; } } public class GetPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Get; [JsonProperty("keys")] public string[] Keys { get; set; } } public class InvalidPacketPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.InvalidPacket; [JsonProperty("type")] public InvalidPacketErrorType ErrorType { get; set; } [JsonProperty("text")] public string ErrorText { get; set; } [JsonProperty("original_cmd")] public ArchipelagoPacketType OriginalCmd { get; set; } } public class LocationChecksPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationChecks; [JsonProperty("locations")] public long[] Locations { get; set; } } public class LocationInfoPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationInfo; [JsonProperty("locations")] public NetworkItem[] Locations { get; set; } } public class LocationScoutsPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationScouts; [JsonProperty("locations")] public long[] Locations { get; set; } [JsonProperty("create_as_hint")] public int CreateAsHint { get; set; } } public class PrintJsonPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.PrintJSON; [JsonProperty("data")] public JsonMessagePart[] Data { get; set; } [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] public JsonMessageType? MessageType { get; set; } } public class ItemPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } } public class ItemCheatPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } [JsonProperty("team")] public int Team { get; set; } } public class HintPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } [JsonProperty("found")] public bool? Found { get; set; } } public class JoinPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } } public class LeavePrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class ChatPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("message")] public string Message { get; set; } } public class ServerChatPrintJsonPacket : PrintJsonPacket { [JsonProperty("message")] public string Message { get; set; } } public class TutorialPrintJsonPacket : PrintJsonPacket { } public class TagsChangedPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } } public class CommandResultPrintJsonPacket : PrintJsonPacket { } public class AdminCommandResultPrintJsonPacket : PrintJsonPacket { } public class GoalPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class ReleasePrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class CollectPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class CountdownPrintJsonPacket : PrintJsonPacket { [JsonProperty("countdown")] public int RemainingSeconds { get; set; } } public class ReceivedItemsPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ReceivedItems; [JsonProperty("index")] public int Index { get; set; } [JsonProperty("items")] public NetworkItem[] Items { get; set; } } public class RetrievedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Retrieved; [JsonProperty("keys")] public Dictionary<string, JToken> Data { get; set; } } public class RoomInfoPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.RoomInfo; [JsonProperty("version")] public NetworkVersion Version { get; set; } [JsonProperty("generator_version")] public NetworkVersion GeneratorVersion { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("password")] public bool Password { get; set; } [JsonProperty("permissions")] public Dictionary<string, Permissions> Permissions { get; set; } [JsonProperty("hint_cost")] public int HintCostPercentage { get; set; } [JsonProperty("location_check_points")] public int LocationCheckPoints { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("games")] public string[] Games { get; set; } [JsonProperty("datapackage_checksums")] public Dictionary<string, string> DataPackageChecksums { get; set; } [JsonProperty("seed_name")] public string SeedName { get; set; } [JsonProperty("time")] public double Timestamp { get; set; } } public class RoomUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.RoomUpdate; [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("password")] public bool? Password { get; set; } [JsonProperty("permissions")] public Dictionary<string, Permissions> Permissions { get; set; } = new Dictionary<string, Permissions>(); [JsonProperty("hint_cost")] public int? HintCostPercentage { get; set; } [JsonProperty("location_check_points")] public int? LocationCheckPoints { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("hint_points")] public int? HintPoints { get; set; } [JsonProperty("checked_locations")] public long[] CheckedLocations { get; set; } } public class SayPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Say; [JsonProperty("text")] public string Text { get; set; } } public class SetNotifyPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.SetNotify; [JsonProperty("keys")] public string[] Keys { get; set; } } public class SetPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Set; [JsonProperty("key")] public string Key { get; set; } [JsonProperty("default")] public JToken DefaultValue { get; set; } [JsonProperty("operations")] public OperationSpecification[] Operations { get; set; } [JsonProperty("want_reply")] public bool WantReply { get; set; } [JsonExtensionData] public Dictionary<string, JToken> AdditionalArguments { get; set; } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { AdditionalArguments?.Remove("cmd"); } } public class SetReplyPacket : SetPacket { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.SetReply; [JsonProperty("value")] public JToken Value { get; set; } [JsonProperty("original_value")] public JToken OriginalValue { get; set; } } public class StatusUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.StatusUpdate; [JsonProperty("status")] public ArchipelagoClientState Status { get; set; } } public class SyncPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Sync; } internal class UnknownPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Unknown; } } namespace Archipelago.MultiClient.Net.Models { public struct Color : IEquatable<Color> { public static Color Red = new Color(byte.MaxValue, 0, 0); public static Color Green = new Color(0, 128, 0); public static Color Yellow = new Color(byte.MaxValue, byte.MaxValue, 0); public static Color Blue = new Color(0, 0, byte.MaxValue); public static Color Magenta = new Color(byte.MaxValue, 0, byte.MaxValue); public static Color Cyan = new Color(0, byte.MaxValue, byte.MaxValue); public static Color Black = new Color(0, 0, 0); public static Color White = new Color(byte.MaxValue, byte.MaxValue, byte.MaxValue); public static Color SlateBlue = new Color(106, 90, 205); public static Color Salmon = new Color(250, 128, 114); public static Color Plum = new Color(221, 160, 221); public byte R { get; set; } public byte G { get; set; } public byte B { get; set; } public Color(byte r, byte g, byte b) { R = r; G = g; B = b; } public override bool Equals(object obj) { if (obj is Color color && R == color.R && G == color.G) { return B == color.B; } return false; } public bool Equals(Color other) { if (R == other.R && G == other.G) { return B == other.B; } return false; } public override int GetHashCode() { return ((-1520100960 * -1521134295 + R.GetHashCode()) * -1521134295 + G.GetHashCode()) * -1521134295 + B.GetHashCode(); } public static bool operator ==(Color left, Color right) { return left.Equals(right); } public static bool operator !=(Color left, Color right) { return !(left == right); } } public class DataPackage { [JsonProperty("games")] public Dictionary<string, GameData> Games { get; set; } = new Dictionary<string, GameData>(); } public class DataStorageElement { internal DataStorageElementContext Context; internal List<OperationSpecification> Operations = new List<OperationSpecification>(0); internal DataStorageHelper.DataStorageUpdatedHandler Callbacks; internal Dictionary<string, JToken> AdditionalArguments = new Dictionary<string, JToken>(0); private JToken cachedValue; public event DataStorageHelper.DataStorageUpdatedHandler OnValueChanged { add { Context.AddHandler(Context.Key, value); } remove { Context.RemoveHandler(Context.Key, value); } } internal DataStorageElement(DataStorageElementContext context) { Context = context; } internal DataStorageElement(OperationType operationType, JToken value) { Operations = new List<OperationSpecification>(1) { new OperationSpecification { OperationType = operationType, Value = value } }; } internal DataStorageElement(DataStorageElement source, OperationType operationType, JToken value) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; Operations.Add(new OperationSpecification { OperationType = operationType, Value = value }); } internal DataStorageElement(DataStorageElement source, Callback callback) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; Callbacks = (DataStorageHelper.DataStorageUpdatedHandler)Delegate.Combine(Callbacks, callback.Method); } internal DataStorageElement(DataStorageElement source, AdditionalArgument additionalArgument) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; AdditionalArguments[additionalArgument.Key] = additionalArgument.Value; } public static DataStorageElement operator ++(DataStorageElement a) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(1)); } public static DataStorageElement operator --(DataStorageElement a) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(-1)); } public static DataStorageElement operator +(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, string b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, JToken b) { return new DataStorageElement(a, OperationType.Add, b); } public static DataStorageElement operator +(DataStorageElement a, IEnumerable b) { return new DataStorageElement(a, OperationType.Add, (JToken)(object)JArray.FromObject((object)b)); } public static DataStorageElement operator +(DataStorageElement a, OperationSpecification s) { return new DataStorageElement(a, s.OperationType, s.Value); } public static DataStorageElement operator +(DataStorageElement a, Callback c) { return new DataStorageElement(a, c); } public static DataStorageElement operator +(DataStorageElement a, AdditionalArgument arg) { return new DataStorageElement(a, arg); } public static DataStorageElement operator *(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator -(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator -(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator -(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(0f - b))); } public static DataStorageElement operator -(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(0.0 - b))); } public static DataStorageElement operator -(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator /(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / (decimal)b))); } public static DataStorageElement operator /(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / (decimal)b))); } public static DataStorageElement operator /(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1.0 / (double)b))); } public static DataStorageElement operator /(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1.0 / b))); } public static DataStorageElement operator /(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / b))); } public static implicit operator DataStorageElement(bool b) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(b)); } public static implicit operator DataStorageElement(int i) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(i)); } public static implicit operator DataStorageElement(long l) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(l)); } public static implicit operator DataStorageElement(decimal m) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(m)); } public static implicit operator DataStorageElement(double d) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(d)); } public static implicit operator DataStorageElement(float f) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(f)); } public static implicit operator DataStorageElement(string s) { if (s != null) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(s)); } return new DataStorageElement(OperationType.Replace, (JToken)(object)JValue.CreateNull()); } public static implicit operator DataStorageElement(JToken o) { return new DataStorageElement(OperationType.Replace, o); } public static implicit operator DataStorageElement(Array a) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)a)); } public static implicit operator DataStorageElement(List<bool> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<int> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<long> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<decimal> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<double> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<float> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<string> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<object> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator bool(DataStorageElement e) { return RetrieveAndReturnBoolValue<bool>(e); } public static implicit operator bool?(DataStorageElement e) { return RetrieveAndReturnBoolValue<bool?>(e); } public static implicit operator int(DataStorageElement e) { return RetrieveAndReturnDecimalValue<int>(e); } public static implicit operator int?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<int?>(e); } public static implicit operator long(DataStorageElement e) { return RetrieveAndReturnDecimalValue<long>(e); } public static implicit operator long?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<long?>(e); } public static implicit operator float(DataStorageElement e) { return RetrieveAndReturnDecimalValue<float>(e); } public static implicit operator float?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<float?>(e); } public static implicit operator double(DataStorageElement e) { return RetrieveAndReturnDecimalValue<double>(e); } public static implicit operator double?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<double?>(e); } public static implicit operator decimal(DataStorageElement e) { return RetrieveAndReturnDecimalValue<decimal>(e); } public static implicit operator decimal?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<decimal?>(e); } public static implicit operator string(DataStorageElement e) { return RetrieveAndReturnStringValue(e); } public static implicit operator bool[](DataStorageElement e) { return RetrieveAndReturnArrayValue<bool[]>(e); } public static implicit operator int[](DataStorageElement e) { return RetrieveAndReturnArrayValue<int[]>(e); } public static implicit operator long[](DataStorageElement e) { return RetrieveAndReturnArrayValue<long[]>(e); } public static implicit operator decimal[](DataStorageElement e) { return RetrieveAndReturnArrayValue<decimal[]>(e); } public static implicit operator double[](DataStorageElement e) { return RetrieveAndReturnArrayValue<double[]>(e); } public static implicit operator float[](DataStorageElement e) { return RetrieveAndReturnArrayValue<float[]>(e); } public static implicit operator string[](DataStorageElement e) { return RetrieveAndReturnArrayValue<string[]>(e); } public static implicit operator object[](DataStorageElement e) { return RetrieveAndReturnArrayValue<object[]>(e); } public static implicit operator List<bool>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<bool>>(e); } public static implicit operator List<int>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<int>>(e); } public static implicit operator List<long>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<long>>(e); } public static implicit operator List<decimal>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<decimal>>(e); } public static implicit operator List<double>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<double>>(e); } public static implicit operator List<float>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<float>>(e); } public static implicit operator List<string>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<string>>(e); } public static implicit operator List<object>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<object>>(e); } public static implicit operator Array(DataStorageElement e) { return RetrieveAndReturnArrayValue<Array>(e); } public static implicit operator JArray(DataStorageElement e) { return RetrieveAndReturnArrayValue<JArray>(e); } public static implicit operator JToken(DataStorageElement e) { return e.Context.GetData(e.Context.Key); } public static DataStorageElement operator +(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Add, JToken.Parse(b.ToString())); } public static DataStorageElement operator *(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Mul, JToken.Parse(b.ToString())); } public static DataStorageElement operator %(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Mod, JToken.Parse(b.ToString())); } public static DataStorageElement operator ^(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Pow, JToken.Parse(b.ToString())); } public static DataStorageElement operator -(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Add, JToken.Parse((-b).ToString())); } public static DataStorageElement operator /(DataStorageElement a, BigInteger b) { throw new InvalidOperationException("DataStorage[Key] / BigInterger is not supported, due to loss of precision when using integer division"); } public static implicit operator DataStorageElement(BigInteger bi) { return new DataStorageElement(OperationType.Replace, JToken.Parse(bi.ToString())); } public static implicit operator BigInteger(DataStorageElement e) { return RetrieveAndReturnBigIntegerValue<BigInteger>(e); } public static implicit operator BigInteger?(DataStorageElement e) { return RetrieveAndReturnBigIntegerValue<BigInteger?>(e); } private static T RetrieveAndReturnBigIntegerValue<T>(DataStorageElement e) { if (e.cachedValue != null) { if (!BigInteger.TryParse(((object)e.cachedValue).ToString(), out var result)) { return default(T); } return (T)Convert.ChangeType(result, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } BigInteger result2; BigInteger? bigInteger = (BigInteger.TryParse(((object)e.Context.GetData(e.Context.Key)).ToString(), out result2) ? new BigInteger?(result2) : null); if (!bigInteger.HasValue && !IsNullable<T>()) { bigInteger = Activator.CreateInstance<BigInteger>(); } foreach (OperationSpecification operation in e.Operations) { if (operation.OperationType == OperationType.Floor || operation.OperationType == OperationType.Ceil) { continue; } if (!BigInteger.TryParse(((object)operation.Value).ToString(), NumberStyles.AllowLeadingSign, null, out var result3)) { throw new InvalidOperationException($"DataStorage[Key] cannot be converted to BigInterger as its value its not an integer number, value: {operation.Value}"); } switch (operation.OperationType) { case OperationType.Replace: bigInteger = result3; break; case OperationType.Add: bigInteger += result3; break; case OperationType.Mul: bigInteger *= result3; break; case OperationType.Mod: bigInteger %= result3; break; case OperationType.Pow: bigInteger = BigInteger.Pow(bigInteger.Value, (int)operation.Value); break; case OperationType.Max: { BigInteger value = result3; BigInteger? bigInteger2 = bigInteger; if (value > bigInteger2) { bigInteger = result3; } break; } case OperationType.Min: { BigInteger value = result3; BigInteger? bigInteger2 = bigInteger; if (value < bigInteger2) { bigInteger = result3; } break; } case OperationType.Xor: bigInteger ^= result3; break; case OperationType.Or: bigInteger |= result3; break; case OperationType.And: bigInteger &= result3; break; case OperationType.LeftShift: bigInteger <<= (int)operation.Value; break; case OperationType.RightShift: bigInteger >>= (int)operation.Value; break; } } e.cachedValue = JToken.Parse(bigInteger.ToString()); if (!bigInteger.HasValue) { return default(T); } return (T)Convert.ChangeType(bigInteger.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } public void Initialize(JToken value) { Context.Initialize(Context.Key, value); } public void Initialize(IEnumerable value) { Context.Initialize(Context.Key, (JToken)(object)JArray.FromObject((object)value)); } public Task<T> GetAsync<T>() { return GetAsync().ContinueWith((Task<JToken> r) => r.Result.ToObject<T>()); } public Task<JToken> GetAsync() { return Context.GetAsync(Context.Key); } private static T RetrieveAndReturnArrayValue<T>(DataStorageElement e) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (e.cachedValue != null) { return ((JToken)(JArray)e.cachedValue).ToObject<T>(); } JArray val = (JArray)(((object)e.Context.GetData(e.Context.Key).ToObject<JArray>()) ?? ((object)new JArray())); foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Add: if ((int)operation.Value.Type != 2) { throw new InvalidOperationException($"Cannot perform operation {OperationType.Add} on Array value, with a non Array value: {operation.Value}"); } ((JContainer)val).Merge((object)operation.Value); break; case OperationType.Replace: if ((int)operation.Value.Type != 2) { throw new InvalidOperationException($"Cannot replace Array value, with a non Array value: {operation.Value}"); } val = (JArray)(((object)operation.Value.ToObject<JArray>()) ?? ((object)new JArray())); break; default: throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on Array value"); } } e.cachedValue = (JToken)(object)val; return ((JToken)val).ToObject<T>(); } private static string RetrieveAndReturnStringValue(DataStorageElement e) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Invalid comparison between Unknown and I4 if (e.cachedValue != null) { return (string)e.cachedValue; } JToken val = e.Context.GetData(e.Context.Key); string text = (((int)val.Type == 10) ? null : ((object)val).ToString()); foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Add: text += (string)operation.Value; break; case OperationType.Mul: if ((int)operation.Value.Type != 6) { throw new InvalidOperationException($"Cannot perform operation {OperationType.Mul} on string value, with a non interger value: {operation.Value}"); } text = string.Concat(Enumerable.Repeat(text, (int)operation.Value)); break; case OperationType.Replace: text = (string)operation.Value; break; default: throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on string value"); } } if (text == null) { e.cachedValue = (JToken)(object)JValue.CreateNull(); } else { e.cachedValue = JToken.op_Implicit(text); } return (string)e.cachedValue; } private static T RetrieveAndReturnBoolValue<T>(DataStorageElement e) { if (e.cachedValue != null) { return e.cachedValue.ToObject<T>(); } bool? flag = e.Context.GetData(e.Context.Key).ToObject<bool?>() ?? ((bool?)Activator.CreateInstance(typeof(T))); foreach (OperationSpecification operation in e.Operations) { if (operation.OperationType == OperationType.Replace) { flag = (bool?)operation.Value; continue; } throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on boolean value"); } e.cachedValue = JToken.op_Implicit(flag); if (!flag.HasValue) { return default(T); } return (T)Convert.ChangeType(flag.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } private static T RetrieveAndReturnDecimalValue<T>(DataStorageElement e) { if (e.cachedValue != null) { return e.cachedValue.ToObject<T>(); } decimal? num = e.Context.GetData(e.Context.Key).ToObject<decimal?>(); if (!num.HasValue && !IsNullable<T>()) { num = Activator.CreateInstance<decimal>(); } foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Replace: num = (decimal)operation.Value; break; case OperationType.Add: num += (decimal?)(decimal)operation.Value; break; case OperationType.Mul: num *= (decimal?)(decimal)operation.Value; break; case OperationType.Mod: num %= (decimal?)(decimal)operation.Value; break; case OperationType.Pow: num = (decimal)Math.Pow((double)num.Value, (double)operation.Value); break; case OperationType.Max: num = Math.Max(num.Value, (decimal)operation.Value); break; case OperationType.Min: num = Math.Min(num.Value, (decimal)operation.Value); break; case OperationType.Xor: num = (long)num.Value ^ (long)operation.Value; break; case OperationType.Or: num = (long)num.Value | (long)operation.Value; break; case OperationType.And: num = (long)num.Value & (long)operation.Value; break; case OperationType.LeftShift: num = (long)num.Value << (int)operation.Value; break; case OperationType.RightShift: num = (long)num.Value >> (int)operation.Value; break; case OperationType.Floor: num = Math.Floor(num.Value); break; case OperationType.Ceil: num = Math.Ceiling(num.Value); break; } } e.cachedValue = JToken.op_Implicit(num); if (!num.HasValue) { return default(T); } return (T)Convert.ChangeType(num.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } private static bool IsNullable<T>() { if (typeof(T).IsGenericType) { return typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition(); } return false; } public T To<T>() { if (Operations.Count != 0) { throw new InvalidOperationException("DataStorageElement.To<T>() cannot be used together with other operations on the DataStorageElement"); } return Context.GetData(Context.Key).ToObject<T>(); } public override string ToString() { return (Context?.ToString() ?? "(null)") + ", (" + ListOperations() + ")"; } private string ListOperations() { if (Operations != null) { return string.Join(", ", Operations.Select((OperationSpecification o) => o.ToString()).ToArray()); } return "none"; } } internal class DataStorageElementContext { internal string Key { get; set; } internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> AddHandler { get; set; } internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> RemoveHandler { get; set; } internal Func<string, JToken> GetData { get; set; } internal Action<string, JToken> Initialize { get; set; } internal Func<string, Task<JToken>> GetAsync { get; set; } public override string ToString() { return "Key: " + Key; } } public class GameData { [JsonProperty("location_name_to_id")] public Dictionary<string, long> LocationLookup { get; set; } = new Dictionary<string, long>(); [JsonProperty("item_name_to_id")] public Dictionary<string, long> ItemLookup { get; set; } = new Dictionary<string, long>(); [Obsolete("use Checksum instead")] [JsonProperty("version")] public int Version { get; set; } [JsonProperty("checksum")] public string Checksum { get; set; } } public class Hint { [JsonProperty("receiving_player")] public int ReceivingPlayer { get; set; } [JsonProperty("finding_player")] public int FindingPlayer { get; set; } [JsonProperty("item")] public long ItemId { get; set; } [JsonProperty("location")] public long LocationId { get; set; } [JsonProperty("item_flags")] public ItemFlags ItemFlags { get; set; } [JsonProperty("found")] public bool Found { get; set; } [JsonProperty("entrance")] public string Entrance { get; set; } } public class ItemInfo { private readonly IItemInfoResolver itemInfoResolver; public long ItemId { get; } public long LocationId { get; } public PlayerInfo Player { get; } public ItemFlags Flags { get; } public string ItemName => itemInfoResolver.GetItemName(ItemId, ItemGame); public string ItemDisplayName => ItemName ?? $"Item: {ItemId}"; public string LocationName => itemInfoResolver.GetLocationName(LocationId, LocationGame); public string LocationDisplayName => LocationName ?? $"Location: {LocationId}"; public string ItemGame { get; } public string LocationGame { get; } public ItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, PlayerInfo player) { this.itemInfoResolver = itemInfoResolver; ItemGame = receiverGame; LocationGame = senderGame; ItemId = item.Item; LocationId = item.Location; Flags = item.Flags; Player = player; } } public class ScoutedItemInfo : ItemInfo { public new PlayerInfo Player => base.Player; public ScoutedItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, PlayerInfo player) : base(item, receiverGame, senderGame, itemInfoResolver, player) { } } public class JsonMessagePart { [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public JsonMessagePartType? Type { get; set; } [JsonProperty("color")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public JsonMessagePartColor? Color { get; set; } [JsonProperty("text")] public string Text { get; set; } [JsonProperty("player")] public int? Player { get; set; } [JsonProperty("flags")] public ItemFlags? Flags { get; set; } } public struct NetworkItem { [JsonProperty("item")] public long Item { get; set; } [JsonProperty("location")] public long Location { get; set; } [JsonProperty("player")] public int Player { get; set; } [JsonProperty("flags")] public ItemFlags Flags { get; set; } } public struct NetworkPlayer { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("alias")] public string Alias { get; set; } [JsonProperty("name")] public string Name { get; set; } } public struct NetworkSlot { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("game")] public string Game { get; set; } [JsonProperty("type")] public SlotType Type { get; set; } [JsonProperty("group_members")] public int[] GroupMembers { get; set; } } public class NetworkVersion { [JsonProperty("major")] public int Major { get; set; } [JsonProperty("minor")] public int Minor { get; set; } [JsonProperty("build")] public int Build { get; set; } [JsonProperty("class")] public string Class => "Version"; public NetworkVersion() { } public NetworkVersion(int major, int minor, int build) { Major = major; Minor = minor; Build = build; } public NetworkVersion(Version version) { Major = version.Major; Minor = version.Minor; Build = version.Build; } public Version ToVersion() { return new Version(Major, Minor, Build); } } public class OperationSpecification { [JsonProperty("operation")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public OperationType OperationType; [JsonProperty("value")] public JToken Value { get; set; } public override string ToString() { return $"{OperationType}: {Value}"; } } public static class Operation { public static OperationSpecification Min(int i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(long i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(float i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(double i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(decimal i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(JToken i) { return new OperationSpecification { OperationType = OperationType.Min, Value = i }; } public static OperationSpecification Min(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Max(int i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(long i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(float i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(double i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(decimal i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(JToken i) { return new OperationSpecification { OperationType = OperationType.Max, Value = i }; } public static OperationSpecification Max(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Remove(JToken value) { return new OperationSpecification { OperationType = OperationType.Remove, Value = value }; } public static OperationSpecification Pop(int value) { return new OperationSpecification { OperationType = OperationType.Pop, Value = JToken.op_Implicit(value) }; } public static OperationSpecification Pop(JToken value) { return new OperationSpecification { OperationType = OperationType.Pop, Value = value }; } public static OperationSpecification Update(IDictionary dictionary) { return new OperationSpecification { OperationType = OperationType.Update, Value = (JToken)(object)JObject.FromObject((object)dictionary) }; } public static OperationSpecification Floor() { return new OperationSpecification { OperationType = OperationType.Floor, Value = null }; } public static OperationSpecification Ceiling() { return new OperationSpecification { OperationType = OperationType.Ceil, Value = null }; } } public static class Bitwise { public static OperationSpecification Xor(long i) { return new OperationSpecification { OperationType = OperationType.Xor, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Xor(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Xor, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Or(long i) { return new OperationSpecification { OperationType = OperationType.Or, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Or(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Or, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification And(long i) { return new OperationSpecification { OperationType = OperationType.And, Value = JToken.op_Implicit(i) }; } public static OperationSpecification And(BigInteger i) { return new OperationSpecification { OperationType = OperationType.And, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification LeftShift(long i) { return new OperationSpecification { OperationType = OperationType.LeftShift, Value = JToken.op_Implicit(i) }; } public static OperationSpecification RightShift(long i) { return new OperationSpecification { OperationType = OperationType.RightShift, Value = JToken.op_Implicit(i) }; } } public class Callback { internal DataStorageHelper.DataStorageUpdatedHandler Method { get; set; } private Callback() { } public static Callback Add(DataStorageHelper.DataStorageUpdatedHandler callback) { return new Callback { Method = callback }; } } public class AdditionalArgument { internal string Key { get; set; } internal JToken Value { get; set; } private AdditionalArgument() { } public static AdditionalArgument Add(string name, JToken value) { return new AdditionalArgument { Key = name, Value = value }; } } } namespace Archipelago.MultiClient.Net.MessageLog.Parts { public class EntranceMessagePart : MessagePart { internal EntranceMessagePart(JsonMessagePart messagePart) : base(MessagePartType.Entrance, messagePart, Color.Blue) { base.Text = messagePart.Text; } } public class ItemMessagePart : MessagePart { public ItemFlags Flags { get; } public long ItemId { get; } public int Player { get; } internal ItemMessagePart(IPlayerHelper players, IItemInfoResolver items, JsonMessagePart part) : base(MessagePartType.Item, part) { Flags = part.Flags.GetValueOrDefault(); base.Color = GetColor(Flags); Player = part.Player.GetValueOrDefault(); string game = (players.GetPlayerInfo(Player) ?? new PlayerInfo()).Game; JsonMessagePartType? type = part.Type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case JsonMessagePartType.ItemId: ItemId = long.Parse(part.Text); base.Text = items.GetItemName(ItemId, game) ?? $"Item: {ItemId}"; break; case JsonMessagePartType.ItemName: ItemId = 0L; base.Text = part.Text; break; } } } private static Color GetColor(ItemFlags flags) { if (HasFlag(flags, ItemFlags.Advancement)) { return Color.Plum; } if (HasFlag(flags, ItemFlags.NeverExclude)) { return Color.SlateBlue; } if (HasFlag(flags, ItemFlags.Trap)) { return Color.Salmon; } return Color.Cyan; } private static bool HasFlag(ItemFlags flags, ItemFlags flag) { return flags.HasFlag(flag); } } public class LocationMessagePart : MessagePart { public long LocationId { get; } public int Player { get; } internal LocationMessagePart(IPlayerHelper players, IItemInfoResolver itemInfoResolver, JsonMessagePart part) : base(MessagePartType.Location, part, Color.Green) { Player = part.Player.GetValueOrDefault(); string game = (players.GetPlayerInfo(Player) ?? new PlayerInfo()).Game; JsonMessagePartType? type = part.Type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case JsonMessagePartType.LocationId: LocationId = long.Parse(part.Text); base.Text = itemInfoResolver.GetLocationName(LocationId, game) ?? $"Location: {LocationId}"; break; case JsonMessagePartType.LocationName: LocationId = itemInfoResolver.GetLocationId(part.Text, game); base.Text = part.Text; break; } } } } public class MessagePart { public string Text { get; internal set; } public MessagePartType Type { get; internal set; } public Color Color { get; internal set; } public bool IsBackgroundColor { get; internal set; } internal MessagePart(MessagePartType type, JsonMessagePart messagePart, Color? color = null) { Type = type; Text = messagePart.Text; if (color.HasValue) { Color = color.Value; } else if (messagePart.Color.HasValue) { Color = GetColor(messagePart.Color.Value); IsBackgroundColor = messagePart.Color.Value >= JsonMessagePartColor.BlackBg; } else { Color = Color.White; } } private static Color GetColor(JsonMessagePartColor color) { switch (color) { case JsonMessagePartColor.Red: case JsonMessagePartColor.RedBg: return Color.Red; case JsonMessagePartColor.Green: case JsonMessagePartColor.GreenBg: return Color.Green; case JsonMessagePartColor.Yellow: case JsonMessagePartColor.YellowBg: return Color.Yellow; case JsonMessagePartColor.Blue: case JsonMessagePartColor.BlueBg: return Color.Blue; case JsonMessagePartColor.Magenta: case JsonMessagePartColor.MagentaBg: return Color.Magenta; case JsonMessagePartColor.Cyan: case JsonMessagePartColor.CyanBg: return Color.Cyan; case JsonMessagePartColor.Black: case JsonMessagePartColor.BlackBg: return Color.Black; case JsonMessagePartColor.White: case JsonMessagePartColor.WhiteBg: return Color.White; default: return Color.White; } } public override string ToString() { return Text; } } public enum MessagePartType { Text, Player, Item, Location, Entrance } public class PlayerMessagePart : MessagePart { public bool IsActivePlayer { get; } public int SlotId { get; } internal PlayerMessagePart(IPlayerHelper players, IConnectionInfoProvider connectionInfo, JsonMessagePart part) : base(MessagePartType.Player, part) { switch (part.Type) { case JsonMessagePartType.PlayerId: SlotId = int.Parse(part.Text); IsActivePlayer = SlotId == connectionInfo.Slot; base.Text = players.GetPlayerAlias(SlotId) ?? $"Player {SlotId}"; break; case JsonMessagePartType.PlayerName: SlotId = 0; IsActivePlayer = false; base.Text = part.Text; break; } base.Color = GetColor(IsActivePlayer); } private static Color GetColor(bool isActivePlayer) { if (isActivePlayer) { return Color.Magenta; } return Color.Yellow; } } } namespace Archipelago.MultiClient.Net.MessageLog.Messages { public class AdminCommandResultLogMessage : LogMessage { internal AdminCommandResultLogMessage(MessagePart[] parts) : base(parts) { } } public class ChatLogMessage : PlayerSpecificLogMessage { public string Message { get; } internal ChatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string message) : base(parts, players, connectionInfo, team, slot) { Message = message; } } public class CollectLogMessage : PlayerSpecificLogMessage { internal CollectLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class CommandResultLogMessage : LogMessage { internal CommandResultLogMessage(MessagePart[] parts) : base(parts) { } } public class CountdownLogMessage : LogMessage { public int RemainingSeconds { get; } internal CountdownLogMessage(MessagePart[] parts, int remainingSeconds) : base(parts) { RemainingSeconds = remainingSeconds; } } public class GoalLogMessage : PlayerSpecificLogMessage { internal GoalLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class HintItemSendLogMessage : ItemSendLogMessage { public bool IsFound { get; } internal HintItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, bool found, IItemInfoResolver itemInfoResolver) : base(parts, players, connectionInfo, receiver, sender, item, itemInfoResolver) { IsFound = found; } } public class ItemCheatLogMessage : ItemSendLogMessage { internal ItemCheatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, NetworkItem item, IItemInfoResolver itemInfoResolver) : base(parts, players, connectionInfo, slot, 0, item, team, itemInfoResolver) { } } public class ItemSendLogMessage : LogMessage { public PlayerInfo Receiver { get; } public PlayerInfo Sender { get; } public bool IsReceiverTheActivePlayer { get; } public bool IsSenderTheActivePlayer { get; } public bool IsRelatedToActivePlayer { get; } public ItemInfo Item { get; } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, IItemInfoResolver itemInfoResolver) : this(parts, players, connectionInfo, receiver, sender, item, connectionInfo.Team, itemInfoResolver) { } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, int team, IItemInfoResolver itemInfoResolver) : base(parts) { IsReceiverTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == receiver; IsSenderTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == sender; Receiver = players.GetPlayerInfo(team, receiver) ?? new PlayerInfo(); Sender = players.GetPlayerInfo(team, sender) ?? new PlayerInfo(); PlayerInfo player = players.GetPlayerInfo(team, item.Player) ?? new PlayerInfo(); IsRelatedToActivePlayer = IsReceiverTheActivePlayer || IsSenderTheActivePlayer || Receiver.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot) || Sender.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot); Item = new ItemInfo(item, Receiver.Game, Sender.Game, itemInfoResolver, player); } } public class JoinLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal JoinLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags) : base(parts, players, connectionInfo, team, slot) { Tags = tags; } } public class LeaveLogMessage : PlayerSpecificLogMessage { internal LeaveLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class LogMessage { public MessagePart[] Parts { get; } internal LogMessage(MessagePart[] parts) { Parts = parts; } public override string ToString() { if (Parts.Length == 1) { return Parts[0].Text; } StringBuilder stringBuilder = new StringBuilder(); MessagePart[] parts = Parts; foreach (MessagePart messagePart in parts) { stringBuilder.Append(messagePart.Text); } return stringBuilder.ToString(); } } public abstract class PlayerSpecificLogMessage : LogMessage { public PlayerInfo Player { get; } public bool IsActivePlayer { get; } public bool IsRelatedToActivePlayer { get; } internal PlayerSpecificLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts) { ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> players2 = players.Players; IsActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == slot; Player = ((players2.Count > team && players2[team].Count > slot) ? players2[team][slot] : new PlayerInfo()); IsRelatedToActivePlayer = IsActivePlayer || Player.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot); } } public class ReleaseLogMessage : PlayerSpecificLogMessage { internal ReleaseLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class ServerChatLogMessage : LogMessage { public string Message { get; } internal ServerChatLogMessage(MessagePart[] parts, string message) : base(parts) { Message = message; } } public class TagsChangedLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal TagsChangedLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags) : base(parts, players, connectionInfo, team, slot) { Tags = tags; } } public class TutorialLogMessage : LogMessage { internal TutorialLogMessage(MessagePart[] parts) : base(parts) { } } } namespace Archipelago.MultiClient.Net.Helpers { public class ArchipelagoSocketHelper : IArchipelagoSocketHelper { private static readonly ArchipelagoPacketConverter Converter = new ArchipelagoPacketConverter(); private const int ReceiveChunkSize = 1024; private const int SendChunkSize = 1024; private readonly BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>> sendQueue = new BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>>(); internal ClientWebSocket webSocket; public Uri Uri { get; } public bool Connected { get { if (webSocket.State != WebSocketState.Open) { return webSocket.State == WebSocketState.CloseReceived; } return true; } } public event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived; public event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent; public event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived; public event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed; public event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened; internal ArchipelagoSocketHelper(Uri hostUri) { Uri = hostUri; webSocket = new ClientWebSocket(); SecurityProtocolType securityProtocolType = SecurityProtocolType.Tls13; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | securityProtocolType; } public async Task ConnectAsync() { await ConnectToProvidedUri(Uri); if (this.SocketOpened != null) { this.SocketOpened(); } Task.Run((Func<Task?>)PollingLoop); Task.Run((Func<Task?>)SendLoop); } private async Task ConnectToProvidedUri(Uri uri) { if (uri.Scheme != "unspecified") { try { await webSocket.ConnectAsync(uri, CancellationToken.None); return; } catch (Exception e) { OnError(e); throw; } } List<Exception> errors = new List<Exception>(0); try { await webSocket.ConnectAsync(uri.AsWss(), CancellationToken.None); if (webSocket.State == WebSocketState.Open) { return; } } catch (Exception item) { errors.Add(item); webSocket = new ClientWebSocket(); } try { await webSocket.ConnectAsync(uri.AsWs(), CancellationToken.None); } catch (Exception item2) { errors.Add(item2); OnError(new AggregateException(errors)); throw; } } private async Task PollingLoop() { byte[] buffer = new byte[1024]; while (webSocket.State == WebSocketState.Open) { string message = null; try { message = await ReadMessageAsync(buffer); } catch (Exception e) { OnError(e); } OnMessageReceived(message); } } private async Task SendLoop() { while (webSocket.State == WebSocketState.Open) { try { await HandleSendBuffer(); } catch (Exception e) { OnError(e); } } } private async Task<string> ReadMessageAsync(byte[] buffer) { StringBuilder stringResult = new StringBuilder(); WebSocketReceiveResult result; do { result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { try { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } catch { } OnSocketClosed(); } else { stringResult.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); } } while (!result.EndOfMessage); return stringResult.ToString(); } public async Task DisconnectAsync() { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closure requested by client", CancellationToken.None); OnSocketClosed(); } public void SendPacket(ArchipelagoPacketBase packet) { SendMultiplePackets(new List<ArchipelagoPacketBase> { packet }); } public void SendMultiplePackets(List<ArchipelagoPacketBase> packets) { SendMultiplePackets(packets.ToArray()); } public void SendMultiplePackets(params ArchipelagoPacketBase[] packets) { SendMultiplePacketsAsync(packets).Wait(); } public Task SendPacketAsync(ArchipelagoPacketBase packet) { return SendMultiplePacketsAsync(new List<ArchipelagoPacketBase> { packet }); } public Task SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets) { return SendMultiplePacketsAsync(packets.ToArray()); } public Task SendMultiplePacketsAsync(params ArchipelagoPacketBase[] packets) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); foreach (ArchipelagoPacketBase item in packets) { sendQueue.Add(new Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>(item, taskCompletionSource)); } return taskCompletionSource.Task; } private async Task HandleSendBuffer() { List<ArchipelagoPacketBase> list = new List<ArchipelagoPacketBase>(); List<TaskCompletionSource<bool>> tasks = new List<TaskCompletionSource<bool>>(); Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>> tuple = sendQueue.Take(); list.Add(tuple.Item1); tasks.Add(tuple.Item2); Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>> item; while (sendQueue.TryTake(out item)) { list.Add(item.Item1); tasks.Add(item.Item2); } if (!list.Any()) { return; } if (webSocket.State != WebSocketState.Open) { throw new ArchipelagoSocketClosedException(); } ArchipelagoPacketBase[] packets = list.ToArray(); string s = JsonConvert.SerializeObject((object)packets); byte[] messageBuffer = Encoding.UTF8.GetBytes(s); int messagesCount = (int)Math.Ceiling((double)messageBuffer.Length / 1024.0); for (int i = 0; i < messagesCount; i++) { int num = 1024 * i; int num2 = 1024; bool endOfMessage = i + 1 == messagesCount; if (num2 * (i + 1) > messageBuffer.Length) { num2 = messageBuffer.Length - num; } await webSocket.SendAsync(new ArraySegment<byte>(messageBuffer, num, num2), WebSocketMessageType.Text, endOfMessage, CancellationToken.None); } foreach (TaskCompletionSource<bool> item2 in tasks) { item2.TrySetResult(result: true); } OnPacketSend(packets); } private void OnPacketSend(ArchipelagoPacketBase[] packets) { try { if (this.PacketsSent != null) { this.PacketsSent(packets); } } catch (Exception e) { OnError(e); } } private void OnSocketClosed() { try { if (this.SocketClosed != null) { this.SocketClosed(""); } } catch (Exception e) { OnError(e); } } private void OnMessageReceived(string message) { try { if (string.IsNullOrEmpty(message) || this.PacketReceived == null) { return; } List<ArchipelagoPacketBase> list = JsonConvert.DeserializeObject<List<ArchipelagoPacketBase>>(message, (JsonConverter[])(object)new JsonConverter[1] { Converter }); if (list == null) { return; } foreach (ArchipelagoPacketBase item in list) { this.PacketReceived(item); } } catch (Exception e) { OnError(e); } } private void OnError(Exception e) { try { if (this.ErrorReceived != null) { this.ErrorReceived(e, e.Message); } } catch (Exception ex) { Console.Out.WriteLine("Error occured during reporting of errorOuter Errror: " + e.Message + " " + e.StackTrace + "Inner Errror: " + ex.Message + " " + ex.StackTrace); } } } public interface IConnectionInfoProvider { string Game { get; } int Team { get; } int Slot { get; } string[] Tags { get; } ItemsHandlingFlags ItemsHandlingFlags { get; } string Uuid { get; } void UpdateConnectionOptions(string[] tags); void UpdateConnectionOptions(ItemsHandlingFlags itemsHandlingFlags); void UpdateConnectionOptions(string[] tags, ItemsHandlingFlags itemsHandlingFlags); } public class ConnectionInfoHelper : IConnectionInfoProvider { private readonly IArchipelagoSocketHelper socket; public string Game { get; private set; } public int Team { get; private set; } public int Slot { get; private set; } public string[] Tags { get; internal set; } public ItemsHandlingFlags ItemsHandlingFlags { get; internal set; } public string Uuid { get; private set; } internal ConnectionInfoHelper(IArchipelagoSocketHelper socket) { this.socket = socket; Reset(); socket.PacketReceived += PacketReceived; } private void PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket)) { if (packet is ConnectionRefusedPacket) { Reset(); } } else { Team = connectedPacket.Team; Slot = connectedPacket.Slot; } } internal void SetConnectionParameters(string game, string[] tags, ItemsHandlingFlags itemsHandlingFlags, string uuid) { Game = game; Tags = tags ?? new string[0]; ItemsHandlingFlags = itemsHandlingFlags; Uuid = uuid ?? Guid.NewGuid().ToString(); } private void Reset() { Game = null; Team = -1; Slot = -1; Tags = new string[0]; ItemsHandlingFlags = ItemsHandlingFlags.NoItems; Uuid = null; } public void UpdateConnectionOptions(string[] tags) { UpdateConnectionOptions(tags, ItemsHandlingFlags); } public void UpdateConnectionOptions(ItemsHandlingFlags itemsHandlingFlags) { UpdateConnectionOptions(Tags, ItemsHandlingFlags); } public void UpdateConnectionOptions(string[] tags, ItemsHandlingFlags itemsHandlingFlags) { SetConnectionParameters(Game, tags, itemsHandlingFlags, Uuid); socket.SendPacket(new ConnectUpdatePacket { Tags = Tags, ItemsHandling = ItemsHandlingFlags }); } } public interface IDataStorageHelper : IDataStorageWrapper { DataStorageElement this[Scope scope, string key] { get; set; } DataStorageElement this[string key] { get; set; } } public class DataStorageHelper : IDataStorageHelper, IDataStorageWrapper { public delegate void DataStorageUpdatedHandler(JToken originalValue, JToken newValue, Dictionary<string, JToken> additionalArguments); private readonly Dictionary<string, DataStorageUpdatedHandler> onValueChangedEventHandlers = new Dictionary<string, DataStorageUpdatedHandler>(); private readonly Dictionary<Guid, DataStorageUpdatedHandler> operationSpecificCallbacks = new Dictionary<Guid, DataStorageUpdatedHandler>(); private readonly Dictionary<string, TaskCompletionSource<JToken>> asyncRetrievalTasks = new Dictionary<string, TaskCompletionSource<JToken>>(); private readonly IArchipelagoSocketHelper socket; private readonly IConnectionInfoProvider connectionInfoProvider; public DataStorageElement this[Scope scope, string key] { get { return this[AddScope(scope, key)]; } set { this[AddScope(scope, key)] = value; } } public DataStorageElement this[string key] { get { return new DataStorageElement(GetContextForKey(key)); } set { SetValue(key, value); } } internal DataStorageHelper(IArchipelagoSocketHelper socket, IConnectionInfoProvider connectionInfoProvider) { this.socket = socket; this.connectionInfoProvider = connectionInfoProvider; socket.PacketReceived += OnPacketReceived; } private void OnPacketReceived(ArchipelagoPacketBase packet) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Invalid comparison between Unknown and I4 if (!(packet is RetrievedPacket retrievedPacket)) { if (packet is SetReplyPacket setReplyPacket) { if (setReplyPacket.AdditionalArguments != null && setReplyPacket.AdditionalArguments.ContainsKey("Reference") && (int)setReplyPacket.AdditionalArguments["Reference"].Type == 15 && operationSpecificCallbacks.TryGetValue((Guid)setReplyPacket.AdditionalArguments["Reference"], out var value)) { value(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments); operationSpecificCallbacks.Remove((Guid)setReplyPacket.AdditionalArguments["Reference"]); } if (onValueChangedEventHandlers.TryGetValue(setReplyPacket.Key, out var value2)) { value2(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments); } } return; } foreach (KeyValuePair<string, JToken> datum in retrievedPacket.Data) { if (asyncRetrievalTasks.TryGetValue(datum.Key, out var value3)) { value3.TrySetResult(datum.Value); asyncRetrievalTasks.Remove(datum.Key); } } } private Task<JToken> GetAsync(string key) { if (asyncRetrievalTasks.TryGetValue(key, out var value)) { return value.Task; } TaskCompletionSource<JToken> taskCompletionSource = new TaskCompletionSource<JToken>(); asyncRetrievalTasks[key] = taskCompletionSource; socket.SendPacketAsync(new GetPacket { Keys = new string[1] { key } }); return taskCompletionSource.Task; } private void Initialize(string key, JToken value) { socket.SendPacketAsync(new SetPacket { Key = key, DefaultValue = value, Operations = new OperationSpecification[1] { new OperationSpecification { OperationType = OperationType.Default } } }); } private JToken GetValue(string key) { Task<JToken> async = GetAsync(key); if (!async.Wait(TimeSpan.FromSeconds(2.0))) { throw new TimeoutException("Timed out retrieving data for key `" + key + "`. This may be due to an attempt to retrieve a value from the DataStorageHelper in a synchronous fashion from within a PacketReceived handler. When using the DataStorageHelper from within code which runs on the websocket thread then use the asynchronous getters. Ex: `DataStorageHelper[\"" + key + "\"].GetAsync().ContinueWith(x => {});`Be aware that DataStorageHelper calls tend to cause packet responses, so making a call from within a PacketReceived handler may cause an infinite loop."); } return async.Result; } private void SetValue(string key, DataStorageElement e) { if (key.StartsWith("_read_")) { throw new InvalidOperationException("DataStorage write operation on readonly key '" + key + "' is not allowed"); } if (e == null) { e = new DataStorageElement(OperationType.Replace, (JToken)(object)JValue.CreateNull()); } if (e.Context == null) { e.Context = GetContextForKey(key); } else if (e.Context.Key != key) { e.Operations.Insert(0, new OperationSpecification { OperationType = OperationType.Replace, Value = GetValue(e.Context.Key) }); } Dictionary<string, JToken> dictionary = e.AdditionalArguments ?? new Dictionary<string, JToken>(0); if (e.Callbacks != null) { Guid guid = Guid.NewGuid(); operationSpecificCallbacks[guid] = e.Callbacks; dictionary["Reference"] = JToken.FromObject((object)guid); socket.SendPacketAsync(new SetPacket { Key = key, Operations = e.Operations.ToArray(), WantReply = true, AdditionalArguments = dictionary }); } else { socket.SendPacketAsync(new SetPacket { Key = key, Operations = e.Operations.ToArray(), AdditionalArguments = dictionary }); } } private DataStorageElementContext GetContextForKey(string key) { return new DataStorageElementContext { Key = key, GetData = GetValue, GetAsync = GetAsync, Initialize = Initialize, AddHandler = AddHandler, RemoveHandler = RemoveHandler }; } private void AddHandler(string key, DataStorageUpdatedHandler handler) { if (onValueChangedEventHandlers.ContainsKey(key)) { Dictionary<string, DataStorageUpdatedHandler> dictionary = onValueChangedEventHandlers; dictionary[key] = (DataStorageUpdatedHandler)Delegate.Combine(dictionary[key], handler); } else { onValueChangedEventHandlers[key] = handler; } socket.SendPacketAsync(new SetNotifyPacket { Keys = new string[1] { key } }); } private void RemoveHandler(string key, DataStorageUpdatedHandler handler) { if (onValueChangedEventHandlers.ContainsKey(key)) { Dictionary<string, DataStorageUpdatedHandler> dictionary = onValueChangedEventHandlers; dictionary[key] = (DataStorageUpdatedHandler)Delegate.Remove(dictionary[key], handler); if (onValueChangedEventHandlers[key] == null) { onValueChangedEventHandlers.Remove(key); } } } private string AddScope(Scope scope, string key) { return scope switch { Scope.Global => key, Scope.Game => $"{scope}:{connectionInfoProvider.Game}:{key}", Scope.Team => $"{scope}:{connectionInfoProvider.Team}:{key}", Scope.Slot => $"{scope}:{connectionInfoProvider.Slot}:{key}", Scope.ReadOnly => "_read_" + key, _ => throw new ArgumentOutOfRangeException("scope", scope, "Invalid scope for key " + key), }; } private DataStorageElement GetHintsElement(int? slot = null, int? team = null) { return this[Scope.ReadOnly, $"hints_{team ?? connectionInfoProvider.Team}_{slot ?? connectionInfoProvider.Slot}"]; } private DataStorageElement GetSlotDataElement(int? slot = null) { return this[Scope.ReadOnly, $"slot_data_{slot ?? connectionInfoProvider.Slot}"]; } private DataStorageElement GetItemNameGroupsElement(string game = null) { return this[Scope.ReadOnly, "item_name_groups_" + (game ?? connectionInfoProvider.Game)]; } private DataStorageElement GetLocationNameGroupsElement(string game = null) { return this[Scope.ReadOnly, "location_name_groups_" + (game ?? connectionInfoProvider.Game)]; } private DataStorageElement GetClientStatusElement(int? slot = null, int? team = null) { return this[Scope.ReadOnly, $"client_status_{team ?? connectionInfoProvider.Team}_{slot ?? connectionInfoProvider.Slot}"]; } public Hint[] GetHints(int? slot = null, int? team = null) { return GetHintsElement(slot, team).To<Hint[]>(); } public Task<Hint[]> GetHintsAsync(int? slot = null, int? team = null) { return GetHintsElement(slot, team).GetAsync<Hint[]>(); } public void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null) { GetHintsElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onHintsUpdated(newValue.ToObject<Hint[]>()); }; if (retrieveCurrentlyUnlockedHints) { GetHintsAsync(slot, team).ContinueWith(delegate(Task<Hint[]> t) { onHintsUpdated(t.Result); }); } } public Dictionary<string, object> GetSlotData(int? slot = null) { return GetSlotDataElement(slot).To<Dictionary<string, object>>(); } public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null) { return GetSlotDataElement(slot).GetAsync<Dictionary<string, object>>(); } public Dictionary<string, string[]> GetItemNameGroups(string game = null) { return GetItemNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public Task<Dictionary<string, string[]>> GetItemNameGroupsAsync(string game = null) { return GetItemNameGroupsElement(game).GetAsync<Dictionary<string, string[]>>(); } public Dictionary<string, string[]> GetLocationNameGroups(string game = null) { return GetLocationNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public Task<Dictionary<string, string[]>> GetLocationNameGroupsAsync(string game = null) { return GetLocationNameGroupsElement(game).GetAsync<Dictionary<string, string[]>>(); } public ArchipelagoClientState GetClientStatus(int? slot = null, int? team = null) { return GetClientStatusElement(slot, team).To<ArchipelagoClientState?>().GetValueOrDefault(); } public Task<ArchipelagoClientState> GetClientStatusAsync(int? slot = null, int? team = null) { return GetClientStatusElement(slot, team).GetAsync<ArchipelagoClientState?>().ContinueWith((Task<ArchipelagoClientState?> r) => r.Result.GetValueOrDefault()); } public void TrackClientStatus(Action<ArchipelagoClientState> onStatusUpdated, bool retrieveCurrentClientStatus = true, int? slot = null, int? team = null) { GetClientStatusElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onStatusUpdated(newValue.ToObject<ArchipelagoClientState>()); }; if (retrieveCurrentClientStatus) { GetClientStatusAsync(slot, team).ContinueWith(delegate(Task<ArchipelagoClientState> t) { onStatusUpdated(t.Result); }); } } } public interface IDataStorageWrapper { Hint[] GetHints(int? slot = null, int? team = null); Task<Hint[]> GetHintsAsync(int? slot = null, int? team = null); void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null); Dictionary<string, object> GetSlotData(int? slot = null); Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null); Dictionary<string, string[]> GetItemNameGroups(string game = null); Task<Dictionary<string, string[]>> GetItemNameGroupsAsync(string game = null); Dictionary<string, string[]> GetLocationNameGroups(string game = null); Task<Dictionary<string, string[]>> GetLocationNameGroupsAsync(string game = null); ArchipelagoClientState GetClientStatus(int? slot = null, int? team = null); Task<ArchipelagoClientState> GetClientStatusAsync(int? slot = null, int? team = null); void TrackClientStatus(Action<ArchipelagoClientState> onStatusUpdated, bool retrieveCurrentClientStatus = true, int? slot = null, int? team = null); } public class ArchipelagoSocketHelperDelagates { public delegate void PacketReceivedHandler(ArchipelagoPacketBase packet); public delegate void PacketsSentHandler(ArchipelagoPacketBase[] packets); public delegate void ErrorReceivedHandler(Exception e, string message); public delegate void SocketClosedHandler(string reason); public delegate void SocketOpenedHandler(); } public interface IArchipelagoSocketHelper { Uri Uri { get; } bool Connected { get; } event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived; event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent; event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived; event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed; event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened; void SendPacket(ArchipelagoPacketBase packet); void SendMultiplePackets(List<ArchipelagoPacketBase> packets); void SendMultiplePackets(params ArchipelagoPacketBase[] packets); Task ConnectAsync(); Task DisconnectAsync(); Task SendPacketAsync(ArchipelagoPacketBase packet); Task SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets); Task SendMultiplePacketsAsync(params ArchipelagoPacketBase[] packets); } public interface ILocationCheckHelper { ReadOnlyCollection<long> AllLocations { get; } ReadOnlyCollection<long> AllLocationsChecked { get; } ReadOnlyCollection<long> AllMissingLocations { get; } event LocationCheckHelper.CheckedLocationsUpdatedHandler CheckedLocationsUpdated; void CompleteLocationChecks(params long[] ids); Task CompleteLocationChecksAsync(params long[] ids); Task<Dictionary<long, ScoutedItemInfo>> ScoutLocationsAsync(HintCreationPolicy hintCreationPolicy, params long[] ids); Task<Dictionary<long, ScoutedItemInfo>> ScoutLocationsAsync(bool createAsHint, params long[] ids); Task<Dictionary<long, ScoutedItemInfo>> ScoutLocationsAsync(params long[] ids); long GetLocationIdFromName(string game, string locationName); string GetLocationNameFromId(long locationId, string game = null); } public class LocationCheckHelper : ILocationCheckHelper { public delegate void CheckedLocationsUpdatedHandler(ReadOnlyCollection<long> newCheckedLocations); private readonly IConcurrentHashSet<long> allLocations = new ConcurrentHashSet<long>(); private readonly IConcurrentHashSet<long> locationsChecked = new ConcurrentHashSet<long>(); private readonly IConcurrentHashSet<long> serverConfirmedChecks = new ConcurrentHashSet<long>(); private ReadOnlyCollection<long> missingLocations = new ReadOnlyCollection<long>(new long[0]); private readonly IArchipelagoSocketHelper socket; private readonly IItemInfoResolver itemInfoResolver; private readonly IConnectionInfoProvider connectionInfoProvider; private readonly IPlayerHelper players; private bool awaitingLocationInfoPacket; private TaskCompletionSource<Dictionary<long, ScoutedItemInfo>> locationInfoPacketCallbackTask; public ReadOnlyCollection<long> AllLocations => allLocations.AsToReadOnlyCollection(); public ReadOnlyCollection<long> AllLocationsChecked => locationsChecked.AsToReadOnlyCollection(); public ReadOnlyCollection<long> AllMissingLocations => missingLocations; public event CheckedLocationsUpdatedHandler CheckedLocationsUpdated; internal LocationCheckHelper(IArchipelagoSocketHelper socket, IItemInfoResolver itemInfoResolver, IConnectionInfoProvider connectionInfoProvider, IPlayerHelper players) { this.socket = socket; this.itemInfoResolver = itemInfoResolver; this.connectionInfoProvider = connectionInfoProvider; this.players = players; socket.PacketReceived += Socket_PacketReceived; } private void Socket_PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket)) { if (!(packet is RoomUpdatePacket roomUpdatePacket)) { if (!(packet is LocationInfoPacket locationInfoPacket)) { if (packet is InvalidPacketPacket invalidPacketPacket && awaitingLocationInfoPacket && invalidPacketPacket.OriginalCmd == ArchipelagoPacketType.LocationScouts) { locationInfoPacketCallbackTask.TrySetException(new ArchipelagoServerRejectedPacketException(invalidPacketPacket.OriginalCmd, invalidP
ArchipelagoULTRAKILL.dll
Decompiled 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using Archipelago.MultiClient.Net; using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using ArchipelagoULTRAKILL.Commands; using ArchipelagoULTRAKILL.Components; using ArchipelagoULTRAKILL.Powerups; using ArchipelagoULTRAKILL.Properties; using ArchipelagoULTRAKILL.Structures; using BepInEx; using BepInEx.Logging; using GameConsole; using HarmonyLib; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PluginConfig.API; using PluginConfig.API.Decorators; using PluginConfig.API.Fields; using PluginConfig.API.Functionals; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; using plog; using plog.Models; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ArchipelagoULTRAKILL")] [assembly: AssemblyDescription("Connect to an Archipelago server to play ULTRAKILL randomizer.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ArchipelagoULTRAKILL")] [assembly: AssemblyCopyright("Copyright © TRPG 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("c7de03cb-cf51-44da-ba1f-6fcecd638e0a")] [assembly: AssemblyFileVersion("2.2.2")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("2.2.2.0")] namespace ArchipelagoULTRAKILL { public static class AudioManager { private static readonly Dictionary<string, string> multiMusicBattle = new Dictionary<string, string> { ["1"] = "Assets/Music/0-1.wav", ["2"] = "Assets/Music/0-2.wav", ["3"] = "Assets/Music/0-1.wav", ["4"] = "Assets/Music/0-2.wav", ["6B"] = "Assets/Music/1-1.wav", ["7B"] = "Assets/Music/1-2 Noise Battle.wav", ["8"] = "Assets/Music/1-3.wav", ["10"] = "Assets/Music/2-1.wav", ["11"] = "Assets/Music/2-2.wav", ["12"] = "Assets/Music/2-3.wav", ["14A"] = "Assets/Music/3-1 Guts.wav", ["14B"] = "Assets/Music/3-1 Glory.wav", ["16"] = "Assets/Music/4-1.wav", ["17"] = "Assets/Music/4-2.wav", ["18A"] = "Assets/Music/4-3 Phase 1.wav", ["18B"] = "Assets/Music/4-3 Phase 2.wav", ["18C"] = "Assets/Music/4-3 Phase 3.wav", ["20"] = "Assets/Music/5-1.wav", ["22A"] = "Assets/Music/5-3.wav", ["22B"] = "Assets/Music/5-3 Aftermath.wav", ["24A"] = "Assets/Music/6-1.wav", ["26B"] = "Assets/Music/7-1.wav", ["27A"] = "Assets/Music/7-2 Intro Battle.wav", ["27B"] = "Assets/Music/7-2.wav", ["28B"] = "Assets/Music/7-3.wav", ["667A"] = "Assets/Music/P-2.wav" }; private static readonly Dictionary<string, string> multiMusicClean = new Dictionary<string, string> { ["1"] = "Assets/Music/0-1 Clean.wav", ["2"] = "Assets/Music/0-2 Clean.wav", ["3"] = "Assets/Music/0-1 Clean.wav", ["4"] = "Assets/Music/0-2 Clean.wav", ["6B"] = "Assets/Music/1-1 Clean.wav", ["7B"] = "Assets/Music/1-2 Noise Clean.wav", ["8"] = "Assets/Music/1-3 Clean.wav", ["10"] = "Assets/Music/2-1 Clean.wav", ["11"] = "Assets/Music/2-2 Clean.wav", ["12"] = "Assets/Music/2-3 Clean.wav", ["14A"] = "Assets/Music/3-1 Guts Clean.wav", ["14B"] = "Assets/Music/3-1 Glory Clean.wav", ["16"] = "Assets/Music/4-1 Clean.wav", ["17"] = "Assets/Music/4-2 Clean.wav", ["18A"] = "Assets/Music/4-3 Phase 1 Clean.wav", ["18B"] = "Assets/Music/4-3 Phase 2 Clean.wav", ["18C"] = "Assets/Music/4-3 Phase 3.wav", ["20"] = "Assets/Music/5-1 Clean.wav", ["22A"] = "Assets/Music/5-3 Clean.wav", ["22B"] = "Assets/Music/5-3 Aftermath Clean.wav", ["24A"] = "Assets/Music/6-1 Clean.wav", ["26B"] = "Assets/Music/7-1 Clean.wav", ["27A"] = "Assets/Music/7-2 Intro Clean.wav", ["27B"] = "Assets/Music/7-2 Clean.wav", ["28B"] = "Assets/Music/7-3 Clean.wav", ["667A"] = "Assets/Music/P-2 Clean.wav" }; private static readonly Dictionary<string, string> singleMusic = new Dictionary<string, string> { ["5"] = "Assets/Music/Bosses/Cerberus A.mp3", ["6A"] = "Assets/Music/Misc/A Thousand Greetings.wav", ["7A"] = "Assets/Music/Misc/A Thousand Greetings.wav", ["9A"] = "Assets/Music/Misc/Clair_de_lune_(Claude_Debussy)_Suite_bergamasque (CREATIVE COMMONS).ogg", ["9B"] = "Assets/Music/Bosses/V2 1-4.wav", ["13"] = "Assets/Music/Bosses/Minos Corpse B.wav", ["15A"] = "Assets/Music/Bosses/Gabriel 3-2 Intro.wav", ["15B"] = "Assets/Music/Bosses/Gabriel 3-2.wav", ["18D"] = "Assets/Music/Misc/themeofcancer.wav", ["19"] = "Assets/Music/Bosses/V2 4-4.wav", ["24B"] = "Assets/Music/6-1 Hall of Sacreligious Remains.wav", ["25A"] = "Assets/Music/Bosses/Gabriel 6-2 Intro B.wav", ["25B"] = "Assets/Music/Bosses/Gabriel 6-2.wav", ["26A"] = "Assets/Music/7-1 Intro.wav", ["26C"] = "Assets/Music/Misc/themeofcancer.wav", ["26D"] = "Assets/Music/Bosses/Minotaur A.wav", ["26E"] = "Assets/Music/Bosses/Minotaur B.wav", ["28A"] = "Assets/Music/7-3 Intro Clean.wav", ["666A"] = "Assets/Music/Bosses/Flesh Prison.wav", ["666B"] = "Assets/Music/Bosses/Minos Prime.wav", ["667B"] = "Assets/Music/Bosses/Flesh panopticon.wav", ["667C"] = "Assets/Music/Bosses/Sisyphus Prime.wav" }; public static AudioClip LoadNewSingleTrack(AudioClip source, string id) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (singleMusic.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)singleMusic[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + singleMusic[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static AudioClip LoadNewCleanTrack(AudioClip source, string id) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (multiMusicClean.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)multiMusicClean[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + multiMusicClean[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static AudioClip LoadNewBattleTrack(AudioClip source, string id) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (multiMusicBattle.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)multiMusicBattle[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + multiMusicBattle[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static void LoadMusicManagerTracks(string id, bool single = false) { if (single) { MonoSingleton<MusicManager>.Instance.cleanTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.cleanTheme.clip, id); MonoSingleton<MusicManager>.Instance.battleTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.battleTheme.clip, id); MonoSingleton<MusicManager>.Instance.bossTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.bossTheme.clip, id); } else { MonoSingleton<MusicManager>.Instance.cleanTheme.clip = LoadNewCleanTrack(MonoSingleton<MusicManager>.Instance.cleanTheme.clip, id); MonoSingleton<MusicManager>.Instance.battleTheme.clip = LoadNewBattleTrack(MonoSingleton<MusicManager>.Instance.battleTheme.clip, id); MonoSingleton<MusicManager>.Instance.bossTheme.clip = LoadNewBattleTrack(MonoSingleton<MusicManager>.Instance.bossTheme.clip, id); } } public static void ChangeMusic() { if (Core.CurrentLevelInfo.Music == MusicType.Normal) { LoadMusicManagerTracks(Core.CurrentLevelInfo.Id.ToString()); } else { switch (SceneHelper.CurrentScene) { default: return; case "Level 0-5": foreach (AudioSource item in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if ((Object)(object)((Component)item).transform.parent != (Object)null && (((Object)((Component)item).transform.parent).name == "4 Contents" || ((Object)((Component)item).transform.parent).name == "4 Contents(Clone)") && ((Object)((Component)item).transform).name == "Music") { item.clip = LoadNewSingleTrack(item.clip, "5"); ((Component)((Component)item).transform.parent.Find("Enemies").Find("StatueEnemy (1)")).GetComponent<SoundChanger>().newSound = LoadNewSingleTrack(item.clip, "5"); } } break; case "Level 1-1": LoadMusicManagerTracks("6A", single: true); foreach (MusicChanger item2 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item2).gameObject).name == "MusicChanger") { item2.clean = LoadNewCleanTrack(item2.clean, "6B"); item2.battle = LoadNewBattleTrack(item2.battle, "6B"); } } break; case "Level 1-2": LoadMusicManagerTracks("7A", single: true); foreach (MusicChanger item3 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item3).gameObject).name == "MusicActivator") { item3.clean = LoadNewCleanTrack(item3.clean, "7B"); item3.battle = LoadNewBattleTrack(item3.battle, "7B"); } } break; case "Level 1-4": foreach (AudioSource item4 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item4).gameObject).name == "Music - Clair de Lune") { item4.clip = LoadNewSingleTrack(item4.clip, "9A"); } else if (((Object)((Component)item4).gameObject).name == "Music - Versus") { item4.clip = LoadNewSingleTrack(item4.clip, "9B"); } } break; case "Level 2-1": foreach (MusicChanger item5 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item5).gameObject).name == "Cube (1)") { item5.clean = LoadNewCleanTrack(item5.clean, "10"); item5.battle = LoadNewBattleTrack(item5.battle, "10"); } } break; case "Level 2-4": foreach (AudioSource item6 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item6).gameObject).name == "BossMusic") { item6.clip = LoadNewSingleTrack(item6.clip, "13"); } } break; case "Level 3-1": LoadMusicManagerTracks("14A"); foreach (MusicChanger item7 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item7).gameObject).name == "MusicChanger") { item7.clean = LoadNewCleanTrack(item7.clean, "14B"); item7.battle = LoadNewBattleTrack(item7.battle, "14B"); } } break; case "Level 3-2": foreach (AudioSource item8 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item8).gameObject).name == "Music 2") { item8.clip = LoadNewSingleTrack(item8.clip, "15A"); } else if (((Object)((Component)item8).gameObject).name == "Music 3") { item8.clip = LoadNewSingleTrack(item8.clip, "15B"); } } break; case "Level 4-3": foreach (MusicChanger item9 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item9).gameObject).name == "OnLight") { item9.clean = LoadNewCleanTrack(item9.clean, "18A"); item9.battle = LoadNewBattleTrack(item9.battle, "18A"); } else if (((Object)((Component)item9).gameObject).name == "Music Changer") { item9.clean = LoadNewCleanTrack(item9.clean, "18B"); item9.battle = LoadNewBattleTrack(item9.battle, "18B"); } else if (((Object)((Component)item9).gameObject).name == "Music Changer (Normal)") { item9.clean = LoadNewCleanTrack(item9.clean, "18B"); item9.battle = LoadNewBattleTrack(item9.battle, "18B"); } else if (((Object)((Component)item9).gameObject).name == "Music") { item9.clean = LoadNewCleanTrack(item9.clean, "18C"); item9.battle = LoadNewBattleTrack(item9.battle, "18C"); } else if (((Object)((Component)item9).gameObject).name == "Trigger (Fight)") { item9.clean = LoadNewSingleTrack(item9.clean, "18D"); item9.battle = LoadNewSingleTrack(item9.battle, "18D"); item9.boss = LoadNewSingleTrack(item9.boss, "18D"); } } break; case "Level 4-4": foreach (AudioSource item10 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item10).gameObject).name == "Versus 2") { item10.clip = LoadNewSingleTrack(item10.clip, "19"); } } break; case "Level 5-3": LoadMusicManagerTracks("22A"); foreach (MusicChanger item11 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item11).gameObject).name == "InstantVer") { item11.clean = LoadNewCleanTrack(item11.clean, "22B"); item11.battle = LoadNewBattleTrack(item11.battle, "22B"); } else if (((Object)((Component)item11).gameObject).name == "NormalVer") { item11.clean = LoadNewCleanTrack(item11.clean, "22B"); item11.battle = LoadNewBattleTrack(item11.battle, "22B"); } } break; case "Level 6-1": foreach (MusicChanger item12 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item12).gameObject).name == "MusicChanger") { item12.clean = LoadNewCleanTrack(item12.clean, "24A"); item12.battle = LoadNewBattleTrack(item12.battle, "24A"); } } foreach (AudioSource item13 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item13).gameObject).name == "ClimaxMusic") { item13.clip = LoadNewSingleTrack(item13.clip, "24B"); } } break; case "Level 6-2": foreach (AudioSource item14 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item14).gameObject).name == "Organ") { item14.clip = LoadNewSingleTrack(item14.clip, "25A"); } else if (((Object)((Component)item14).gameObject).name == "BossMusic") { item14.clip = LoadNewSingleTrack(item14.clip, "25B"); } } break; case "Level 7-1": foreach (MusicChanger item15 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item15).name == "LevelMusicStart") { item15.clean = LoadNewCleanTrack(item15.clean, "26B"); item15.battle = LoadNewBattleTrack(item15.battle, "26B"); item15.boss = LoadNewBattleTrack(item15.battle, "26B"); } } foreach (AudioSource item16 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)item16).name == "IntroMusic") { item16.clip = LoadNewSingleTrack(item16.clip, "26A"); } else if (((Object)item16).name == "BigJohnatronMusic") { item16.clip = LoadNewSingleTrack(item16.clip, "26C"); } else if (((Object)item16).name == "MinotaurPhase1Music") { item16.clip = LoadNewSingleTrack(item16.clip, "26D"); } else if (((Object)item16).name == "MinotaurPhase2Music") { item16.clip = LoadNewSingleTrack(item16.clip, "26E"); } } break; case "Level 7-2": LoadMusicManagerTracks("27A"); foreach (MusicChanger item17 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item17).name == "MusicActivator") { item17.clean = LoadNewCleanTrack(item17.clean, "27B"); item17.battle = LoadNewBattleTrack(item17.battle, "27B"); item17.boss = LoadNewBattleTrack(item17.battle, "27B"); } } break; case "Level 7-3": LoadMusicManagerTracks("28A", single: true); foreach (MusicChanger item18 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item18).name == "SecondTrackStart") { item18.clean = LoadNewCleanTrack(item18.clean, "28B"); item18.battle = LoadNewBattleTrack(item18.battle, "28B"); item18.boss = LoadNewBattleTrack(item18.battle, "28B"); } } break; case "Level P-1": foreach (AudioSource item19 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item19).gameObject).name == "Chaos") { item19.clip = LoadNewSingleTrack(item19.clip, "666A"); } else if (((Object)((Component)item19).gameObject).name == "Music 3") { item19.clip = LoadNewSingleTrack(item19.clip, "666B"); } } break; case "Level P-2": foreach (MusicChanger item20 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item20).gameObject).name == "DelayedMusicActivator") { item20.clean = LoadNewCleanTrack(item20.clean, "667A"); item20.battle = LoadNewBattleTrack(item20.battle, "667A"); item20.boss = LoadNewBattleTrack(item20.battle, "667A"); } } foreach (AudioSource item21 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item21).gameObject).name == "FleshPrison") { item21.clip = LoadNewSingleTrack(item21.clip, "667B"); } else if (((Object)((Component)item21).gameObject).name == "Sisyphus") { item21.clip = LoadNewSingleTrack(item21.clip, "667C"); } } break; } } Core.Logger.LogInfo((object)"Music changed successfully."); } } public static class ColorRandomizer { public static void RandomizeGunColors() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 2; j++) { if (j != 2 || (i != 4 && i != 5)) { bool flag = false; if (j == 2) { flag = true; } for (int k = 1; k <= 3; k++) { MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "r" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "g" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "b" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "a" }), Random.Range(0f, 1f)); } } } } if (Core.IsPlaying) { MonoSingleton<GunColorController>.Instance.UpdateGunColors(); GunColorTypeGetter[] array = Object.FindObjectsOfType<GunColorTypeGetter>(); foreach (GunColorTypeGetter val in array) { val.UpdatePreview(); } } } public static void RandomizeUIColors() { for (int i = 1; i <= 3; i++) { string text = ".r"; if (i == 2) { text = ".g"; } if (i == 3) { text = ".b"; } MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hp" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hptext" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hpaft" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hphdmg" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hpover" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stm" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stmchr" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stmemp" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.raifull" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.raicha" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var0" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var1" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var2" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var3" + text, Random.Range(0f, 1f)); } if (Core.IsPlaying) { MonoSingleton<ColorBlindSettings>.Instance.UpdateHudColors(); MonoSingleton<ColorBlindSettings>.Instance.UpdateWeaponColors(); } } } public static class ConfigManager { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static OnClick <>9__80_0; public static OnClick <>9__80_1; public static OnClick <>9__80_2; public static OnClick <>9__80_3; public static PostStringValueChangeEvent <>9__80_4; public static BoolValueChangeEventDelegate <>9__80_5; public static IntValueChangeEventDelegate <>9__80_6; public static IntValueChangeEventDelegate <>9__80_7; public static OnClick <>9__80_8; public static OnClick <>9__80_9; public static OnClick <>9__80_10; public static OnClick <>9__80_11; public static OnClick <>9__80_12; public static OnClick <>9__80_13; public static OnClick <>9__80_14; internal void <Initialize>b__80_0() { if (Multiworld.Authenticated) { connectionInfo.text = "Already connected to server."; } else if (SceneHelper.CurrentScene != "Main Menu") { connectionInfo.text = "Can only connect to an Archipelago server on the main menu."; } else if ((GameProgressSaver.GetTutorial() || GameProgressSaver.GetIntro()) && !Core.DataExists() && !hintMode.value) { connectionInfo.text = "No Archipelago data found. Start a new save file before connecting."; } else if (Core.DataExists() && hintMode.value) { connectionInfo.text = "Can't use hint mode on a save file that already has randomizer data."; } else if (!Multiworld.Authenticated) { Core.data.slot_name = playerName.value; Core.data.host_name = serverAddress.value; Core.data.password = serverPassword.value; if (Core.data.password == "") { Core.data.password = null; } if (hintMode.value) { Multiworld.ConnectBK(); } else { Multiworld.Connect(); } } } internal void <Initialize>b__80_1() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Authenticated) { Multiworld.Disconnect(); connectionInfo.text = "Disconnected from server."; if (SceneHelper.CurrentScene == "Main Menu") { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } } } internal void <Initialize>b__80_2() { if (Multiworld.Authenticated) { Core.data.deathLink = true; Multiworld.EnableDeathLink(); } } internal void <Initialize>b__80_3() { if (Multiworld.Authenticated) { Core.data.deathLink = false; Multiworld.DisableDeathLink(); } } internal void <Initialize>b__80_4(string value) { if (Multiworld.Authenticated) { if (value != "") { Multiworld.Session.Say(value); } chat.value = ""; } } internal void <Initialize>b__80_5(BoolValueChangeEvent e) { ((Component)UIManager.log).gameObject.SetActive(e.value); } internal void <Initialize>b__80_6(IntValueChangeEvent e) { UIManager.lines = e.value; while (Multiworld.messages.Count > e.value) { Multiworld.messages.RemoveAt(0); } } internal void <Initialize>b__80_7(IntValueChangeEvent e) { ((TMP_Text)UIManager.log).fontSize = e.value; } internal void <Initialize>b__80_8() { UIManager.SetLogText(""); Multiworld.messages.Clear(); } internal void <Initialize>b__80_9() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); } internal void <Initialize>b__80_10() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", false); } internal void <Initialize>b__80_11() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Invalid comparison between Unknown and I4 //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (!Multiworld.Authenticated) { return; } Object.Destroy((Object)(object)Traverse.Create((object)hintList).Field("panelObject").GetValue<GameObject>()); Traverse.Create((object)hintsPanel).Field("fieldObjects").GetValue<List<List<Transform>>>() .RemoveAt(2); Traverse.Create((object)hintsPanel).Field("fields").GetValue<List<ConfigField>>() .RemoveAt(2); hintList = null; hintList = new ConfigDivision(hintsPanel, "hintList"); Hint[] hints = ((IDataStorageWrapper)Multiworld.Session.DataStorage).GetHints((int?)null, (int?)null); Hint[] array = hints; foreach (Hint val in array) { if (!hintAdvancementOnly.value || (int)val.ItemFlags == 1) { if (Array.IndexOf(hints, val) != 0) { new ConfigHeader((ConfigPanel)(object)hintList, "-----", 24); } ((ConfigField)new StringField((ConfigPanel)(object)hintList, "ITEM", $"hint{Array.IndexOf(hints, val)}_item", Multiworld.Session.Items.GetItemName(val.ItemId, (string)null), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "RECEIVING PLAYER", $"hint{Array.IndexOf(hints, val)}_receiving_player", Multiworld.Session.Players.GetPlayerAlias(val.ReceivingPlayer), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "LOCATION", $"hint{Array.IndexOf(hints, val)}_location", Multiworld.Session.Locations.GetLocationNameFromId(val.LocationId, (string)null), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "SENDING PLAYER", $"hint{Array.IndexOf(hints, val)}_sending_player", Multiworld.Session.Players.GetPlayerAlias(val.FindingPlayer), true, false)).interactable = false; ((ConfigField)new BoolField((ConfigPanel)(object)hintList, "FOUND", $"hint{Array.IndexOf(hints, val)}_found", val.Found, false)).interactable = false; } } } internal void <Initialize>b__80_12() { Application.OpenURL("https://thunderstore.io/c/ultrakill/p/TRPG/Archipelago/"); } internal void <Initialize>b__80_13() { Application.OpenURL("https://github.com/TRPG0/ArchipelagoULTRAKILL"); } internal void <Initialize>b__80_14() { Application.OpenURL("https://discord.gg/Sbhy4ykUKn"); } } public static PluginConfigurator config; public static ConfigPanel playerPanel; public static BoolField isConnected; public static StringField playerName; public static StringField serverAddress; public static StringField serverPassword; public static BoolField hintMode; public static ButtonField connectButton; public static ButtonField disconnectButton; public static ConfigHeader connectionInfo; public static ButtonField deathLinkOnButton; public static ButtonField deathLinkOffButton; public static StringField chat; public static StringField goal; public static StringField goalProgress; public static StringField locationsChecked; public static EnumField<BossOptions> bossRewards; public static BoolField challengeRewards; public static BoolField pRankRewards; public static BoolField hankRewards; public static BoolField clashReward; public static BoolField fishRewards; public static BoolField cleanRewards; public static BoolField chessReward; public static BoolField rocketReward; public static BoolField randomizeFire2; public static EnumField<WeaponForm> revForm; public static EnumField<WeaponForm> shoForm; public static EnumField<WeaponForm> naiForm; public static BoolField randomizeSkulls; public static BoolField randomizeLimbo; public static BoolField randomizeViolence; public static BoolField musicRandomizer; public static BoolField cybergrindHints; public static BoolField deathLink; public static ConfigPanel logPanel; public static BoolField showLog; public static IntField logLines; public static IntField logFontSize; public static ButtonField logClear; public static ConfigPanel colorPanel; public static EnumField<ColorOptions> uiColorRandomizer; public static EnumField<ColorOptions> gunColorRandomizer; public static ButtonField enableCustomButton; public static ButtonField disableCustomButton; public static ColorField APPlayerSelf; public static ColorField APPlayerOther; public static ColorField APItemAdvancement; public static ColorField APItemNeverExclude; public static ColorField APItemFiller; public static ColorField APItemTrap; public static ColorField APLocation; public static ColorField layer0Color; public static ColorField layer1Color; public static ColorField layer2Color; public static ColorField layer3Color; public static ColorField layer4Color; public static ColorField layer5Color; public static ColorField layer6Color; public static ColorField layer7Color; public static ColorField primeColor; public static ColorField altColor; public static ColorField arm0Color; public static ColorField arm1Color; public static ColorField arm2Color; public static ColorField blueSkullColor; public static ColorField redSkullColor; public static ColorField switchColor; public static ColorField pointsColor; public static ColorField dualwieldColor; public static ColorField doublejumpColor; public static ColorField trapColor; public static ConfigPanel hintsPanel; public static BoolField hintAdvancementOnly; public static ButtonField hintRefresh; public static ConfigDivision hintList; public static ConfigPanel linksPanel; public static ButtonField thunderstoreButton; public static ButtonField githubButton; public static ButtonField discordButton; public static void Initialize() { //IL_005d: 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_0081: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //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_020a: Expected O, but got Unknown //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Expected O, but got Unknown //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Expected O, but got Unknown //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Expected O, but got Unknown //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Expected O, but got Unknown //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Expected O, but got Unknown //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Expected O, but got Unknown //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Expected O, but got Unknown //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Expected O, but got Unknown //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Expected O, but got Unknown //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Expected O, but got Unknown //IL_0511: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0523: Expected O, but got Unknown //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Expected O, but got Unknown //IL_0623: Unknown result type (might be due to invalid IL or missing references) //IL_0628: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Expected O, but got Unknown //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_0669: Unknown result type (might be due to invalid IL or missing references) //IL_066e: Unknown result type (might be due to invalid IL or missing references) //IL_067b: Expected O, but got Unknown //IL_068c: Unknown result type (might be due to invalid IL or missing references) //IL_0691: Unknown result type (might be due to invalid IL or missing references) //IL_069e: Expected O, but got Unknown //IL_06af: Unknown result type (might be due to invalid IL or missing references) //IL_06b4: Unknown result type (might be due to invalid IL or missing references) //IL_06c1: Expected O, but got Unknown //IL_06d2: Unknown result type (might be due to invalid IL or missing references) //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_06e4: Expected O, but got Unknown //IL_06f5: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Expected O, but got Unknown //IL_073e: Unknown result type (might be due to invalid IL or missing references) //IL_0748: Expected O, but got Unknown //IL_0718: Unknown result type (might be due to invalid IL or missing references) //IL_071d: Unknown result type (might be due to invalid IL or missing references) //IL_0723: Expected O, but got Unknown //IL_0788: Unknown result type (might be due to invalid IL or missing references) //IL_0792: Expected O, but got Unknown //IL_0761: Unknown result type (might be due to invalid IL or missing references) //IL_0766: Unknown result type (might be due to invalid IL or missing references) //IL_076c: Expected O, but got Unknown //IL_07cb: Unknown result type (might be due to invalid IL or missing references) //IL_07d5: Expected O, but got Unknown //IL_07ab: Unknown result type (might be due to invalid IL or missing references) //IL_07b0: Unknown result type (might be due to invalid IL or missing references) //IL_07b6: Expected O, but got Unknown //IL_08aa: Unknown result type (might be due to invalid IL or missing references) //IL_08b4: Expected O, but got Unknown //IL_07ee: Unknown result type (might be due to invalid IL or missing references) //IL_07f3: Unknown result type (might be due to invalid IL or missing references) //IL_07f9: Expected O, but got Unknown //IL_08ed: Unknown result type (might be due to invalid IL or missing references) //IL_08f7: Expected O, but got Unknown //IL_08cd: Unknown result type (might be due to invalid IL or missing references) //IL_08d2: Unknown result type (might be due to invalid IL or missing references) //IL_08d8: Expected O, but got Unknown //IL_092d: Unknown result type (might be due to invalid IL or missing references) //IL_0951: Unknown result type (might be due to invalid IL or missing references) //IL_0957: Unknown result type (might be due to invalid IL or missing references) //IL_0961: Expected O, but got Unknown //IL_097f: Unknown result type (might be due to invalid IL or missing references) //IL_0985: Unknown result type (might be due to invalid IL or missing references) //IL_098f: Expected O, but got Unknown //IL_09ad: Unknown result type (might be due to invalid IL or missing references) //IL_09b3: Unknown result type (might be due to invalid IL or missing references) //IL_09bd: Expected O, but got Unknown //IL_09db: Unknown result type (might be due to invalid IL or missing references) //IL_09e1: Unknown result type (might be due to invalid IL or missing references) //IL_09eb: Expected O, but got Unknown //IL_0a09: Unknown result type (might be due to invalid IL or missing references) //IL_0a0f: Unknown result type (might be due to invalid IL or missing references) //IL_0a19: Expected O, but got Unknown //IL_0a37: Unknown result type (might be due to invalid IL or missing references) //IL_0a3d: Unknown result type (might be due to invalid IL or missing references) //IL_0a47: Expected O, but got Unknown //IL_0a65: Unknown result type (might be due to invalid IL or missing references) //IL_0a6b: Unknown result type (might be due to invalid IL or missing references) //IL_0a75: Expected O, but got Unknown //IL_0a81: Unknown result type (might be due to invalid IL or missing references) //IL_0aa5: Unknown result type (might be due to invalid IL or missing references) //IL_0aab: Unknown result type (might be due to invalid IL or missing references) //IL_0ab5: Expected O, but got Unknown //IL_0ad3: Unknown result type (might be due to invalid IL or missing references) //IL_0ad9: Unknown result type (might be due to invalid IL or missing references) //IL_0ae3: Expected O, but got Unknown //IL_0b01: Unknown result type (might be due to invalid IL or missing references) //IL_0b07: Unknown result type (might be due to invalid IL or missing references) //IL_0b11: Expected O, but got Unknown //IL_0b2f: Unknown result type (might be due to invalid IL or missing references) //IL_0b35: Unknown result type (might be due to invalid IL or missing references) //IL_0b3f: Expected O, but got Unknown //IL_0b5d: Unknown result type (might be due to invalid IL or missing references) //IL_0b63: Unknown result type (might be due to invalid IL or missing references) //IL_0b6d: Expected O, but got Unknown //IL_0b8b: Unknown result type (might be due to invalid IL or missing references) //IL_0b91: Unknown result type (might be due to invalid IL or missing references) //IL_0b9b: Expected O, but got Unknown //IL_0bb9: Unknown result type (might be due to invalid IL or missing references) //IL_0bbf: Unknown result type (might be due to invalid IL or missing references) //IL_0bc9: Expected O, but got Unknown //IL_0be7: Unknown result type (might be due to invalid IL or missing references) //IL_0bed: Unknown result type (might be due to invalid IL or missing references) //IL_0bf7: Expected O, but got Unknown //IL_0c15: Unknown result type (might be due to invalid IL or missing references) //IL_0c1b: Unknown result type (might be due to invalid IL or missing references) //IL_0c25: Expected O, but got Unknown //IL_0c43: Unknown result type (might be due to invalid IL or missing references) //IL_0c49: Unknown result type (might be due to invalid IL or missing references) //IL_0c53: Expected O, but got Unknown //IL_0c71: Unknown result type (might be due to invalid IL or missing references) //IL_0c77: Unknown result type (might be due to invalid IL or missing references) //IL_0c81: Expected O, but got Unknown //IL_0c9f: Unknown result type (might be due to invalid IL or missing references) //IL_0ca5: Unknown result type (might be due to invalid IL or missing references) //IL_0caf: Expected O, but got Unknown //IL_0ccd: Unknown result type (might be due to invalid IL or missing references) //IL_0cd3: Unknown result type (might be due to invalid IL or missing references) //IL_0cdd: Expected O, but got Unknown //IL_0cfb: Unknown result type (might be due to invalid IL or missing references) //IL_0d01: Unknown result type (might be due to invalid IL or missing references) //IL_0d0b: Expected O, but got Unknown //IL_0d29: Unknown result type (might be due to invalid IL or missing references) //IL_0d2f: Unknown result type (might be due to invalid IL or missing references) //IL_0d39: Expected O, but got Unknown //IL_0d57: Unknown result type (might be due to invalid IL or missing references) //IL_0d5d: Unknown result type (might be due to invalid IL or missing references) //IL_0d67: Expected O, but got Unknown //IL_0d85: Unknown result type (might be due to invalid IL or missing references) //IL_0d8b: Unknown result type (might be due to invalid IL or missing references) //IL_0d95: Expected O, but got Unknown //IL_0db3: Unknown result type (might be due to invalid IL or missing references) //IL_0db9: Unknown result type (might be due to invalid IL or missing references) //IL_0dc3: Expected O, but got Unknown //IL_0de1: Unknown result type (might be due to invalid IL or missing references) //IL_0de7: Unknown result type (might be due to invalid IL or missing references) //IL_0df1: Expected O, but got Unknown //IL_0e0f: Unknown result type (might be due to invalid IL or missing references) //IL_0e15: Unknown result type (might be due to invalid IL or missing references) //IL_0e1f: Expected O, but got Unknown //IL_0e30: Unknown result type (might be due to invalid IL or missing references) //IL_0e3a: Expected O, but got Unknown //IL_0e49: Unknown result type (might be due to invalid IL or missing references) //IL_0e53: Expected O, but got Unknown //IL_0e5d: Unknown result type (might be due to invalid IL or missing references) //IL_0e67: Expected O, but got Unknown //IL_0910: Unknown result type (might be due to invalid IL or missing references) //IL_0915: Unknown result type (might be due to invalid IL or missing references) //IL_091b: Expected O, but got Unknown //IL_0ea0: Unknown result type (might be due to invalid IL or missing references) //IL_0eaa: Expected O, but got Unknown //IL_0e80: Unknown result type (might be due to invalid IL or missing references) //IL_0e85: Unknown result type (might be due to invalid IL or missing references) //IL_0e8b: Expected O, but got Unknown //IL_0ee3: Unknown result type (might be due to invalid IL or missing references) //IL_0eed: Expected O, but got Unknown //IL_0ec3: Unknown result type (might be due to invalid IL or missing references) //IL_0ec8: Unknown result type (might be due to invalid IL or missing references) //IL_0ece: Expected O, but got Unknown //IL_0f26: Unknown result type (might be due to invalid IL or missing references) //IL_0f30: Expected O, but got Unknown //IL_0f06: Unknown result type (might be due to invalid IL or missing references) //IL_0f0b: Unknown result type (might be due to invalid IL or missing references) //IL_0f11: Expected O, but got Unknown //IL_0f49: Unknown result type (might be due to invalid IL or missing references) //IL_0f4e: Unknown result type (might be due to invalid IL or missing references) //IL_0f54: Expected O, but got Unknown if (config != null) { return; } config = PluginConfigurator.Create("Archipelago", "trpg.archipelagoultrakill"); string text = Path.Combine(Core.workingDir, "icon.png"); if (File.Exists(text)) { config.SetIconWithURL(text); } new ConfigHeader(config.rootPanel, "ARCHIPELAGO", 24); playerPanel = new ConfigPanel(config.rootPanel, "PLAYER SETTINGS", "playerPanel"); logPanel = new ConfigPanel(config.rootPanel, "LOG SETTINGS", "logPanel"); colorPanel = new ConfigPanel(config.rootPanel, "COLOR SETTINGS", "colorPanel"); hintsPanel = new ConfigPanel(config.rootPanel, "HINTS", "hintsPanel"); linksPanel = new ConfigPanel(config.rootPanel, "LINKS", "linksPanel"); isConnected = new BoolField(playerPanel, "CONNECTED TO SERVER?", "isConnected", false, false); ((ConfigField)isConnected).interactable = false; playerName = new StringField(playerPanel, "NAME", "playerName", "V1", false, true); serverAddress = new StringField(playerPanel, "ADDRESS", "serverAddress", "archipelago.gg", false, true); serverPassword = new StringField(playerPanel, "PASSWORD", "serverPassword", "", true, true); hintMode = new BoolField(playerPanel, "HINT MODE", "hintMode", false, false); new ConfigHeader(playerPanel, "Hint mode disables all randomization, and allows connecting to other games' slots to unlock hints while playing The Cyber Grind.", 12, (TextAlignmentOptions)257); connectionInfo = new ConfigHeader(playerPanel, "", 16, (TextAlignmentOptions)258); connectButton = new ButtonField(playerPanel, "CONNECT", "connectButton"); ButtonField obj = connectButton; object obj2 = <>c.<>9__80_0; if (obj2 == null) { OnClick val = delegate { if (Multiworld.Authenticated) { connectionInfo.text = "Already connected to server."; } else if (SceneHelper.CurrentScene != "Main Menu") { connectionInfo.text = "Can only connect to an Archipelago server on the main menu."; } else if ((GameProgressSaver.GetTutorial() || GameProgressSaver.GetIntro()) && !Core.DataExists() && !hintMode.value) { connectionInfo.text = "No Archipelago data found. Start a new save file before connecting."; } else if (Core.DataExists() && hintMode.value) { connectionInfo.text = "Can't use hint mode on a save file that already has randomizer data."; } else if (!Multiworld.Authenticated) { Core.data.slot_name = playerName.value; Core.data.host_name = serverAddress.value; Core.data.password = serverPassword.value; if (Core.data.password == "") { Core.data.password = null; } if (hintMode.value) { Multiworld.ConnectBK(); } else { Multiworld.Connect(); } } }; <>c.<>9__80_0 = val; obj2 = (object)val; } obj.onClick += (OnClick)obj2; disconnectButton = new ButtonField(playerPanel, "DISCONNECT", "disconnectButton"); ButtonField obj3 = disconnectButton; object obj4 = <>c.<>9__80_1; if (obj4 == null) { OnClick val2 = delegate { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Authenticated) { Multiworld.Disconnect(); connectionInfo.text = "Disconnected from server."; if (SceneHelper.CurrentScene == "Main Menu") { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } } }; <>c.<>9__80_1 = val2; obj4 = (object)val2; } obj3.onClick += (OnClick)obj4; deathLinkOnButton = new ButtonField(playerPanel, "ENABLE DEATH LINK", "deathLinkOnButton"); ButtonField obj5 = deathLinkOnButton; object obj6 = <>c.<>9__80_2; if (obj6 == null) { OnClick val3 = delegate { if (Multiworld.Authenticated) { Core.data.deathLink = true; Multiworld.EnableDeathLink(); } }; <>c.<>9__80_2 = val3; obj6 = (object)val3; } obj5.onClick += (OnClick)obj6; deathLinkOffButton = new ButtonField(playerPanel, "DISABLE DEATH LINK", "deathLinkOffButton"); ButtonField obj7 = deathLinkOffButton; object obj8 = <>c.<>9__80_3; if (obj8 == null) { OnClick val4 = delegate { if (Multiworld.Authenticated) { Core.data.deathLink = false; Multiworld.DisableDeathLink(); } }; <>c.<>9__80_3 = val4; obj8 = (object)val4; } obj7.onClick += (OnClick)obj8; chat = new StringField(playerPanel, "CHAT", "chat", "", true, false) { interactable = false }; StringField obj9 = chat; object obj10 = <>c.<>9__80_4; if (obj10 == null) { PostStringValueChangeEvent val5 = delegate(string value) { if (Multiworld.Authenticated) { if (value != "") { Multiworld.Session.Say(value); } chat.value = ""; } }; <>c.<>9__80_4 = val5; obj10 = (object)val5; } obj9.postValueChangeEvent += (PostStringValueChangeEvent)obj10; new ConfigHeader(playerPanel, "-----", 24); goal = new StringField(playerPanel, "GOAL", "goal", "?", false, false) { interactable = false }; goalProgress = new StringField(playerPanel, "LEVELS COMPLETED", "goalProgress", "?", false, false) { interactable = false }; locationsChecked = new StringField(playerPanel, "LOCATIONS CHECKED", "locationsChecked", "?", false, false) { interactable = false }; EnumField<BossOptions> obj11 = new EnumField<BossOptions>(playerPanel, "BOSS REWARDS", "bossRewards", BossOptions.Disabled, false); ((ConfigField)obj11).interactable = false; bossRewards = obj11; bossRewards.SetEnumDisplayName(BossOptions.Disabled, "DISABLED"); bossRewards.SetEnumDisplayName(BossOptions.Standard, "STANDARD"); bossRewards.SetEnumDisplayName(BossOptions.Extended, "EXTENDED"); challengeRewards = new BoolField(playerPanel, "CHALLENGE REWARDS", "challengeRewards", false, false) { interactable = false }; pRankRewards = new BoolField(playerPanel, "P RANK REWARDS", "pRankRewards", false, false) { interactable = false }; hankRewards = new BoolField(playerPanel, "HANK REWARDS", "hankRewards", false, false) { interactable = false }; clashReward = new BoolField(playerPanel, "RANDOMIZE CLASH MODE", "clashReward", false, false) { interactable = false }; fishRewards = new BoolField(playerPanel, "FISH REWARDS", "fishRewards", false, false) { interactable = false }; cleanRewards = new BoolField(playerPanel, "CLEANING REWARDS", "cleanRewards", false, false) { interactable = false }; chessReward = new BoolField(playerPanel, "CHESS REWARD", "chessReward", false, false) { interactable = false }; rocketReward = new BoolField(playerPanel, "ROCKET RACE REWARD", "rocketReward", false, false) { interactable = false }; randomizeFire2 = new BoolField(playerPanel, "RANDOMIZE SECONDARY FIRE", "randomizeFire2", false, false) { interactable = false }; EnumField<WeaponForm> obj12 = new EnumField<WeaponForm>(playerPanel, "REVOLVER FORM", "revForm", WeaponForm.Standard); ((ConfigField)obj12).interactable = false; revForm = obj12; revForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); revForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); EnumField<WeaponForm> obj13 = new EnumField<WeaponForm>(playerPanel, "SHOTGUN FORM", "shoForm", WeaponForm.Standard); ((ConfigField)obj13).interactable = false; shoForm = obj13; shoForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); shoForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); EnumField<WeaponForm> obj14 = new EnumField<WeaponForm>(playerPanel, "NAILGUN FORM", "naiForm", WeaponForm.Standard); ((ConfigField)obj14).interactable = false; naiForm = obj14; naiForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); naiForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); randomizeSkulls = new BoolField(playerPanel, "RANDOMIZE SKULLS", "randomizeSkulls", false, false) { interactable = false }; randomizeLimbo = new BoolField(playerPanel, "RANDOMIZE LIMBO SWITCHES", "randomizeLimbo", false, false) { interactable = false }; randomizeViolence = new BoolField(playerPanel, "RANDOMIZE VIOLENCE SWITCHES", "randomizeViolence", false, false) { interactable = false }; musicRandomizer = new BoolField(playerPanel, "MUSIC RANDOMIZER", "musicRandomizer", false, false) { interactable = false }; cybergrindHints = new BoolField(playerPanel, "UNLOCK HINTS IN CYBERGRIND", "cybergrindHints", false, false) { interactable = false }; deathLink = new BoolField(playerPanel, "DEATH LINK", "deathLink", false, false) { interactable = false }; showLog = new BoolField(logPanel, "SHOW LOG", "showLog", true, true); BoolField obj15 = showLog; object obj16 = <>c.<>9__80_5; if (obj16 == null) { BoolValueChangeEventDelegate val6 = delegate(BoolValueChangeEvent e) { ((Component)UIManager.log).gameObject.SetActive(e.value); }; <>c.<>9__80_5 = val6; obj16 = (object)val6; } obj15.onValueChange += (BoolValueChangeEventDelegate)obj16; logLines = new IntField(logPanel, "NUMBER OF MESSAGES", "logLines", 5, 1, 16, true, true); IntField obj17 = logLines; object obj18 = <>c.<>9__80_6; if (obj18 == null) { IntValueChangeEventDelegate val7 = delegate(IntValueChangeEvent e) { UIManager.lines = e.value; while (Multiworld.messages.Count > e.value) { Multiworld.messages.RemoveAt(0); } }; <>c.<>9__80_6 = val7; obj18 = (object)val7; } obj17.onValueChange += (IntValueChangeEventDelegate)obj18; logFontSize = new IntField(logPanel, "FONT SIZE", "logFontSize", 16, 1, 32, true, true); IntField obj19 = logFontSize; object obj20 = <>c.<>9__80_7; if (obj20 == null) { IntValueChangeEventDelegate val8 = delegate(IntValueChangeEvent e) { ((TMP_Text)UIManager.log).fontSize = e.value; }; <>c.<>9__80_7 = val8; obj20 = (object)val8; } obj19.onValueChange += (IntValueChangeEventDelegate)obj20; logClear = new ButtonField(logPanel, "CLEAR LOG", "logClear"); ButtonField obj21 = logClear; object obj22 = <>c.<>9__80_8; if (obj22 == null) { OnClick val9 = delegate { UIManager.SetLogText(""); Multiworld.messages.Clear(); }; <>c.<>9__80_8 = val9; obj22 = (object)val9; } obj21.onClick += (OnClick)obj22; uiColorRandomizer = new EnumField<ColorOptions>(colorPanel, "UI COLOR RANDOMIZER", "uiColorRandomizer", ColorOptions.Off, true); uiColorRandomizer.SetEnumDisplayName(ColorOptions.Off, "DISABLED"); uiColorRandomizer.SetEnumDisplayName(ColorOptions.Once, "ONCE"); uiColorRandomizer.SetEnumDisplayName(ColorOptions.EveryLoad, "EVERY NEW LEVEL LOADED"); gunColorRandomizer = new EnumField<ColorOptions>(colorPanel, "GUN COLOR RANDOMIZER", "gunColorRandomizer", ColorOptions.Off, true); gunColorRandomizer.SetEnumDisplayName(ColorOptions.Off, "DISABLED"); gunColorRandomizer.SetEnumDisplayName(ColorOptions.Once, "ONCE"); gunColorRandomizer.SetEnumDisplayName(ColorOptions.EveryLoad, "EVERY NEW LEVEL LOADED"); enableCustomButton = new ButtonField(colorPanel, "ENABLE ALL CUSTOM WEAPON COLORS", "enableCustomButton"); ButtonField obj23 = enableCustomButton; object obj24 = <>c.<>9__80_9; if (obj24 == null) { OnClick val10 = delegate { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); }; <>c.<>9__80_9 = val10; obj24 = (object)val10; } obj23.onClick += (OnClick)obj24; disableCustomButton = new ButtonField(colorPanel, "DISABLE ALL CUSTOM WEAPON COLORS", "disableCustomButton"); ButtonField obj25 = disableCustomButton; object obj26 = <>c.<>9__80_10; if (obj26 == null) { OnClick val11 = delegate { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", false); }; <>c.<>9__80_10 = val11; obj26 = (object)val11; } obj25.onClick += (OnClick)obj26; new ConfigHeader(colorPanel, "ARCHIPELAGO COLORS", 24); APPlayerSelf = new ColorField(colorPanel, "PLAYER (YOU)", "APPlayerSelf", new Color(0.93f, 0f, 0.93f), true); APPlayerOther = new ColorField(colorPanel, "PLAYER (OTHERS)", "APPlayerOther", new Color(0.98f, 0.98f, 0.82f), true); APItemFiller = new ColorField(colorPanel, "ITEM (FILLER)", "APItemFiller", new Color(0f, 0.93f, 0.93f), true); APItemNeverExclude = new ColorField(colorPanel, "ITEM (USEFUL)", "APItemNeverExclude", new Color(0.43f, 0.55f, 0.91f), true); APItemAdvancement = new ColorField(colorPanel, "ITEM (PROGRESSION)", "APItemAdvancement", new Color(0.69f, 0.6f, 0.94f), true); APItemTrap = new ColorField(colorPanel, "ITEM (TRAP)", "APItemTrap", new Color(0.98f, 0.5f, 0.45f), true); APLocation = new ColorField(colorPanel, "LOCATION", "APLocation", new Color(0f, 1f, 0.5f), true); new ConfigHeader(colorPanel, "POPUP COLORS", 24); layer0Color = new ColorField(colorPanel, "LAYER 0", "layer0Color", new Color(1f, 0.5f, 0.25f), true); layer1Color = new ColorField(colorPanel, "LAYER 1", "layer1Color", new Color(0.2667f, 1f, 0.2706f), true); layer2Color = new ColorField(colorPanel, "LAYER 2", "layer2Color", new Color(0.765f, 0.25f, 1f), true); layer3Color = new ColorField(colorPanel, "LAYER 3", "layer3Color", new Color(1f, 0.9479f, 0.8566f), true); layer4Color = new ColorField(colorPanel, "LAYER 4", "layer4Color", new Color(1f, 1f, 0.25f), true); layer5Color = new ColorField(colorPanel, "LAYER 5", "layer5Color", new Color(0.251f, 0.9059f, 1f), true); layer6Color = new ColorField(colorPanel, "LAYER 6", "layer6Color", new Color(1f, 0.2353f, 0.2353f), true); layer7Color = new ColorField(colorPanel, "LAYER 7", "layer7Color", new Color(0.8f, 0.8f, 0.8f), true); primeColor = new ColorField(colorPanel, "PRIME SANCTUMS", "primeColor", new Color(1f, 0.2353f, 0.2353f), true); altColor = new ColorField(colorPanel, "ALTERNATE WEAPON", "altColor", new Color(1f, 0.65f, 0f), true); arm0Color = new ColorField(colorPanel, "FEEDBACKER", "arm0Color", new Color(0.251f, 0.9059f, 1f), true); arm1Color = new ColorField(colorPanel, "KNUCKLEBLASTER", "arm1Color", new Color(1f, 0.2353f, 0.2353f), true); arm2Color = new ColorField(colorPanel, "WHIPLASH", "arm2Color", new Color(0.2667f, 1f, 0.2706f), true); blueSkullColor = new ColorField(colorPanel, "BLUE SKULL", "blueSkullColor", new Color(0.251f, 0.9059f, 1f), true); redSkullColor = new ColorField(colorPanel, "RED SKULL", "redSkullColor", new Color(1f, 0.2353f, 0.2353f), true); switchColor = new ColorField(colorPanel, "SWITCH", "switchColor", new Color(0.25f, 0.3f, 1f), true); pointsColor = new ColorField(colorPanel, "POINTS", "pointsColor", new Color(1f, 0.65f, 0f), true); dualwieldColor = new ColorField(colorPanel, "DUAL WIELD", "dualwieldColor", new Color(1f, 1f, 0.25f), true); doublejumpColor = new ColorField(colorPanel, "AIR JUMP", "doublejumpColor", new Color(1f, 1f, 0.6f), true); trapColor = new ColorField(colorPanel, "TRAP", "trapColor", new Color(0.7f, 0.7f, 0.7f), true); hintAdvancementOnly = new BoolField(hintsPanel, "PROGRESSION ITEM HINTS ONLY", "hintAdvancementOnly", true, true); hintRefresh = new ButtonField(hintsPanel, "REFRESH LIST", "hintRefresh"); hintList = new ConfigDivision(hintsPanel, "hintList"); ButtonField obj27 = hintRefresh; object obj28 = <>c.<>9__80_11; if (obj28 == null) { OnClick val12 = delegate { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Invalid comparison between Unknown and I4 //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Authenticated) { Object.Destroy((Object)(object)Traverse.Create((object)hintList).Field("panelObject").GetValue<GameObject>()); Traverse.Create((object)hintsPanel).Field("fieldObjects").GetValue<List<List<Transform>>>() .RemoveAt(2); Traverse.Create((object)hintsPanel).Field("fields").GetValue<List<ConfigField>>() .RemoveAt(2); hintList = null; hintList = new ConfigDivision(hintsPanel, "hintList"); Hint[] hints = ((IDataStorageWrapper)Multiworld.Session.DataStorage).GetHints((int?)null, (int?)null); Hint[] array = hints; foreach (Hint val16 in array) { if (!hintAdvancementOnly.value || (int)val16.ItemFlags == 1) { if (Array.IndexOf(hints, val16) != 0) { new ConfigHeader((ConfigPanel)(object)hintList, "-----", 24); } ((ConfigField)new StringField((ConfigPanel)(object)hintList, "ITEM", $"hint{Array.IndexOf(hints, val16)}_item", Multiworld.Session.Items.GetItemName(val16.ItemId, (string)null), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "RECEIVING PLAYER", $"hint{Array.IndexOf(hints, val16)}_receiving_player", Multiworld.Session.Players.GetPlayerAlias(val16.ReceivingPlayer), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "LOCATION", $"hint{Array.IndexOf(hints, val16)}_location", Multiworld.Session.Locations.GetLocationNameFromId(val16.LocationId, (string)null), true, false)).interactable = false; ((ConfigField)new StringField((ConfigPanel)(object)hintList, "SENDING PLAYER", $"hint{Array.IndexOf(hints, val16)}_sending_player", Multiworld.Session.Players.GetPlayerAlias(val16.FindingPlayer), true, false)).interactable = false; ((ConfigField)new BoolField((ConfigPanel)(object)hintList, "FOUND", $"hint{Array.IndexOf(hints, val16)}_found", val16.Found, false)).interactable = false; } } } }; <>c.<>9__80_11 = val12; obj28 = (object)val12; } obj27.onClick += (OnClick)obj28; thunderstoreButton = new ButtonField(linksPanel, "THUNDERSTORE", "thunderstoreButton"); ButtonField obj29 = thunderstoreButton; object obj30 = <>c.<>9__80_12; if (obj30 == null) { OnClick val13 = delegate { Application.OpenURL("https://thunderstore.io/c/ultrakill/p/TRPG/Archipelago/"); }; <>c.<>9__80_12 = val13; obj30 = (object)val13; } obj29.onClick += (OnClick)obj30; githubButton = new ButtonField(linksPanel, "GITHUB", "githubButton"); ButtonField obj31 = githubButton; object obj32 = <>c.<>9__80_13; if (obj32 == null) { OnClick val14 = delegate { Application.OpenURL("https://github.com/TRPG0/ArchipelagoULTRAKILL"); }; <>c.<>9__80_13 = val14; obj32 = (object)val14; } obj31.onClick += (OnClick)obj32; discordButton = new ButtonField(linksPanel, "AP AFTER DARK DISCORD", "discordButton"); ButtonField obj33 = discordButton; object obj34 = <>c.<>9__80_14; if (obj34 == null) { OnClick val15 = delegate { Application.OpenURL("https://discord.gg/Sbhy4ykUKn"); }; <>c.<>9__80_14 = val15; obj34 = (object)val15; } obj33.onClick += (OnClick)obj34; } public static void LoadConnectionInfo() { if (Core.data.slot_name != null) { playerName.value = Core.data.slot_name; } if (Core.data.host_name != null) { serverAddress.value = Core.data.host_name; } if (Core.data.password != null) { serverPassword.value = Core.data.password; } } public static void LoadStats() { goal.value = Core.data.goal; goalProgress.value = $"{Core.data.completedLevels.Count} / {Core.data.goalRequirement}"; string arg = ((LocationManager.locations.Count == 0) ? "?" : LocationManager.locations.Count.ToString()); locationsChecked.value = $"{[email protected]} / {arg}"; bossRewards.value = Core.data.bossRewards; challengeRewards.value = Core.data.challengeRewards; pRankRewards.value = Core.data.pRankRewards; hankRewards.value = Core.data.hankRewards; clashReward.value = Core.data.clashReward; fishRewards.value = Core.data.fishRewards; cleanRewards.value = Core.data.cleanRewards; chessReward.value = Core.data.chessReward; rocketReward.value = Core.data.rocketReward; randomizeFire2.value = Core.data.randomizeFire2; revForm.value = Core.data.revForm; shoForm.value = Core.data.shoForm; naiForm.value = Core.data.naiForm; randomizeSkulls.value = Core.data.randomizeSkulls; randomizeLimbo.value = Core.data.l1switch; randomizeViolence.value = Core.data.l7switch; musicRandomizer.value = Core.data.musicRandomizer; cybergrindHints.value = Core.data.cybergrindHints; deathLink.value = Core.data.deathLink; } public static void ResetStatsDefaults() { goal.value = "?"; goalProgress.value = "?"; locationsChecked.value = "?"; bossRewards.value = BossOptions.Disabled; challengeRewards.value = false; pRankRewards.value = false; hankRewards.value = false; clashReward.value = false; fishRewards.value = false; cleanRewards.value = false; chessReward.value = false; rocketReward.value = false; randomizeFire2.value = false; revForm.value = WeaponForm.Standard; shoForm.value = WeaponForm.Standard; naiForm.value = WeaponForm.Standard; randomizeSkulls.value = false; randomizeLimbo.value = false; randomizeViolence.value = false; musicRandomizer.value = false; cybergrindHints.value = false; deathLink.value = false; } } public static class LevelManager { public static Dictionary<string, GameObject> skulls = new Dictionary<string, GameObject>(); public static void FindSkulls() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0031: Invalid comparison between Unknown and I4 //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Invalid comparison between Unknown and I4 skulls.Clear(); int num = 0; ItemIdentifier[] array = Resources.FindObjectsOfTypeAll<ItemIdentifier>(); foreach (ItemIdentifier val in array) { if ((int)val.itemType != 1 && (int)val.itemType != 2) { continue; } Scene val2 = ((Component)val).gameObject.scene; string name = ((Scene)(ref val2)).name; val2 = SceneManager.GetActiveScene(); if (name == ((Scene)(ref val2)).name && (!(SceneHelper.CurrentScene == "Level 7-S") || (((int)val.itemType != 1 || Object.op_Implicit((Object)(object)((Component)val).transform.parent.parent.parent)) && ((int)val.itemType != 2 || !(((Object)((Component)val).transform.parent.parent.parent).name != "Interactives"))))) { if (skulls.ContainsKey(((object)(ItemType)(ref val.itemType)).ToString())) { num++; skulls[((object)(ItemType)(ref val.itemType)).ToString() + num] = ((Component)val).gameObject; } else { skulls[((object)(ItemType)(ref val.itemType)).ToString()] = ((Component)val).gameObject; } } } for (int j = 0; j < skulls.Count; j++) { KeyValuePair<string, GameObject> keyValuePair = skulls.ElementAt(j); string text = Core.CurrentLevelInfo.Id.ToString(); if (Core.CurrentLevelInfo.Name == "0-S") { text = "0S"; } else if (Core.CurrentLevelInfo.Name == "7-S") { text = "7S"; } string currentScene = SceneHelper.CurrentScene; string text2 = currentScene; if (!(text2 == "Level 1-4")) { if (text2 == "Level 5-1") { if (j + 1 > Core.data.unlockedSkulls5_1) { keyValuePair.Value.SetActive(false); } } else if (((Object)keyValuePair.Value).name.Contains("Blue")) { if (!Core.data.unlockedSkulls.Contains(text + "_b")) { keyValuePair.Value.SetActive(false); } } else if (((Object)keyValuePair.Value).name.Contains("Red") && !Core.data.unlockedSkulls.Contains(text + "_r")) { keyValuePair.Value.SetActive(false); } } else if (j + 1 > Core.data.unlockedSkulls1_4) { keyValuePair.Value.SetActive(false); } } } public static void UpdateShopVariation(VariationInfo variation) { //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Invalid comparison between Unknown and I4 //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Invalid comparison between Unknown and I4 //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Invalid comparison between Unknown and I4 //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_0769: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0693: Unknown result type (might be due to invalid IL or missing references) //IL_063b: Unknown result type (might be due to invalid IL or missing references) //IL_0665: Unknown result type (might be due to invalid IL or missing references) if (variation.weaponName == "arm0" && !Core.data.hasArm) { variation.costText.text = "<color=red>UNAVAILABLE</color>"; ((TMP_Text)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "UNAVAILABLE"; ((Component)variation.equipButton).gameObject.SetActive(false); Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Is not unlocked")); return; } if (variation.weaponName == "arm0" && Core.data.hasArm) { variation.costText.text = "ALREADY OWNED"; ((TMP_Text)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "ALREADY OWNED"; ((Component)variation.equipButton).gameObject.SetActive(true); Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Is unlocked")); return; } if (variation.weaponName == "arm1" || variation.weaponName == "arm2") { Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Skipping")); return; } if (!variation.weaponName.Contains("0")) { string text = "[Purchase to unlock: "; if (LocationManager.locations.ContainsKey("shop_" + variation.weaponName)) { if (LocationManager.shopScouts["shop_" + variation.weaponName] is UKItem uKItem) { text = text + "<color=#" + ColorUtility.ToHtmlStringRGB(LocationManager.GetUKMessageColor(uKItem.itemName)) + "FF>" + uKItem.itemName + "</color>"; if (uKItem.playerName != Core.data.slot_name) { text = text + " for <color=#" + ColorUtility.ToHtmlStringRGB(Colors.PlayerOther) + "FF>" + uKItem.playerName + "</color>"; } text += "]\n\n"; } else if (LocationManager.shopScouts["shop_" + variation.weaponName] is APItem aPItem) { text = text + "<color=#" + ColorUtility.ToHtmlStringRGB(LocationManager.GetAPMessageColor(aPItem.type)) + "FF>" + aPItem.itemName + "</color>"; text = text + " for <color=#" + ColorUtility.ToHtmlStringRGB(Colors.PlayerOther) + "FF>" + aPItem.playerName + "</color>"; text += "]\n\n"; text = (((int)aPItem.type == 1) ? (text + "You don't know what this is, but it seems <color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemAdvancement) + "FF>important.</color>") : (((int)aPItem.type == 2) ? (text + "You don't know what this is, but it seems like it could be <color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemNeverExclude) + "FF>useful.</color>") : (((int)aPItem.type != 4) ? (text + "You don't know what this is, but it seems like you could probably <color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemFiller) + "FF>skip this</color> if you wanted to.") : (text + "You don't know what this is, but it seems like they're probably <color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemTrap) + "FF>better off without it.</color>")))); } } else { text = "???"; } ((TMP_Text)((Component)variation.varPage.transform.Find("Description")).GetComponent<TextMeshProUGUI>()).text = text; } GameProgressMoneyAndGear generalProgress = GameProgressSaver.GetGeneralProgress(); FieldInfo field = typeof(GameProgressMoneyAndGear).GetField(variation.weaponName, BindingFlags.Instance | BindingFlags.Public); bool flag = int.Parse(field.GetValue(generalProgress).ToString()) == 1; if (flag && !variation.weaponName.Contains("0") && !Core.data.purchasedItems.Contains(variation.weaponName)) { bool flag2 = false; if (GameProgressSaver.GetMoney() >= Core.shopPrices[variation.weaponName]) { flag2 = true; } string text2 = ((!flag2) ? ("<color=red>" + MoneyText.DivideMoney(Core.shopPrices[variation.weaponName]) + "P</color>") : (MoneyText.DivideMoney(Core.shopPrices[variation.weaponName]) + "<color=orange>P</color>")); variation.costText.text = text2; ((Component)((Component)variation.equipButton).transform.GetChild(0)).GetComponent<Image>().sprite = variation.equipSprites[MonoSingleton<PrefsManager>.Instance.GetInt("weapon." + variation.weaponName, 1)]; variation.orderButtons.SetActive(true); Traverse val = Traverse.Create((object)variation); val.Field<int>("equipStatus").Value = MonoSingleton<PrefsManager>.Instance.GetInt("weapon." + variation.weaponName, 1); val.Field<int>("money").Value = GameProgressSaver.GetMoney(); variation.varPage.GetComponentInChildren<MoneyText>().UpdateMoney(); ((TMP_Text)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = text2; if (flag2) { ((Graphic)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).color = new Color(1f, 1f, 1f); ((Graphic)((Component)variation.buyButton).gameObject.GetComponent<Image>()).color = new Color(1f, 1f, 1f); } else { ((Graphic)((Component)variation.buyButton).gameObject.GetComponent<Image>()).color = new Color(1f, 0f, 0f); } Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Is unlocked, is not purchased")); } else if (!flag && !variation.weaponName.Contains("0") && Core.data.purchasedItems.Contains(variation.weaponName)) { variation.costText.text = "ALREADY OWNED"; variation.buyButton.deactivated = true; ((TMP_Text)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "ALREADY OWNED"; ((Graphic)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).color = new Color(0.5882f, 0.5882f, 0.5882f); ((Component)variation.equipButton).gameObject.SetActive(false); Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Is unlocked, is purchased")); } else if (!flag && variation.weaponName.Contains("0")) { variation.costText.text = "<color=red>UNAVAILABLE</color>"; ((TMP_Text)((Component)((Component)variation.buyButton).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "UNAVAILABLE"; ((Component)variation.equipButton).gameObject.SetActive(false); Core.Logger.LogInfo((object)("Shop - Weapon: \"" + variation.weaponName + "\" - Is not unlocked")); } } public static void AddDoorClosers() { ItemPlaceZone[] array = Resources.FindObjectsOfTypeAll<ItemPlaceZone>(); foreach (ItemPlaceZone val in array) { if (SceneHelper.CurrentScene == "Level 1-1") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "11 Nonstuff" && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 1-2") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "3 Nonstuff" && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 2-3") { if ((Object)(object)((Component)val).transform.parent != (Object)null && (((Object)((Component)val).transform.parent).name == "Altar" || ((Object)((Component)val).transform.parent).name == "Altar (1)") && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 4-4") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "Secret Hall" && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 5-2") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && (((Object)((Component)val).transform.parent.parent).name == "6" || ((Object)((Component)val).transform.parent.parent).name == "7B") && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 5-3") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "2A4 - Skullway" && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } else if (SceneHelper.CurrentScene == "Level 6-1" && (Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "3 - Crossroads" && !Object.op_Implicit((Object)(object)((Component)((Component)val).transform.parent.parent).gameObject.GetComponent<ReverseDoorCloser>())) { ((Component)((Component)val).transform.parent.parent).gameObject.AddComponent<ReverseDoorCloser>(); } } } public static void DeactivateNailgun() { GearCheckEnabler[] array = Resources.FindObjectsOfTypeAll<GearCheckEnabler>(); foreach (GearCheckEnabler val in array) { if (((Object)((Component)val).transform.parent).name == "1 - First Room") { ((Component)val).gameObject.SetActive(false); } } } public static void ChangeIntro() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if (Core.CurrentLevelHasInfo && Core.CurrentLevelInfo.Id == 1) { TextMeshProUGUI component = ((Component)GameObject.Find("/Canvas").transform.Find("HurtScreen").Find("Text 2 Sound").Find("Text (2)")).GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).text = ((TMP_Text)component).text + "\nARCHIPELAGO BY <color=#fec24c>TRPG</color>"; ((TMP_Text)component).lineSpacing = 25f; TextMeshProUGUI component2 = Object.Instantiate<GameObject>(((Component)component).gameObject, ((TMP_Text)component).transform.parent).GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).text = "and others!"; ((TMP_Text)component2).fontSize = 32f; ((TMP_Text)component2).transform.localPosition = new Vector3(270f, -70f, 0f); ((TMP_Text)component2).transform.Rotate(new Vector3(0f, 0f, 6f)); GameObject val = Object.Instantiate<GameObject>(((Component)component).gameObject, ((TMP_Text)component).transform.parent); Object.DestroyImmediate((Object)(object)val.GetComponent<TextMeshProUGUI>()); Object.DestroyImmediate((Object)(object)val.GetComponent<TMP_SpriteAnimator>()); Image val2 = val.AddComponent<Image>(); val2.sprite = UIManager.bundle.LoadAsset<Sprite>("assets/trpg.png"); ((Graphic)val2).color = new Color(0.992f, 0.758f, 0.297f); val2.preserveAspect = true; ((Component)val2).transform.localPosition = new Vector3(150f, -32f, 0f); ((Component)val2).transform.localScale = new Vector3(0.08f, 0.08f, 0.08f); ((Component)component).gameObject.AddComponent<LinkedDisabler>().objects.Add(((Component)component2).gameObject); ((Component)component).gameObject.AddComponent<LinkedDisabler>().objects.Add(((Component)val2).gameObject); } } public static void AddGlassComponents() { if (!Core.CurrentLevelHasInfo || Core.CurrentLevelInfo.Id != 1) { return; } Glass[] array = Resources.FindObjectsOfTypeAll<Glass>(); foreach (Glass val in array) { string name = ((Object)((Component)val).transform.parent.parent).name; switch (name) { default: if (!(name == "11 Content(Clone)")) { continue; } break; case "5 Stuff": case "5 Stuff(Clone)": case "11 Content": break; } GameObject gameObject = ((Component)((Component)val).transform.parent.parent).gameObject; if (!Object.op_Implicit((Object)(object)gameObject.GetComponent<GlassDisabler>())) { gameObject.AddComponent<GlassDisabler>(); } } } public static void FindHank() { if (!Core.CurrentLevelHasInfo) { return; } HudMessage[] array = Resources.FindObjectsOfTypeAll<HudMessage>(); foreach (HudMessage val in array) { if ((Core.CurrentLevelInfo.Id == 9 || Core.CurrentLevelInfo.Id == 22) && ((Object)val).name == "EasterEgg") { string message = val.message; message = message.Replace("Nothing", "Something"); message = message.Replace("but", "and"); val.message = message; ((Component)val).gameObject.AddComponent<Hank>(); } } } public static void ForceBlueArm() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)MonoSingleton<FistControl>.Instance)) { Core.Logger.LogWarning((object)"FistControl.Instance is null!"); return; } MonoSingleton<FistControl>.Instance.forcedLoadout.arm.blueVariant = (VariantOption)1; MonoSingleton<FistControl>.Instance.ResetFists(); } public static void FindRocketRaceButton() { if (!(SceneHelper.CurrentScene != "CreditsMuseum2") && Core.data.rocketReward) { GameObject.Find("/PuzzleScreen (2)/Canvas/Background/Start").AddComponent<RocketRaceCheck>(); } } } public static class Multiworld { public static int[] AP_VERSION = new int[3] { 0, 5, 0 }; public static DeathLinkService DeathLinkService = null; public static bool DeathLinkKilling = false; public static bool Authenticated; public static bool HintMode = false; public static ArchipelagoSession Session; public static List<string> messages = new List<string>(); public static void TryGetGoal(ref string goal, Dictionary<string, object> slotData, string defaultValue) { try { switch (int.Parse(slotData["goal"].ToString())) { case 0: goal = "1-4"; break; case 1: goal = "2-4"; break; case 2: goal = "3-2"; break; case 3: goal = "4-4"; break; case 4: goal = "5-4"; break; case 6: goal = "P-1"; break; case 7: goal = "P-2"; break; case 8: goal = "7-4"; break; default: goal = "6-2"; break; } } catch (Exception) { Core.Logger.LogError((object)("Couldn't parse goal. Something has gone very wrong. Using default value (" + defaultValue + ")")); goal = defaultValue; } } public static void TryGetSlotDataValue(ref int option, Dictionary<string, object> slotData, string key, int defaultValue) { try { option = int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public static void TryGetSlotDataValue(ref bool option, Dictionary<string, object> slotData, string key, bool defaultValue) { try { option = bool.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public static void TryGetSlotDataValue(ref BossOptions option, Dictionary<string, object> slotData, string key, BossOptions defaultValue) { try { option = (BossOptions)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public static void TryGetSlotDataValue(ref WeaponForm option, Dictionary<string, object> slotData, string key, WeaponForm defaultValue) { try { option = (WeaponForm)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public static bool Connect() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_0a5a: Unknown result type (might be due to invalid IL or missing references) //IL_0761: Unknown result type (might be due to invalid IL or missing references) //IL_07c8: Unknown result type (might be due to invalid IL or missing references) //IL_0975: Unknown result type (might be due to invalid IL or missing references) //IL_097a: Unknown result type (might be due to invalid IL or missing references) if (Authenticated) { return true; } Core.data.unlockedSkulls1_4 = 0; Core.data.unlockedSkulls5_1 = 0; Session = ArchipelagoSessionFactory.CreateSession(Core.data.host_name, 38281); Session.Socket.SocketClosed += new SocketClosedHandler(SocketClosed); Session.Socket.ErrorReceived += new ErrorReceivedHandler(ErrorReceived); Session.Socket.PacketReceived += new PacketReceivedHandler(PacketReceived); Session.Items.ItemReceived += new ItemReceivedHandler(ItemReceived); LoginResult val = Session.TryConnectAndLogin("ULTRAKILL", Core.data.slot_name, (ItemsHandlingFlags)7, new Version(AP_VERSION[0], AP_VERSION[1], AP_VERSION[2]), (string[])null, (string)null, (Core.data.password == "") ? null : Core.data.password, true); LoginSuccessful val2 = (LoginSuccessful)(object)((val is LoginSuccessful) ? val : null); if (val2 != null) { Authenticated = true; ConfigManager.isConnected.value = true; ((ConfigField)ConfigManager.playerName).interactable = false; ((ConfigField)ConfigManager.serverAddress).interactable = false; ((ConfigField)ConfigManager.serverPassword).interactable = false; ((ConfigField)ConfigManager.hintMode).interactable = false; ((ConfigField)ConfigManager.chat).interactable = true; TryGetGoal(ref Core.data.goal, val2.SlotData, "6-2"); TryGetSlotDataValue(ref Core.data.goalRequirement, val2.SlotData, "goal_requirement", 15); TryGetSlotDataValue(ref Core.data.bossRewards, val2.SlotData, "boss_rewards", BossOptions.Disabled); TryGetSlotDataValue(ref Core.data.challengeRewards, val2.SlotData, "challenge_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.pRankRewards, val2.SlotData, "p_rank_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.hankRewards, val2.SlotData, "hank_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.clashReward, val2.SlotData, "randomize_clash_mode", defaultValue: false); TryGetSlotDataValue(ref Core.data.fishRewards, val2.SlotData, "fish_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.cleanRewards, val2.SlotData, "cleaning_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.chessReward, val2.SlotData, "chess_reward", defaultValue: false); TryGetSlotDataValue(ref Core.data.rocketReward, val2.SlotData, "rocket_race_reward", defaultValue: false); TryGetSlotDataValue(ref Core.data.randomizeFire2, val2.SlotData, "randomize_secondary_fire", defaultValue: false); TryGetSlotDataValue(ref Core.data.revForm, val2.SlotData, "revolver_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.shoForm, val2.SlotData, "shotgun_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.naiForm, val2.SlotData, "nailgun_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.randomizeSkulls, val2.SlotData, "randomize_skulls", defaultValue: false); TryGetSlotDataValue(ref Core.data.l1switch, val2.SlotData, "randomize_limbo_switches", defaultValue: false); TryGetSlotDataValue(ref Core.data.l7switch, val2.SlotData, "randomize_violence_switches", defaultValue: false); if (Core.data.randomizeSkulls && !UIManager.createdSkullIcons) { UIManager.CreateMenuSkullIcons(); } if ((Core.data.l1switch || Core.data.l7switch) && !UIManager.createdSwitchIcons) { UIManager.CreateMenuSwitchIcons(); } if (!Core.DataExists()) { if (Core.data.revForm == WeaponForm.Standard) { Core.data.revstd = true; Core.data.revalt = false; } else { Core.data.revstd = false; Core.data.revalt = true; GameProgressSaver.AddGear("revalt"); } if (Core.data.shoForm == WeaponForm.Standard) { Core.data.shostd = true; Core.data.shoalt = false; } else { Core.data.shostd = false; Core.data.shoalt = true; GameProgressSaver.AddGear("shoalt"); } if (Core.data.naiForm == WeaponForm.Standard) { Core.data.naistd = true; Core.data.naialt = false; } else { Core.data.naistd = false; Core.data.naialt = true; GameProgressSaver.AddGear("naialt"); } TryGetSlotDataValue(ref Core.data.hasArm, val2.SlotData, "start_with_arm", defaultValue: true); TryGetSlotDataValue(ref Core.data.dashes, val2.SlotData, "starti
websocket-sharp.dll
Decompiled 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using System.Timers; using WebSocketSharp.Net; using WebSocketSharp.Net.WebSockets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("websocket-sharp")] [assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("websocket-sharp.dll")] [assembly: AssemblyCopyright("sta.blockhead")] [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("1.0.2.34775")] namespace WebSocketSharp { public static class Ext { private static readonly byte[] _last = new byte[1]; private static readonly int _retry = 5; private const string _tspecials = "()<>@,;:\\\"/[]?={} \t"; private static byte[] compress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.compressToArray(); } private static MemoryStream compress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, leaveOpen: true); CopyTo(stream, deflateStream, 1024); deflateStream.Close(); memoryStream.Write(_last, 0, 1); memoryStream.Position = 0L; return memoryStream; } private static byte[] compressToArray(this Stream stream) { using MemoryStream memoryStream = stream.compress(); memoryStream.Close(); return memoryStream.ToArray(); } private static byte[] decompress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.decompressToArray(); } private static MemoryStream decompress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true); CopyTo(source, memoryStream, 1024); memoryStream.Position = 0L; return memoryStream; } private static byte[] decompressToArray(this Stream stream) { using MemoryStream memoryStream = stream.decompress(); memoryStream.Close(); return memoryStream.ToArray(); } private static bool isHttpMethod(this string value) { int result; switch (value) { default: result = ((value == "TRACE") ? 1 : 0); break; case "GET": case "HEAD": case "POST": case "PUT": case "DELETE": case "CONNECT": case "OPTIONS": result = 1; break; } return (byte)result != 0; } private static bool isHttpMethod10(this string value) { return value == "GET" || value == "HEAD" || value == "POST"; } internal static byte[] Append(this ushort code, string reason) { byte[] array = code.InternalToByteArray(ByteOrder.Big); if (reason == null || reason.Length == 0) { return array; } List<byte> list = new List<byte>(array); list.AddRange(Encoding.UTF8.GetBytes(reason)); return list.ToArray(); } internal static byte[] Compress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.compress() : data; } internal static Stream Compress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compress() : stream; } internal static byte[] CompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compressToArray() : stream.ToByteArray(); } internal static bool Contains(this string value, params char[] anyOf) { return anyOf != null && anyOf.Length != 0 && value.IndexOfAny(anyOf) > -1; } internal static bool Contains(this NameValueCollection collection, string name) { return collection[name] != null; } internal static bool Contains(this NameValueCollection collection, string name, string value, StringComparison comparisonTypeForValue) { string text = collection[name]; if (text == null) { return false; } string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text2.Trim().Equals(value, comparisonTypeForValue)) { return true; } } return false; } internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition) { foreach (T item in source) { if (condition(item)) { return true; } } return false; } internal static bool ContainsTwice(this string[] values) { int len = values.Length; int end = len - 1; Func<int, bool> seek = null; seek = delegate(int idx) { if (idx == end) { return false; } string text = values[idx]; for (int i = idx + 1; i < len; i++) { if (values[i] == text) { return true; } } return seek(++idx); }; return seek(0); } internal static T[] Copy<T>(this T[] source, int length) { T[] array = new T[length]; Array.Copy(source, 0, array, 0, length); return array; } internal static T[] Copy<T>(this T[] source, long length) { T[] array = new T[length]; Array.Copy(source, 0L, array, 0L, length); return array; } internal static void CopyTo(this Stream source, Stream destination, int bufferLength) { byte[] buffer = new byte[bufferLength]; int num = 0; while (true) { num = source.Read(buffer, 0, bufferLength); if (num <= 0) { break; } destination.Write(buffer, 0, num); } } internal static void CopyToAsync(this Stream source, Stream destination, int bufferLength, Action completed, Action<Exception> error) { byte[] buff = new byte[bufferLength]; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = source.EndRead(ar); if (num <= 0) { if (completed != null) { completed(); } } else { destination.Write(buff, 0, num); source.BeginRead(buff, 0, bufferLength, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { source.BeginRead(buff, 0, bufferLength, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static byte[] Decompress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.decompress() : data; } internal static Stream Decompress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompress() : stream; } internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompressToArray() : stream.ToByteArray(); } internal static void Emit(this EventHandler eventHandler, object sender, EventArgs e) { eventHandler?.Invoke(sender, e); } internal static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs { eventHandler?.Invoke(sender, e); } internal static bool EqualsWith(this int value, char c, Action<int> action) { action(value); return value == c; } internal static string GetAbsolutePath(this Uri uri) { if (uri.IsAbsoluteUri) { return uri.AbsolutePath; } string originalString = uri.OriginalString; if (originalString[0] != '/') { return null; } int num = originalString.IndexOfAny(new char[2] { '?', '#' }); return (num > 0) ? originalString.Substring(0, num) : originalString; } internal static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response) { string text = headers[response ? "Set-Cookie" : "Cookie"]; return (text != null) ? WebSocketSharp.Net.CookieCollection.Parse(text, response) : new WebSocketSharp.Net.CookieCollection(); } internal static string GetDnsSafeHost(this Uri uri, bool bracketIPv6) { return (bracketIPv6 && uri.HostNameType == UriHostNameType.IPv6) ? uri.Host : uri.DnsSafeHost; } internal static string GetMessage(this CloseStatusCode code) { return code switch { CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.", CloseStatusCode.ServerError => "WebSocket server got an internal error.", CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).", CloseStatusCode.TooBig => "A too big message has been received.", CloseStatusCode.PolicyViolation => "A policy violation has occurred.", CloseStatusCode.InvalidData => "Invalid data has been received.", CloseStatusCode.Abnormal => "An exception has occurred.", CloseStatusCode.UnsupportedData => "Unsupported data has been received.", CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.", _ => string.Empty, }; } internal static string GetName(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); return (num > 0) ? nameAndValue.Substring(0, num).Trim() : null; } internal static string GetUTF8DecodedString(this byte[] bytes) { return Encoding.UTF8.GetString(bytes); } internal static byte[] GetUTF8EncodedBytes(this string s) { return Encoding.UTF8.GetBytes(s); } internal static string GetValue(this string nameAndValue, char separator) { return nameAndValue.GetValue(separator, unquote: false); } internal static string GetValue(this string nameAndValue, char separator, bool unquote) { int num = nameAndValue.IndexOf(separator); if (num < 0 || num == nameAndValue.Length - 1) { return null; } string text = nameAndValue.Substring(num + 1).Trim(); return unquote ? text.Unquote() : text; } internal static byte[] InternalToByteArray(this ushort value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static byte[] InternalToByteArray(this ulong value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static bool IsCompressionExtension(this string value, CompressionMethod method) { return value.StartsWith(method.ToExtensionString()); } internal static bool IsControl(this byte opcode) { return opcode > 7 && opcode < 16; } internal static bool IsControl(this Opcode opcode) { return (int)opcode >= 8; } internal static bool IsData(this byte opcode) { return opcode == 1 || opcode == 2; } internal static bool IsData(this Opcode opcode) { return opcode == Opcode.Text || opcode == Opcode.Binary; } internal static bool IsHttpMethod(this string value, Version version) { return (version == WebSocketSharp.Net.HttpVersion.Version10) ? value.isHttpMethod10() : value.isHttpMethod(); } internal static bool IsPortNumber(this int value) { return value > 0 && value < 65536; } internal static bool IsReserved(this ushort code) { return code == 1004 || code == 1005 || code == 1006 || code == 1015; } internal static bool IsReserved(this CloseStatusCode code) { return code == CloseStatusCode.Undefined || code == CloseStatusCode.NoStatus || code == CloseStatusCode.Abnormal || code == CloseStatusCode.TlsHandshakeFailure; } internal static bool IsSupported(this byte opcode) { return Enum.IsDefined(typeof(Opcode), opcode); } internal static bool IsText(this string value) { int length = value.Length; for (int i = 0; i < length; i++) { char c = value[i]; if (c < ' ') { if ("\r\n\t".IndexOf(c) == -1) { return false; } if (c == '\n') { i++; if (i == length) { break; } c = value[i]; if (" \t".IndexOf(c) == -1) { return false; } } } else if (c == '\u007f') { return false; } } return true; } internal static bool IsToken(this string value) { foreach (char c in value) { if (c < ' ') { return false; } if (c > '~') { return false; } if ("()<>@,;:\\\"/[]?={} \t".IndexOf(c) > -1) { return false; } } return true; } internal static bool KeepsAlive(this NameValueCollection headers, Version version) { StringComparison comparisonTypeForValue = StringComparison.OrdinalIgnoreCase; return (version < WebSocketSharp.Net.HttpVersion.Version11) ? headers.Contains("Connection", "keep-alive", comparisonTypeForValue) : (!headers.Contains("Connection", "close", comparisonTypeForValue)); } internal static string Quote(this string value) { return string.Format("\"{0}\"", value.Replace("\"", "\\\"")); } internal static byte[] ReadBytes(this Stream stream, int length) { byte[] array = new byte[length]; int num = 0; int num2 = 0; int num3 = 0; while (length > 0) { num3 = stream.Read(array, num, length); if (num3 <= 0) { if (num2 >= _retry) { return array.SubArray(0, num); } num2++; } else { num2 = 0; num += num3; length -= num3; } } return array; } internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(); byte[] buffer = new byte[bufferLength]; int num = 0; int num2 = 0; while (length > 0) { if (length < bufferLength) { bufferLength = (int)length; } num2 = stream.Read(buffer, 0, bufferLength); if (num2 <= 0) { if (num >= _retry) { break; } num++; } else { num = 0; memoryStream.Write(buffer, 0, num2); length -= num2; } } memoryStream.Close(); return memoryStream.ToArray(); } internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error) { byte[] buff = new byte[length]; int offset = 0; int retry = 0; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num <= 0) { if (retry < _retry) { retry++; stream.BeginRead(buff, offset, length, callback, null); } else if (completed != null) { completed(buff.SubArray(0, offset)); } } else if (num == length) { if (completed != null) { completed(buff); } } else { retry = 0; offset += num; length -= num; stream.BeginRead(buff, offset, length, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { stream.BeginRead(buff, offset, length, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static void ReadBytesAsync(this Stream stream, long length, int bufferLength, Action<byte[]> completed, Action<Exception> error) { MemoryStream dest = new MemoryStream(); byte[] buff = new byte[bufferLength]; int retry = 0; Action<long> read = null; read = delegate(long len) { if (len < bufferLength) { bufferLength = (int)len; } stream.BeginRead(buff, 0, bufferLength, delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num <= 0) { if (retry < _retry) { int num2 = retry; retry = num2 + 1; read(len); } else { if (completed != null) { dest.Close(); completed(dest.ToArray()); } dest.Dispose(); } } else { dest.Write(buff, 0, num); if (num == len) { if (completed != null) { dest.Close(); completed(dest.ToArray()); } dest.Dispose(); } else { retry = 0; read(len - num); } } } catch (Exception obj2) { dest.Dispose(); if (error != null) { error(obj2); } } }, null); }; try { read(length); } catch (Exception obj) { dest.Dispose(); if (error != null) { error(obj); } } } internal static T[] Reverse<T>(this T[] array) { int num = array.Length; T[] array2 = new T[num]; int num2 = num - 1; for (int i = 0; i <= num2; i++) { array2[i] = array[num2 - i]; } return array2; } internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators) { int len = value.Length; int end = len - 1; StringBuilder buff = new StringBuilder(32); bool escaped = false; bool quoted = false; for (int i = 0; i <= end; i++) { char c = value[i]; buff.Append(c); switch (c) { case '"': if (escaped) { escaped = false; } else { quoted = !quoted; } continue; case '\\': if (i == end) { break; } if (value[i + 1] == '"') { escaped = true; } continue; default: if (Array.IndexOf(separators, c) > -1 && !quoted) { buff.Length--; yield return buff.ToString(); buff.Length = 0; } continue; } break; } yield return buff.ToString(); } internal static byte[] ToByteArray(this Stream stream) { using MemoryStream memoryStream = new MemoryStream(); stream.Position = 0L; CopyTo(stream, memoryStream, 1024); memoryStream.Close(); return memoryStream.ToArray(); } internal static CompressionMethod ToCompressionMethod(this string value) { Array values = Enum.GetValues(typeof(CompressionMethod)); foreach (CompressionMethod item in values) { if (item.ToExtensionString() == value) { return item; } } return CompressionMethod.None; } internal static string ToExtensionString(this CompressionMethod method, params string[] parameters) { if (method == CompressionMethod.None) { return string.Empty; } string text = $"permessage-{method.ToString().ToLower()}"; return (parameters != null && parameters.Length != 0) ? string.Format("{0}; {1}", text, parameters.ToString("; ")) : text; } internal static IPAddress ToIPAddress(this string value) { if (value == null || value.Length == 0) { return null; } if (IPAddress.TryParse(value, out IPAddress address)) { return address; } try { IPAddress[] hostAddresses = Dns.GetHostAddresses(value); return hostAddresses[0]; } catch { return null; } } internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } internal static string ToString(this IPAddress address, bool bracketIPv6) { return (bracketIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6) ? $"[{address.ToString()}]" : address.ToString(); } internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0); } internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0); } internal static IEnumerable<string> TrimEach(this IEnumerable<string> source) { foreach (string elm in source) { yield return elm.Trim(); } } internal static string TrimSlashFromEnd(this string value) { string text = value.TrimEnd(new char[1] { '/' }); return (text.Length > 0) ? text : "/"; } internal static string TrimSlashOrBackslashFromEnd(this string value) { string text = value.TrimEnd('/', '\\'); return (text.Length > 0) ? text : value[0].ToString(); } internal static bool TryCreateVersion(this string versionString, out Version result) { result = null; try { result = new Version(versionString); } catch { return false; } return true; } internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message) { result = null; message = null; Uri uri = uriString.ToUri(); if (uri == null) { message = "An invalid URI string."; return false; } if (!uri.IsAbsoluteUri) { message = "A relative URI."; return false; } string scheme = uri.Scheme; if (!(scheme == "ws") && !(scheme == "wss")) { message = "The scheme part is not 'ws' or 'wss'."; return false; } int port = uri.Port; if (port == 0) { message = "The port part is zero."; return false; } if (uri.Fragment.Length > 0) { message = "It includes the fragment component."; return false; } result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery))); return true; } internal static bool TryGetUTF8DecodedString(this byte[] bytes, out string s) { s = null; try { s = Encoding.UTF8.GetString(bytes); } catch { return false; } return true; } internal static bool TryGetUTF8EncodedBytes(this string s, out byte[] bytes) { bytes = null; try { bytes = Encoding.UTF8.GetBytes(s); } catch { return false; } return true; } internal static bool TryOpenRead(this FileInfo fileInfo, out FileStream fileStream) { fileStream = null; try { fileStream = fileInfo.OpenRead(); } catch { return false; } return true; } internal static string Unquote(this string value) { int num = value.IndexOf('"'); if (num == -1) { return value; } int num2 = value.LastIndexOf('"'); if (num2 == num) { return value; } int num3 = num2 - num - 1; return (num3 > 0) ? value.Substring(num + 1, num3).Replace("\\\"", "\"") : string.Empty; } internal static bool Upgrades(this NameValueCollection headers, string protocol) { StringComparison comparisonTypeForValue = StringComparison.OrdinalIgnoreCase; return headers.Contains("Upgrade", protocol, comparisonTypeForValue) && headers.Contains("Connection", "Upgrade", comparisonTypeForValue); } internal static string UrlDecode(this string value, Encoding encoding) { return HttpUtility.UrlDecode(value, encoding); } internal static string UrlEncode(this string value, Encoding encoding) { return HttpUtility.UrlEncode(value, encoding); } internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength) { using MemoryStream source = new MemoryStream(bytes); CopyTo(source, stream, bufferLength); } internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error) { MemoryStream src = new MemoryStream(bytes); src.CopyToAsync(stream, bufferLength, delegate { if (completed != null) { completed(); } src.Dispose(); }, delegate(Exception ex) { src.Dispose(); if (error != null) { error(ex); } }); } public static string GetDescription(this WebSocketSharp.Net.HttpStatusCode code) { return ((int)code).GetStatusDescription(); } public static string GetStatusDescription(this int code) { return code switch { 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-Uri Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "Http Version Not Supported", 507 => "Insufficient Storage", _ => string.Empty, }; } public static bool IsCloseStatusCode(this ushort value) { return value > 999 && value < 5000; } public static bool IsEnclosedIn(this string value, char c) { if (value == null) { return false; } int length = value.Length; if (length < 2) { return false; } return value[0] == c && value[length - 1] == c; } public static bool IsHostOrder(this ByteOrder order) { return BitConverter.IsLittleEndian == (order == ByteOrder.Little); } public static bool IsLocal(this IPAddress address) { if (address == null) { throw new ArgumentNullException("address"); } if (address.Equals(IPAddress.Any)) { return true; } if (address.Equals(IPAddress.Loopback)) { return true; } if (Socket.OSSupportsIPv6) { if (address.Equals(IPAddress.IPv6Any)) { return true; } if (address.Equals(IPAddress.IPv6Loopback)) { return true; } } string hostName = Dns.GetHostName(); IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName); IPAddress[] array = hostAddresses; foreach (IPAddress obj in array) { if (address.Equals(obj)) { return true; } } return false; } public static bool IsNullOrEmpty(this string value) { return value == null || value.Length == 0; } public static bool IsPredefinedScheme(this string value) { if (value == null || value.Length < 2) { return false; } switch (value[0]) { case 'h': return value == "http" || value == "https"; case 'w': return value == "ws" || value == "wss"; case 'f': return value == "file" || value == "ftp"; case 'g': return value == "gopher"; case 'm': return value == "mailto"; case 'n': { char c = value[1]; return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp"); } default: return false; } } public static bool MaybeUri(this string value) { if (value == null) { return false; } if (value.Length == 0) { return false; } int num = value.IndexOf(':'); if (num == -1) { return false; } if (num >= 10) { return false; } string value2 = value.Substring(0, num); return value2.IsPredefinedScheme(); } public static T[] SubArray<T>(this T[] array, int startIndex, int length) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { if (startIndex != 0) { throw new ArgumentOutOfRangeException("startIndex"); } if (length != 0) { throw new ArgumentOutOfRangeException("length"); } return array; } if (startIndex < 0 || startIndex >= num) { throw new ArgumentOutOfRangeException("startIndex"); } if (length < 0 || length > num - startIndex) { throw new ArgumentOutOfRangeException("length"); } if (length == 0) { return new T[0]; } if (length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0, length); return array2; } public static T[] SubArray<T>(this T[] array, long startIndex, long length) { if (array == null) { throw new ArgumentNullException("array"); } long num = array.LongLength; if (num == 0) { if (startIndex != 0) { throw new ArgumentOutOfRangeException("startIndex"); } if (length != 0) { throw new ArgumentOutOfRangeException("length"); } return array; } if (startIndex < 0 || startIndex >= num) { throw new ArgumentOutOfRangeException("startIndex"); } if (length < 0 || length > num - startIndex) { throw new ArgumentOutOfRangeException("length"); } if (length == 0) { return new T[0]; } if (length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0L, length); return array2; } public static void Times(this int n, Action action) { if (n > 0 && action != null) { for (int i = 0; i < n; i++) { action(); } } } public static void Times(this long n, Action action) { if (n > 0 && action != null) { for (long num = 0L; num < n; num++) { action(); } } } public static void Times(this uint n, Action action) { if (n != 0 && action != null) { for (uint num = 0u; num < n; num++) { action(); } } } public static void Times(this ulong n, Action action) { if (n != 0 && action != null) { for (ulong num = 0uL; num < n; num++) { action(); } } } public static void Times(this int n, Action<int> action) { if (n > 0 && action != null) { for (int i = 0; i < n; i++) { action(i); } } } public static void Times(this long n, Action<long> action) { if (n > 0 && action != null) { for (long num = 0L; num < n; num++) { action(num); } } } public static void Times(this uint n, Action<uint> action) { if (n != 0 && action != null) { for (uint num = 0u; num < n; num++) { action(num); } } } public static void Times(this ulong n, Action<ulong> action) { if (n != 0 && action != null) { for (ulong num = 0uL; num < n; num++) { action(num); } } } [Obsolete("This method will be removed.")] public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length == 0) { return default(T); } Type typeFromHandle = typeof(T); byte[] value = source.ToHostOrder(sourceOrder); return ((object)typeFromHandle == typeof(bool)) ? ((T)(object)BitConverter.ToBoolean(value, 0)) : (((object)typeFromHandle == typeof(char)) ? ((T)(object)BitConverter.ToChar(value, 0)) : (((object)typeFromHandle == typeof(double)) ? ((T)(object)BitConverter.ToDouble(value, 0)) : (((object)typeFromHandle == typeof(short)) ? ((T)(object)BitConverter.ToInt16(value, 0)) : (((object)typeFromHandle == typeof(int)) ? ((T)(object)BitConverter.ToInt32(value, 0)) : (((object)typeFromHandle == typeof(long)) ? ((T)(object)BitConverter.ToInt64(value, 0)) : (((object)typeFromHandle == typeof(float)) ? ((T)(object)BitConverter.ToSingle(value, 0)) : (((object)typeFromHandle == typeof(ushort)) ? ((T)(object)BitConverter.ToUInt16(value, 0)) : (((object)typeFromHandle == typeof(uint)) ? ((T)(object)BitConverter.ToUInt32(value, 0)) : (((object)typeFromHandle == typeof(ulong)) ? ((T)(object)BitConverter.ToUInt64(value, 0)) : default(T)))))))))); } [Obsolete("This method will be removed.")] public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct { Type typeFromHandle = typeof(T); byte[] array = (((object)typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : (((object)typeFromHandle != typeof(byte)) ? (((object)typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : (((object)typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : (((object)typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : (((object)typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : (((object)typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : (((object)typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : (((object)typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : (((object)typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : (((object)typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : WebSocket.EmptyBytes))))))))) : new byte[1] { (byte)(object)value })); if (array.Length > 1 && !order.IsHostOrder()) { Array.Reverse((Array)array); } return array; } public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder) { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length < 2) { return source; } if (sourceOrder.IsHostOrder()) { return source; } return source.Reverse(); } public static string ToString<T>(this T[] array, string separator) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { return string.Empty; } if (separator == null) { separator = string.Empty; } StringBuilder stringBuilder = new StringBuilder(64); int num2 = num - 1; for (int i = 0; i < num2; i++) { stringBuilder.AppendFormat("{0}{1}", array[i], separator); } stringBuilder.Append(array[num2].ToString()); return stringBuilder.ToString(); } public static Uri ToUri(this string value) { Uri.TryCreate(value, value.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result); return result; } [Obsolete("This method will be removed.")] public static void WriteContent(this WebSocketSharp.Net.HttpListenerResponse response, byte[] content) { if (response == null) { throw new ArgumentNullException("response"); } if (content == null) { throw new ArgumentNullException("content"); } long num = content.LongLength; if (num == 0) { response.Close(); return; } response.ContentLength64 = num; Stream outputStream = response.OutputStream; if (num <= int.MaxValue) { outputStream.Write(content, 0, (int)num); } else { outputStream.WriteBytes(content, 1024); } outputStream.Close(); } } public class MessageEventArgs : EventArgs { private string _data; private bool _dataSet; private Opcode _opcode; private byte[] _rawData; internal Opcode Opcode => _opcode; public string Data { get { setData(); return _data; } } public bool IsBinary => _opcode == Opcode.Binary; public bool IsPing => _opcode == Opcode.Ping; public bool IsText => _opcode == Opcode.Text; public byte[] RawData { get { setData(); return _rawData; } } internal MessageEventArgs(WebSocketFrame frame) { _opcode = frame.Opcode; _rawData = frame.PayloadData.ApplicationData; } internal MessageEventArgs(Opcode opcode, byte[] rawData) { if ((ulong)rawData.LongLength > PayloadData.MaxLength) { throw new WebSocketException(CloseStatusCode.TooBig); } _opcode = opcode; _rawData = rawData; } private void setData() { if (_dataSet) { return; } if (_opcode == Opcode.Binary) { _dataSet = true; return; } if (_rawData.TryGetUTF8DecodedString(out var s)) { _data = s; } _dataSet = true; } } public class CloseEventArgs : EventArgs { private bool _clean; private PayloadData _payloadData; public ushort Code => _payloadData.Code; public string Reason => _payloadData.Reason; public bool WasClean => _clean; internal CloseEventArgs(PayloadData payloadData, bool clean) { _payloadData = payloadData; _clean = clean; } internal CloseEventArgs(ushort code, string reason, bool clean) { _payloadData = new PayloadData(code, reason); _clean = clean; } } public enum ByteOrder { Little, Big } public class ErrorEventArgs : EventArgs { private Exception _exception; private string _message; public Exception Exception => _exception; public string Message => _message; internal ErrorEventArgs(string message) : this(message, null) { } internal ErrorEventArgs(string message, Exception exception) { _message = message; _exception = exception; } } public class WebSocket : IDisposable { private AuthenticationChallenge _authChallenge; private string _base64Key; private bool _client; private Action _closeContext; private CompressionMethod _compression; private WebSocketContext _context; private WebSocketSharp.Net.CookieCollection _cookies; private WebSocketSharp.Net.NetworkCredential _credentials; private bool _emitOnPing; private bool _enableRedirection; private string _extensions; private bool _extensionsRequested; private object _forMessageEventQueue; private object _forPing; private object _forSend; private object _forState; private MemoryStream _fragmentsBuffer; private bool _fragmentsCompressed; private Opcode _fragmentsOpcode; private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; private Func<WebSocketContext, string> _handshakeRequestChecker; private bool _ignoreExtensions; private bool _inContinuation; private volatile bool _inMessage; private volatile Logger _logger; private static readonly int _maxRetryCountForConnect; private Action<MessageEventArgs> _message; private Queue<MessageEventArgs> _messageEventQueue; private uint _nonceCount; private string _origin; private ManualResetEvent _pongReceived; private bool _preAuth; private string _protocol; private string[] _protocols; private bool _protocolsRequested; private WebSocketSharp.Net.NetworkCredential _proxyCredentials; private Uri _proxyUri; private volatile WebSocketState _readyState; private ManualResetEvent _receivingExited; private int _retryCountForConnect; private bool _secure; private ClientSslConfiguration _sslConfig; private Stream _stream; private TcpClient _tcpClient; private Uri _uri; private const string _version = "13"; private TimeSpan _waitTime; internal static readonly byte[] EmptyBytes; internal static readonly int FragmentLength; internal static readonly RandomNumberGenerator RandomNumber; internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies; internal Func<WebSocketContext, string> CustomHandshakeRequestChecker { get { return _handshakeRequestChecker; } set { _handshakeRequestChecker = value; } } internal bool HasMessage { get { lock (_forMessageEventQueue) { return _messageEventQueue.Count > 0; } } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } internal bool IsConnected => _readyState == WebSocketState.Open || _readyState == WebSocketState.Closing; public CompressionMethod Compression { get { return _compression; } set { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _compression = value; } } } } public IEnumerable<WebSocketSharp.Net.Cookie> Cookies { get { lock (_cookies.SyncRoot) { foreach (WebSocketSharp.Net.Cookie cookie in _cookies) { yield return cookie; } } } } public WebSocketSharp.Net.NetworkCredential Credentials => _credentials; public bool EmitOnPing { get { return _emitOnPing; } set { _emitOnPing = value; } } public bool EnableRedirection { get { return _enableRedirection; } set { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _enableRedirection = value; } } } } public string Extensions => _extensions ?? string.Empty; public bool IsAlive => ping(EmptyBytes); public bool IsSecure => _secure; public Logger Log { get { return _logger; } internal set { _logger = value; } } public string Origin { get { return _origin; } set { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!value.IsNullOrEmpty()) { if (!Uri.TryCreate(value, UriKind.Absolute, out Uri result)) { text = "Not an absolute URI string."; throw new ArgumentException(text, "value"); } if (result.Segments.Length > 1) { text = "It includes the path segments."; throw new ArgumentException(text, "value"); } } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); return; } _origin = ((!value.IsNullOrEmpty()) ? value.TrimEnd(new char[1] { '/' }) : value); } } } public string Protocol { get { return _protocol ?? string.Empty; } internal set { _protocol = value; } } public WebSocketState ReadyState => _readyState; public ClientSslConfiguration SslConfiguration { get { if (!_client) { string text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!_secure) { string text2 = "This instance does not use a secure connection."; throw new InvalidOperationException(text2); } return getSslConfiguration(); } } public Uri Url => _client ? _uri : _context.RequestUri; public TimeSpan WaitTime { get { return _waitTime; } set { if (value <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("value", "Zero or less."); } if (!canSet(out var text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else { _waitTime = value; } } } } public event EventHandler<CloseEventArgs> OnClose; public event EventHandler<ErrorEventArgs> OnError; public event EventHandler<MessageEventArgs> OnMessage; public event EventHandler OnOpen; static WebSocket() { _maxRetryCountForConnect = 10; EmptyBytes = new byte[0]; FragmentLength = 1016; RandomNumber = new RNGCryptoServiceProvider(); } internal WebSocket(HttpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } internal WebSocket(TcpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } public WebSocket(string url, params string[] protocols) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Length == 0) { throw new ArgumentException("An empty string.", "url"); } if (!url.TryCreateWebSocketUri(out _uri, out var text)) { throw new ArgumentException(text, "url"); } if (protocols != null && protocols.Length != 0) { if (!checkProtocols(protocols, out text)) { throw new ArgumentException(text, "protocols"); } _protocols = protocols; } _base64Key = CreateBase64Key(); _client = true; _logger = new Logger(); _message = messagec; _secure = _uri.Scheme == "wss"; _waitTime = TimeSpan.FromSeconds(5.0); init(); } private bool accept() { if (_readyState == WebSocketState.Open) { string text = "The handshake request has already been accepted."; _logger.Warn(text); return false; } lock (_forState) { if (_readyState == WebSocketState.Open) { string text2 = "The handshake request has already been accepted."; _logger.Warn(text2); return false; } if (_readyState == WebSocketState.Closing) { string text3 = "The close process has set in."; _logger.Error(text3); text3 = "An interruption has occurred while attempting to accept."; error(text3, null); return false; } if (_readyState == WebSocketState.Closed) { string text4 = "The connection has been closed."; _logger.Error(text4); text4 = "An interruption has occurred while attempting to accept."; error(text4, null); return false; } try { if (!acceptHandshake()) { return false; } } catch (Exception ex) { _logger.Fatal(ex.Message); _logger.Debug(ex.ToString()); string text5 = "An exception has occurred while attempting to accept."; fatal(text5, ex); return false; } _readyState = WebSocketState.Open; return true; } } private bool acceptHandshake() { _logger.Debug($"A handshake request from {_context.UserEndPoint}:\n{_context}"); if (!checkHandshakeRequest(_context, out var text)) { _logger.Error(text); refuseHandshake(CloseStatusCode.ProtocolError, "A handshake error has occurred while attempting to accept."); return false; } if (!customCheckHandshakeRequest(_context, out text)) { _logger.Error(text); refuseHandshake(CloseStatusCode.PolicyViolation, "A handshake error has occurred while attempting to accept."); return false; } _base64Key = _context.Headers["Sec-WebSocket-Key"]; if (_protocol != null) { IEnumerable<string> secWebSocketProtocols = _context.SecWebSocketProtocols; processSecWebSocketProtocolClientHeader(secWebSocketProtocols); } if (!_ignoreExtensions) { string value = _context.Headers["Sec-WebSocket-Extensions"]; processSecWebSocketExtensionsClientHeader(value); } return sendHttpResponse(createHandshakeResponse()); } private bool canSet(out string message) { message = null; if (_readyState == WebSocketState.Open) { message = "The connection has already been established."; return false; } if (_readyState == WebSocketState.Closing) { message = "The connection is closing."; return false; } return true; } private bool checkHandshakeRequest(WebSocketContext context, out string message) { message = null; if (!context.IsWebSocketRequest) { message = "Not a handshake request."; return false; } if (context.RequestUri == null) { message = "It specifies an invalid Request-URI."; return false; } NameValueCollection headers = context.Headers; string text = headers["Sec-WebSocket-Key"]; if (text == null) { message = "It includes no Sec-WebSocket-Key header."; return false; } if (text.Length == 0) { message = "It includes an invalid Sec-WebSocket-Key header."; return false; } string text2 = headers["Sec-WebSocket-Version"]; if (text2 == null) { message = "It includes no Sec-WebSocket-Version header."; return false; } if (text2 != "13") { message = "It includes an invalid Sec-WebSocket-Version header."; return false; } string text3 = headers["Sec-WebSocket-Protocol"]; if (text3 != null && text3.Length == 0) { message = "It includes an invalid Sec-WebSocket-Protocol header."; return false; } if (!_ignoreExtensions) { string text4 = headers["Sec-WebSocket-Extensions"]; if (text4 != null && text4.Length == 0) { message = "It includes an invalid Sec-WebSocket-Extensions header."; return false; } } return true; } private bool checkHandshakeResponse(HttpResponse response, out string message) { message = null; if (response.IsRedirect) { message = "Indicates the redirection."; return false; } if (response.IsUnauthorized) { message = "Requires the authentication."; return false; } if (!response.IsWebSocketResponse) { message = "Not a WebSocket handshake response."; return false; } NameValueCollection headers = response.Headers; if (!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"])) { message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolServerHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value."; return false; } if (!validateSecWebSocketExtensionsServerHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } if (!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"])) { message = "Includes an invalid Sec-WebSocket-Version header."; return false; } return true; } private static bool checkProtocols(string[] protocols, out string message) { message = null; Func<string, bool> condition = (string protocol) => protocol.IsNullOrEmpty() || !protocol.IsToken(); if (protocols.Contains(condition)) { message = "It contains a value that is not a token."; return false; } if (protocols.ContainsTwice()) { message = "It contains a value twice."; return false; } return true; } private bool checkReceivedFrame(WebSocketFrame frame, out string message) { message = null; bool isMasked = frame.IsMasked; if (_client && isMasked) { message = "A frame from the server is masked."; return false; } if (!_client && !isMasked) { message = "A frame from a client is not masked."; return false; } if (_inContinuation && frame.IsData) { message = "A data frame has been received while receiving continuation frames."; return false; } if (frame.IsCompressed && _compression == CompressionMethod.None) { message = "A compressed frame has been received without any agreement for it."; return false; } if (frame.Rsv2 == Rsv.On) { message = "The RSV2 of a frame is non-zero without any negotiation for it."; return false; } if (frame.Rsv3 == Rsv.On) { message = "The RSV3 of a frame is non-zero without any negotiation for it."; return false; } return true; } private void close(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } if (code == 1005) { close(PayloadData.Empty, send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); close(new PayloadData(code, reason), receive, receive, received: false); } private void close(PayloadData payloadData, bool send, bool receive, bool received) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } send = send && _readyState == WebSocketState.Open; receive = send && receive; _readyState = WebSocketState.Closing; } _logger.Trace("Begin closing the connection."); bool clean = closeHandshake(payloadData, send, receive, received); releaseResources(); _logger.Trace("End closing the connection."); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs(payloadData, clean); try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); } } private void closeAsync(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } if (code == 1005) { closeAsync(PayloadData.Empty, send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); closeAsync(new PayloadData(code, reason), receive, receive, received: false); } private void closeAsync(PayloadData payloadData, bool send, bool receive, bool received) { Action<PayloadData, bool, bool, bool> closer = close; closer.BeginInvoke(payloadData, send, receive, received, delegate(IAsyncResult ar) { closer.EndInvoke(ar); }, null); } private bool closeHandshake(byte[] frameAsBytes, bool receive, bool received) { bool flag = frameAsBytes != null && sendBytes(frameAsBytes); if (!received && flag && receive && _receivingExited != null) { received = _receivingExited.WaitOne(_waitTime); } bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool closeHandshake(PayloadData payloadData, bool send, bool receive, bool received) { bool flag = false; if (send) { WebSocketFrame webSocketFrame = WebSocketFrame.CreateCloseFrame(payloadData, _client); flag = sendBytes(webSocketFrame.ToArray()); if (_client) { webSocketFrame.Unmask(); } } if (!received && flag && receive && _receivingExited != null) { received = _receivingExited.WaitOne(_waitTime); } bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool connect() { if (_readyState == WebSocketState.Open) { string text = "The connection has already been established."; _logger.Warn(text); return false; } lock (_forState) { if (_readyState == WebSocketState.Open) { string text2 = "The connection has already been established."; _logger.Warn(text2); return false; } if (_readyState == WebSocketState.Closing) { string text3 = "The close process has set in."; _logger.Error(text3); text3 = "An interruption has occurred while attempting to connect."; error(text3, null); return false; } if (_retryCountForConnect > _maxRetryCountForConnect) { string text4 = "An opportunity for reconnecting has been lost."; _logger.Error(text4); text4 = "An interruption has occurred while attempting to connect."; error(text4, null); return false; } _readyState = WebSocketState.Connecting; try { doHandshake(); } catch (Exception ex) { _retryCountForConnect++; _logger.Fatal(ex.Message); _logger.Debug(ex.ToString()); string text5 = "An exception has occurred while attempting to connect."; fatal(text5, ex); return false; } _retryCountForConnect = 1; _readyState = WebSocketState.Open; return true; } } private string createExtensions() { StringBuilder stringBuilder = new StringBuilder(80); if (_compression != 0) { string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover"); stringBuilder.AppendFormat("{0}, ", arg); } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; return stringBuilder.ToString(); } return null; } private HttpResponse createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode code) { HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code); httpResponse.Headers["Sec-WebSocket-Version"] = "13"; return httpResponse; } private HttpRequest createHandshakeRequest() { HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri); NameValueCollection headers = httpRequest.Headers; if (!_origin.IsNullOrEmpty()) { headers["Origin"] = _origin; } headers["Sec-WebSocket-Key"] = _base64Key; _protocolsRequested = _protocols != null; if (_protocolsRequested) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); } _extensionsRequested = _compression != CompressionMethod.None; if (_extensionsRequested) { headers["Sec-WebSocket-Extensions"] = createExtensions(); } headers["Sec-WebSocket-Version"] = "13"; AuthenticationResponse authenticationResponse = null; if (_authChallenge != null && _credentials != null) { authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; } else if (_preAuth) { authenticationResponse = new AuthenticationResponse(_credentials); } if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_cookies.Count > 0) { httpRequest.SetCookies(_cookies); } return httpRequest; } private HttpResponse createHandshakeResponse() { HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse(); NameValueCollection headers = httpResponse.Headers; headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key); if (_protocol != null) { headers["Sec-WebSocket-Protocol"] = _protocol; } if (_extensions != null) { headers["Sec-WebSocket-Extensions"] = _extensions; } if (_cookies.Count > 0) { httpResponse.SetCookies(_cookies); } return httpResponse; } private bool customCheckHandshakeRequest(WebSocketContext context, out string message) { message = null; if (_handshakeRequestChecker == null) { return true; } message = _handshakeRequestChecker(context); return message == null; } private MessageEventArgs dequeueFromMessageEventQueue() { lock (_forMessageEventQueue) { return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null; } } private void doHandshake() { setClientStream(); HttpResponse httpResponse = sendHandshakeRequest(); if (!checkHandshakeResponse(httpResponse, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } if (_protocolsRequested) { _protocol = httpResponse.Headers["Sec-WebSocket-Protocol"]; } if (_extensionsRequested) { processSecWebSocketExtensionsServerHeader(httpResponse.Headers["Sec-WebSocket-Extensions"]); } processCookies(httpResponse.Cookies); } private void enqueueToMessageEventQueue(MessageEventArgs e) { lock (_forMessageEventQueue) { _messageEventQueue.Enqueue(e); } } private void error(string message, Exception exception) { try { this.OnError.Emit(this, new ErrorEventArgs(message, exception)); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); } } private void fatal(string message, Exception exception) { CloseStatusCode code = ((exception is WebSocketException) ? ((WebSocketException)exception).Code : CloseStatusCode.Abnormal); fatal(message, (ushort)code); } private void fatal(string message, ushort code) { PayloadData payloadData = new PayloadData(code, message); close(payloadData, !code.IsReserved(), receive: false, received: false); } private void fatal(string message, CloseStatusCode code) { fatal(message, (ushort)code); } private ClientSslConfiguration getSslConfiguration() { if (_sslConfig == null) { _sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost); } return _sslConfig; } private void init() { _compression = CompressionMethod.None; _cookies = new WebSocketSharp.Net.CookieCollection(); _forPing = new object(); _forSend = new object(); _forState = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.Connecting; } private void message() { MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { return; } _inMessage = true; obj = _messageEventQueue.Dequeue(); } _message(obj); } private void messagec(MessageEventArgs e) { while (true) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; break; } e = _messageEventQueue.Dequeue(); } bool flag = true; } } private void messages(MessageEventArgs e) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } e = _messageEventQueue.Dequeue(); } ThreadPool.QueueUserWorkItem(delegate { messages(e); }); } private void open() { _inMessage = true; startReceiving(); try { this.OnOpen.Emit(this, EventArgs.Empty); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during the OnOpen event.", ex); } MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } obj = _messageEventQueue.Dequeue(); } _message.BeginInvoke(obj, delegate(IAsyncResult ar) { _message.EndInvoke(ar); }, null); } private bool ping(byte[] data) { if (_readyState != WebSocketState.Open) { return false; } ManualResetEvent pongReceived = _pongReceived; if (pongReceived == null) { return false; } lock (_forPing) { try { pongReceived.Reset(); if (!send(Fin.Final, Opcode.Ping, data, compressed: false)) { return false; } return pongReceived.WaitOne(_waitTime); } catch (ObjectDisposedException) { return false; } } } private bool processCloseFrame(WebSocketFrame frame) { PayloadData payloadData = frame.PayloadData; close(payloadData, !payloadData.HasReservedCode, receive: false, received: true); return false; } private void processCookies(WebSocketSharp.Net.CookieCollection cookies) { if (cookies.Count != 0) { _cookies.SetOrRemove(cookies); } } private bool processDataFrame(WebSocketFrame frame) { enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame)); return true; } private bool processFragmentFrame(WebSocketFrame frame) { if (!_inContinuation) { if (frame.IsContinuation) { return true; } _fragmentsOpcode = frame.Opcode; _fragmentsCompressed = frame.IsCompressed; _fragmentsBuffer = new MemoryStream(); _inContinuation = true; } _fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024); if (frame.IsFinal) { using (_fragmentsBuffer) { byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray()); enqueueToMessageEventQueue(new MessageEventArgs(_fragmentsOpcode, rawData)); } _fragmentsBuffer = null; _inContinuation = false; } return true; } private bool processPingFrame(WebSocketFrame frame) { _logger.Trace("A ping was received."); WebSocketFrame webSocketFrame = WebSocketFrame.CreatePongFrame(frame.PayloadData, _client); lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The connection is closing."); return true; } if (!sendBytes(webSocketFrame.ToArray())) { return false; } } _logger.Trace("A pong to this ping has been sent."); if (_emitOnPing) { if (_client) { webSocketFrame.Unmask(); } enqueueToMessageEventQueue(new MessageEventArgs(frame)); } return true; } private bool processPongFrame(WebSocketFrame frame) { _logger.Trace("A pong was received."); try { _pongReceived.Set(); } catch (NullReferenceException ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); return false; } catch (ObjectDisposedException ex2) { _logger.Error(ex2.Message); _logger.Debug(ex2.ToString()); return false; } _logger.Trace("It has been signaled."); return true; } private bool processReceivedFrame(WebSocketFrame frame) { if (!checkReceivedFrame(frame, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } frame.Unmask(); return frame.IsFragment ? processFragmentFrame(frame) : (frame.IsData ? processDataFrame(frame) : (frame.IsPing ? processPingFrame(frame) : (frame.IsPong ? processPongFrame(frame) : (frame.IsClose ? processCloseFrame(frame) : processUnsupportedFrame(frame))))); } private void processSecWebSocketExtensionsClientHeader(string value) { if (value == null) { return; } StringBuilder stringBuilder = new StringBuilder(80); bool flag = false; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (text.Length != 0 && !flag && text.IsCompressionExtension(CompressionMethod.Deflate)) { _compression = CompressionMethod.Deflate; stringBuilder.AppendFormat("{0}, ", _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover")); flag = true; } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; _extensions = stringBuilder.ToString(); } } private void processSecWebSocketExtensionsServerHeader(string value) { if (value == null) { _compression = CompressionMethod.None; } else { _extensions = value; } } private void processSecWebSocketProtocolClientHeader(IEnumerable<string> values) { if (!values.Contains((string val) => val == _protocol)) { _protocol = null; } } private bool processUnsupportedFrame(WebSocketFrame frame) { _logger.Fatal("An unsupported frame:" + frame.PrintToString(dumped: false)); fatal("There is no way to handle it.", CloseStatusCode.PolicyViolation); return false; } private void refuseHandshake(CloseStatusCode code, string reason) { _readyState = WebSocketState.Closing; HttpResponse response = createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest); sendHttpResponse(response); releaseServerResources(); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs((ushort)code, reason, clean: false); try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); } } private void releaseClientResources() { if (_stream != null) { _stream.Dispose(); _stream = null; } if (_tcpClient != null) { _tcpClient.Close(); _tcpClient = null; } } private void releaseCommonResources() { if (_fragmentsBuffer != null) { _fragmentsBuffer.Dispose(); _fragmentsBuffer = null; _inContinuation = false; } if (_pongReceived != null) { _pongReceived.Close(); _pongReceived = null; } if (_receivingExited != null) { _receivingExited.Close(); _receivingExited = null; } } private void releaseResources() { if (_client) { releaseClientResources(); } else { releaseServerResources(); } releaseCommonResources(); } private void releaseServerResources() { if (_closeContext != null) { _closeContext(); _closeContext = null; _stream = null; _context = null; } } private bool send(Opcode opcode, Stream stream) { lock (_forSend) { Stream stream2 = stream; bool flag = false; bool flag2 = false; try { if (_compression != 0) { stream = stream.Compress(_compression); flag = true; } flag2 = send(opcode, stream, flag); if (!flag2) { error("A send has been interrupted.", null); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during a send.", ex); } finally { if (flag) { stream.Dispose(); } stream2.Dispose(); } return flag2; } } private bool send(Opcode opcode, Stream stream, bool compressed) { long length = stream.Length; if (length == 0) { return send(Fin.Final, opcode, EmptyBytes, compressed: false); } long num = length / FragmentLength; int num2 = (int)(length % FragmentLength); byte[] array = null; switch (num) { case 0L: array = new byte[num2]; return stream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed); case 1L: if (num2 == 0) { array = new byte[FragmentLength]; return stream.Read(array, 0, FragmentLength) == FragmentLength && send(Fin.Final, opcode, array, compressed); } break; } array = new byte[FragmentLength]; if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, opcode, array, compressed)) { return false; } long num3 = ((num2 == 0) ? (num - 2) : (num - 1)); for (long num4 = 0L; num4 < num3; num4++) { if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed: false)) { return false; } } if (num2 == 0) { num2 = FragmentLength; } else { array = new byte[num2]; } return stream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed: false); } private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The connection is closing."); return false; } WebSocketFrame webSocketFrame = new WebSocketFrame(fin, opcode, data, compressed, _client); return sendBytes(webSocketFrame.ToArray()); } } private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed) { Func<Opcode, Stream, bool> sender = send; sender.BeginInvoke(opcode, stream, delegate(IAsyncResult ar) { try { bool obj = sender.EndInvoke(ar); if (completed != null) { completed(obj); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An error has occurred during the callback for an async send.", ex); } }, null); } private bool sendBytes(byte[] bytes) { try { _stream.Write(bytes, 0, bytes.Length); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); return false; } return true; } private HttpResponse sendHandshakeRequest() { HttpRequest httpRequest = createHandshakeRequest(); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsUnauthorized) { string text = httpResponse.Headers["WWW-Authenticate"]; _logger.Warn($"Received an authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { _logger.Error("No authentication challenge is specified."); return httpResponse; } _authChallenge = AuthenticationChallenge.Parse(text); if (_authChallenge == null) { _logger.Error("An invalid authentication challenge is specified."); return httpResponse; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest)) { if (httpResponse.HasConnectionClose) { releaseClientResources(); setClientStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; httpRequest.Headers["Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } } if (httpResponse.IsRedirect) { string text2 = httpResponse.Headers["Location"]; _logger.Warn($"Received a redirection to '{text2}'."); if (_enableRedirection) { if (text2.IsNullOrEmpty()) { _logger.Error("No url to redirect is located."); return httpResponse; } if (!text2.TryCreateWebSocketUri(out var result, out var text3)) { _logger.Error("An invalid url to redirect is located: " + text3); return httpResponse; } releaseClientResources(); _uri = result; _secure = result.Scheme == "wss"; setClientStream(); return sendHandshakeRequest(); } } return httpResponse; } private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout) { _logger.Debug("A request to the server:\n" + request.ToString()); HttpResponse response = request.GetResponse(_stream, millisecondsTimeout); _logger.Debug("A response to this request:\n" + response.ToString()); return response; } private bool sendHttpResponse(HttpResponse response) { _logger.Debug($"A response to {_context.UserEndPoint}:\n{response}"); return sendBytes(response.ToByteArray()); } private void sendProxyConnectRequest() { HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsProxyAuthenticationRequired) { string text = httpResponse.Headers["Proxy-Authenticate"]; _logger.Warn($"Received a proxy authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { throw new WebSocketException("No proxy authentication challenge is specified."); } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text); if (authenticationChallenge == null) { throw new WebSocketException("An invalid proxy authentication challenge is specified."); } if (_proxyCredentials != null) { if (httpResponse.HasConnectionClose) { releaseClientResources(); _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u); httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } if (httpResponse.IsProxyAuthenticationRequired) { throw new WebSocketException("A proxy authentication is required."); } } if (httpResponse.StatusCode[0] != '2') { throw new WebSocketException("The proxy has failed a connection to the requested host and port."); } } private void setClientStream() { if (_proxyUri != null) { _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); sendProxyConnectRequest(); } else { _tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port); _stream = _tcpClient.GetStream(); } if (_secure) { ClientSslConfiguration sslConfiguration = getSslConfiguration(); string targetHost = sslConfiguration.TargetHost; if (targetHost != _uri.DnsSafeHost) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified."); } try { SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback); sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation); _stream = sslStream; } catch (Exception innerException) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException); } } } private void startReceiving() { if (_messageEventQueue.Count > 0) { _messageEventQueue.Clear(); } _pongReceived = new ManualResetEvent(initialState: false); _receivingExited = new ManualResetEvent(initialState: false); Action receive = null; receive = delegate { WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame) { if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed) { _receivingExited?.Set(); } else { receive(); if (!_inMessage && HasMessage && _readyState == WebSocketState.Open) { message(); } } }, delegate(Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while receiving.", ex); }); }; receive(); } private bool validateSecWebSocketAcceptHeader(string value) { return value != null && value == CreateResponseKey(_base64Key); } private bool validateSecWebSocketExtensionsServerHeader(string value) { if (value == null) { return true; } if (value.Length == 0) { return false; } if (!_extensionsRequested) { return false; } bool flag = _compression != CompressionMethod.None; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (flag && text.IsCompressionExtension(_compression)) { if (!text.Contains("server_no_context_takeover")) { _logger.Error("The server hasn't sent back 'server_no_context_takeover'."); return false; } if (!text.Contains("client_no_context_takeover")) { _logger.Warn("The server hasn't sent back 'client_no_context_takeover'."); } string method = _compression.ToExtensionString(); if (text.SplitHeaderValue(';').Contains(delegate(string t) { t = t.Trim(); return t != method && t != "server_no_context_takeover" && t != "client_no_context_takeover"; })) { return false; } continue; } return false; } return true; } private bool validateSecWebSocketProtocolServerHeader(string value) { if (value == null) { return !_protocolsRequested; } if (value.Length == 0) { return false; } return _protocolsRequested && _protocols.Contains((string p) => p == value); } private bool validateSecWebSocketVersionServerHeader(string value) { return value == null || value == "13"; } internal void Close(HttpResponse response) { _readyState = WebSocketState.Closing; sendHttpResponse(response); releaseServerResources(); _readyState = WebSocketState.Closed; } internal void Close(WebSocketSharp.Net.HttpStatusCode code) { Close(createHandshakeFailureResponse(code)); } internal void Close(PayloadData payloadData, byte[] frameAsBytes) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has already been closed."); return; } _readyState = WebSocketState.Closing; } _logger.Trace("Begin closing the connection."); bool flag = frameAsBytes != null && sendBytes(frameAsBytes); bool flag2 = flag && _receivingExited != null && _receivingExited.WaitOne(_waitTime); bool flag3 = flag && flag2; _logger.Debug($"Was clean?: {flag3}\n sent: {flag}\n received: {flag2}"); releaseServerResources(); releaseCommonResources(); _logger.Trace("End closing the connection."); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs(payloadData, flag3); try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.Message); _logger.Debug(ex.ToString()); } } internal static string CreateBase64Key() { byte[] array = new byte[16]; RandomNumber.GetBytes(array); return Convert.ToBase64String(array); } internal static string CreateResponseKey(string base64Key) { StringBuilder stringBuilder = new StringBuilder(base64Key, 64); stringBuilder.Append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); SHA1 sHA = new SHA1CryptoServiceProvider(); byte[] inArray = sHA.ComputeHash(stringBuilder.ToString().GetUTF8EncodedBytes()); return Convert.ToBase64String(inArray); } internal void InternalAccept() { try { if (!acceptHandshake()) { return; } } catch (Exception ex) { _logger.Fatal(ex.Message); _logger.Debug(ex.ToString()); string text = "An exception has occurred while attempting to accept."; fatal(text, ex); return; } _readyState = WebSocketState.Open; open(); } internal bool Ping(byte[] frameAsBytes, TimeSpan timeout) { if (_readyState != WebSocketState.Open) { return false; } ManualResetEvent pongReceived = _pongReceived; if (pongReceived == null) { return false; } lock (_forPing) { try { pongReceived.Reset(); lock (_forState) { if (_readyState != WebSocketState.Open) { return false; } if (!sendBytes(frameAsBytes)) { return false; } } return pongReceived.WaitOne(timeout); } catch (ObjectDisposedException) { return false; } } } internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache) { lock (_forSend) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The connection is closing."); return; } if (!cache.TryGetValue(_compression, out var value)) { value = new WebSocketFrame(Fin.Final, opcode, data.Compress(_compression), _compression != CompressionMethod.None, mask: false).ToArray(); cache.Add(_compression, value); } sendBytes(value); } } } internal void Send(Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache) { lock (_forSend) { if (!cache.TryGetValue(_compression, out var value)) { value = stream.Compress(_compression); cache.Add(_compression, value); } else { value.Position = 0L; } send(opcode, value, _compression != CompressionMethod.None); } } public void Accept() { if (_client) { string text = "This instance is a client."; throw new InvalidOperationException(text); } if (_readyState == WebSocketState.Closing) { string text2 = "The close process is in progress."; throw new InvalidOperationException(text2); } if (_readyState == WebSocketState.Closed) { string text3 = "The connection has already been closed."; throw new InvalidOperationException(text3); } if (accept()) { open(); } } public void AcceptAsync() { if (_client) { string text = "This instance is a client."; throw new InvalidOperationException(text); } if (_readyState == WebSocketState.Closing) { string text2 = "The close process is in progress."; throw new InvalidOperationException(text2); } if (_readyState == WebSocketState.Closed) { string text3 = "The connection has already been closed."; throw new InvalidOperationException(text3); } Func<bool> acceptor = accept; acceptor.BeginInvoke(delegate(IAsyncResult ar) { if (acceptor.EndInvoke(ar)) { open(); } }, null); } public void Close() { close(1005, string.Empty); } public void Close(ushort code) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_client && code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } if (!_client && code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } close(code, string.Empty); } public void Close(CloseStatusCode code) { if (_client && code == CloseStatusCode.ServerError) { string text = "ServerError cannot be used."; throw new ArgumentException(text, "code"); } if (!_client && code == CloseStatusCode.MandatoryExtension) { string text2 = "MandatoryExtension cannot be used."; throw new ArgumentException(text2, "code"); } close((ushort)code, string.Empty); } public void Close(ushort code, string reason) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_client && code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } if (!_client && code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { close(code, string.Empty); return; } if (code == 1005) { string text4 = "1005 cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } close(code, reason); } public void Close(CloseStatusCode code, string reason) { if (_client && code == CloseStatusCode.ServerError) { string text = "ServerError cannot be used."; throw new ArgumentException(text, "code"); } if (!_client && code == CloseStatusCode.MandatoryExtension) { string text2 = "MandatoryExtension cannot be used."; throw new ArgumentException(text2, "code"); } if (reason.IsNullOrEmpty()) { close((ushort)code, string.Empty); return; } if (code == CloseStatusCode.NoStatus) { string text3 = "NoStatus cannot be used."; throw new ArgumentException(text3, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text4 = "It could not be UTF-8-encoded."; throw new ArgumentException(text4, "reason"); } if (bytes.Length > 123) { string text5 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text5); } close((ushort)code, reason); } public void CloseAsync() { closeAsync(1005, string.Empty); } public void CloseAsync(ushort code) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_client && code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } if (!_client && code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } closeAsync(code, string.Empty); } public void CloseAsync(CloseStatusCode code) { if (_client && code == CloseStatusCode.ServerError) { string text = "ServerError cannot be used."; throw new ArgumentException(text, "code"); } if (!_client && code == CloseStatusCode.MandatoryExtension) { string text2 = "MandatoryExtension cannot be used."; throw new ArgumentException(text2, "code"); } closeAsync((ushort)code, string.Empty); } public void CloseAsync(ushort code, string reason) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_client && code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } if (!_client && code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { closeAsync(code, string.Empty); return; } if (code == 1005) { string text4 = "1005 cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } closeAsync(code, reason); } public void CloseAsync(CloseStatusCode code, string reason) { if (_client && code == CloseStatusCode.ServerError) { string text = "ServerError cannot be used."; throw new ArgumentException(text, "code"); } if (!_client && code == CloseStatusCode.MandatoryExtension) { string text2 = "MandatoryExtension cannot be used."; throw new ArgumentException(text2, "code"); } if (reason.IsNullOrEmpty()) { closeAsync((ushort)code, string.Empty); return; } if (code == CloseStatusCode.NoStatus) { string text3 = "NoStatus cannot be used."; throw new ArgumentException(text3, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text4 = "It could not be UTF-8-encoded."; throw new ArgumentException(text4, "reason"); } if (bytes.Length > 123) { string text5 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text5); } closeAsync((ushort)code, reason); } public void Connect() { if (!_client) { string text = "This instance is not a client."; throw new InvalidOperationException(text); } if (_readyState == WebSocketState.Closing) { string text2 = "The close process is in progress."; throw new InvalidOperationException(text2); } if (_retryCountForConnect > _maxRetryCountForConnect) { string text3 = "A series of reconnecting has failed."; throw new InvalidOperationException(text3); } if (connect()) { open(); } } public void ConnectAsync() { if (!_client) { string text = "This instance is not a client."; throw new InvalidOperationException(text); } if (_readyState == WebSocketState.Closing) { string text2 = "The close process is in progress."; throw new InvalidOperationException(text2); } if (_retryCountForConnect > _maxRetryCountForConnect) { string text3 = "A series of reconnecting has failed."; throw new InvalidOperationException(text3); } Func<bool> connector = connect; connector.BeginInvoke(delegate(IAsyncResult ar) { if (connector.EndInvoke(ar)) { open(); } }, null); } public bool Ping() { return ping(EmptyBytes); } public bool Ping(string message) { if (message.IsNullOrEmpty()) { return ping(EmptyBytes); } if (!message.TryGetUTF8EncodedBytes(out var bytes)) { string text = "It could not be UTF-8-encoded."; throw new ArgumentException(text, "message"); } if (bytes.Length > 125) { string text2 = "Its size is greater than 125 bytes."; throw new ArgumentOutOfRangeException("message", text2); } return ping(bytes); } public void Send(byte[] data) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } send(Opcode.Binary, new MemoryStream(data)); } public void Send(FileInfo fileInfo) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (fileInfo == null) { throw new ArgumentNullException("fileInfo"); } if (!fileInfo.Exists) { string text2 = "The file does not exist."; throw new ArgumentException(text2, "fileInfo"); } if (!fileInfo.TryOpenRead(out var fileStream)) { string text3 = "The file could not be opened."; throw new ArgumentException(text3, "fileInfo"); } send(Opcode.Binary, fileStream); } public void Send(string data) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } if (!data.TryGetUTF8EncodedBytes(out var bytes)) { string text2 = "It could not be UTF-8-encoded."; throw new ArgumentException(text2, "data"); } send(Opcode.Text, new MemoryStream(bytes)); } public void Send(Stream stream, int length) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { string text2 = "It cannot be read."; throw new ArgumentException(text2, "stream"); } if (length < 1) { string text3 = "Less than 1."; throw new ArgumentException(text3, "length"); } byte[] array = stream.ReadBytes(length); int num = array.Length; if (num == 0) { string text4 = "No data could be read from it."; throw new ArgumentException(text4, "stream"); } if (num < length) { _logger.Warn($"Only {num} byte(s) of data could be read from the stream."); } send(Opcode.Binary, new MemoryStream(array)); } public void SendAsync(byte[] data, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } sendAsync(Opcode.Binary, new MemoryStream(data), completed); } public void SendAsync(FileInfo fileInfo, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (fileInfo == null) { throw new ArgumentNullException("fileInfo"); } if (!fileInfo.Exists) { string text2 = "The file does not exist."; throw new ArgumentException(text2, "fileInfo"); } if (!fileInfo.TryOpenRead(out var fileStream)) { string text3 = "The file could not be opened."; throw new ArgumentException(text3, "fileInfo"); } sendAsync(Opcode.Binary, fileStream, completed); } public void SendAsync(string data, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } if (!data.TryGetUTF8EncodedBytes(out var bytes)) { string text2 = "It could not be UTF-8-encoded."; throw new ArgumentException(text2, "data"); } sendAsync(Opcode.Text, new MemoryStream(bytes), completed); } public void SendAsync(Stream stream, int length, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The current state of the connection is not Open."; throw new InvalidOperationException(text); } if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { string text2 = "It cannot be read."; throw new ArgumentException(text2, "stream"); } if (length < 1) { string text3 = "Less than 1."; throw new ArgumentException(text3, "length"); } byte[] array = stream.ReadBytes(length); int num = array.Length; if (num == 0) { string text4 = "No data could be read from it."; throw new ArgumentException(text4, "stream"); } if (num < length) { _logger.Warn($"Only {num} byte(s) of data could be read from the stream."); } sendAsync(Opcode.Binary, new MemoryStream(array), completed); } public void SetCookie(WebSocketSharp.Net.Cookie cookie) { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (cookie == null) { throw new ArgumentNullException("cookie"); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); return; } lock (_cookies.SyncRoot) { _cookies.SetOrRemove(cookie); } } } public void SetCredentials(string username, string password, bool preAuth) { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } if (!username.IsNullOrEmpty() && (Ext.Contains(username, ':') || !username.IsText())) { text = "It contains an invalid character."; throw new ArgumentException(text, "username"); } if (!password.IsNullOrEmpty() && !password.IsText()) { text = "It contains an invalid character."; throw new ArgumentException(text, "password"); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text); } else if (username.IsNullOrEmpty()) { _credentials = null; _preAuth = false; } else { _credentials = new WebSocketSharp.Net.NetworkCredential(username, password, _uri.PathAndQuery); _preAuth = preAuth; } } } public void SetProxy(string url, string username, string password) { string text = null; if (!_client) { text = "This instance is not a client."; throw new InvalidOperationException(text); } Uri result = null; if (!url.IsNullOrEmpty()) { if (!Uri.TryCreate(url, UriKind.Absolute, out result)) { text = "Not an absolute URI string."; throw new ArgumentException(text, "url"); } if (result.Scheme != "http") { text = "The scheme part is not http."; throw new ArgumentException(text, "url"); } if (result.Segments.Length > 1) { text = "It includes the path segments."; throw new ArgumentException(text, "url"); } } if (!username.IsNullOrEmpty() && (Ext.Contains(username, ':') || !username.IsText())) { text = "It contains an invalid character."; throw new ArgumentException(text, "username"); } if (!password.IsNullOrEmpty() && !password.IsText()) { text = "It contains an invalid character."; throw new ArgumentException(text, "password"); } if (!canSet(out text)) { _logger.Warn(text); return; } lock (_forState) { if (!canSet(out text)) { _logger.Warn(text);