Decompiled source of Archipelago v3.5.0
Archipelago.MultiClient.Net.dll
Decompiled 10 hours 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.Colors; 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 © 2026")] [assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")] [assembly: AssemblyFileVersion("6.7.1.0")] [assembly: AssemblyInformationalVersion("6.7.1+0c57591db30f2497b0b4fef87164aa2bbe2e51b2")] [assembly: AssemblyProduct("Archipelago.MultiClient.Net")] [assembly: AssemblyTitle("Archipelago.MultiClient.Net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")] [assembly: AssemblyVersion("6.7.1.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); } public class AttemptingStringEnumConverter : StringEnumConverter { public AttemptingStringEnumConverter() { } public AttemptingStringEnumConverter(Type namingStrategyType) : base(namingStrategyType) { } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { try { return ((StringEnumConverter)this).ReadJson(reader, objectType, existingValue, serializer); } catch (JsonSerializationException) { return objectType.IsValueType ? Activator.CreateInstance(objectType) : null; } } } 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 interface IArchipelagoSession : IArchipelagoSessionActions { IArchipelagoSocketHelper Socket { get; } IReceivedItemsHelper Items { get; } ILocationCheckHelper Locations { get; } IPlayerHelper Players { get; } IDataStorageHelper DataStorage { get; } IConnectionInfoProvider ConnectionInfo { get; } IRoomStateHelper RoomState { get; } IMessageLogHelper MessageLog { get; } IHintsHelper Hints { get; } Task<RoomInfoPacket> ConnectAsync(); Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true); LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true); } public class ArchipelagoSession : IArchipelagoSession, IArchipelagoSessionActions { 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; } public IHintsHelper Hints { get; } internal ArchipelagoSession(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog, IHintsHelper createHints) { Socket = socket; Items = items; Locations = locations; Players = players; RoomState = roomState; connectionInfo = connectionInfoHelper; DataStorage = dataStorage; MessageLog = messageLog; Hints = createHints; 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); } } else { loginResultTask.TrySetResult(LoginResult.FromPacket(packet)); } } 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.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, 6, 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 interface IArchipelagoSessionActions { void Say(string message); void SetClientState(ArchipelagoClientState state); void SetGoalAchieved(); } 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 roomStateHelper = new RoomStateHelper(socket, locationCheckHelper); DataStorageHelper dataStorageHelper = new DataStorageHelper(socket, connectionInfoHelper); MessageLogHelper messageLog = new MessageLogHelper(socket, itemInfoResolver, playerHelper, connectionInfoHelper); HintsHelper createHints = new HintsHelper(socket, playerHelper, locationCheckHelper, roomStateHelper, dataStorageHelper); return new ArchipelagoSession(socket, items, locationCheckHelper, playerHelper, roomStateHelper, connectionInfoHelper, dataStorageHelper, messageLog, createHints); } 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(AttemptingStringEnumConverter))] 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 CreateHintsPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.CreateHints; [JsonProperty("locations")] public long[] Locations { get; set; } [JsonProperty("player")] public int Player { get; set; } [JsonProperty("status")] public HintStatus Status { 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(AttemptingStringEnumConverter))] 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; } public class UpdateHintPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.UpdateHint; [JsonProperty("player")] public int Player { get; set; } [JsonProperty("location")] public long Location { get; set; } [JsonProperty("status")] public HintStatus Status { get; set; } } } 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_00d8: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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; } [JsonProperty("status")] public HintStatus Status { 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 SerializableItemInfo ToSerializable() { return new SerializableItemInfo { IsScout = (GetType() == typeof(ScoutedItemInfo)), ItemId = ItemId, LocationId = LocationId, PlayerSlot = Player, Player = Player, Flags = Flags, ItemGame = ItemGame, ItemName = ItemName, LocationGame = LocationGame, LocationName = LocationName }; } } public class ScoutedItemInfo : ItemInfo { public new PlayerInfo Player => base.Player; public bool IsReceiverRelatedToActivePlayer { get; } public ScoutedItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, IPlayerHelper players, PlayerInfo player) : base(item, receiverGame, senderGame, itemInfoResolver, player) { IsReceiverRelatedToActivePlayer = (players.ActivePlayer ?? new PlayerInfo()).IsRelatedTo(player); } } public class JsonMessagePart { [JsonProperty("type")] [JsonConverter(typeof(AttemptingStringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public JsonMessagePartType? Type { get; set; } [JsonProperty("color")] [JsonConverter(typeof(AttemptingStringEnumConverter), 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; } [JsonProperty("hint_status")] public HintStatus? HintStatus { 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(AttemptingStringEnumConverter), 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 }; } } public class MinimalSerializableItemInfo { public long ItemId { get; set; } public long LocationId { get; set; } public int PlayerSlot { get; set; } public ItemFlags Flags { get; set; } public string ItemGame { get; set; } public string LocationGame { get; set; } } public class SerializableItemInfo : MinimalSerializableItemInfo { public bool IsScout { get; set; } public PlayerInfo Player { get; set; } public string ItemName { get; set; } public string LocationName { get; set; } [JsonIgnore] public string ItemDisplayName => ItemName ?? $"Item: {base.ItemId}"; [JsonIgnore] public string LocationDisplayName => LocationName ?? $"Location: {base.LocationId}"; public string ToJson(bool full = false) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown MinimalSerializableItemInfo minimalSerializableItemInfo = this; if (!full) { minimalSerializableItemInfo = new MinimalSerializableItemInfo { ItemId = base.ItemId, LocationId = base.LocationId, PlayerSlot = base.PlayerSlot, Flags = base.Flags }; if (IsScout) { minimalSerializableItemInfo.ItemGame = base.ItemGame; } else { minimalSerializableItemInfo.LocationGame = base.LocationGame; } } JsonSerializerSettings val = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, Formatting = (Formatting)0 }; return JsonConvert.SerializeObject((object)minimalSerializableItemInfo, val); } public static SerializableItemInfo FromJson(string json, IArchipelagoSession session = null) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown ItemInfoStreamingContext additional = ((session != null) ? new ItemInfoStreamingContext { Items = session.Items, Locations = session.Locations, PlayerHelper = session.Players, ConnectionInfo = session.ConnectionInfo } : null); JsonSerializerSettings val = new JsonSerializerSettings { Context = new StreamingContext(StreamingContextStates.Other, additional) }; return JsonConvert.DeserializeObject<SerializableItemInfo>(json, val); } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext streamingContext) { if (base.ItemGame == null && base.LocationGame != null) { IsScout = false; } else if (base.ItemGame != null && base.LocationGame == null) { IsScout = true; } if (streamingContext.Context is ItemInfoStreamingContext itemInfoStreamingContext) { if (IsScout && base.LocationGame == null) { base.LocationGame = itemInfoStreamingContext.ConnectionInfo.Game; } else if (!IsScout && base.ItemGame == null) { base.ItemGame = itemInfoStreamingContext.ConnectionInfo.Game; } if (ItemName == null) { ItemName = itemInfoStreamingContext.Items.GetItemName(base.ItemId, base.ItemGame); } if (LocationName == null) { LocationName = itemInfoStreamingContext.Locations.GetLocationNameFromId(base.LocationId, base.LocationGame); } if (Player == null) { Player = itemInfoStreamingContext.PlayerHelper.GetPlayerInfo(base.PlayerSlot); } } } } internal class ItemInfoStreamingContext { public IReceivedItemsHelper Items { get; set; } public ILocationCheckHelper Locations { get; set; } public IPlayerHelper PlayerHelper { get; set; } public IConnectionInfoProvider ConnectionInfo { get; set; } } } namespace Archipelago.MultiClient.Net.MessageLog.Parts { public class EntranceMessagePart : MessagePart { internal EntranceMessagePart(JsonMessagePart messagePart) : base(MessagePartType.Entrance, messagePart, Archipelago.MultiClient.Net.Colors.PaletteColor.Blue) { base.Text = messagePart.Text; } } public class HintStatusMessagePart : MessagePart { internal HintStatusMessagePart(JsonMessagePart messagePart) : base(MessagePartType.HintStatus, messagePart) { base.Text = messagePart.Text; if (messagePart.HintStatus.HasValue) { base.PaletteColor = ColorUtils.GetColor(messagePart.HintStatus.Value); } } } 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.PaletteColor = ColorUtils.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; } } } } public class LocationMessagePart : MessagePart { public long LocationId { get; } public int Player { get; } internal LocationMessagePart(IPlayerHelper players, IItemInfoResolver itemInfoResolver, JsonMessagePart part) : base(MessagePartType.Location, part, Archipelago.MultiClient.Net.Colors.PaletteColor.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 => GetColor(BuiltInPalettes.Dark); public PaletteColor? PaletteColor { get; protected set; } public bool IsBackgroundColor { get; internal set; } internal MessagePart(MessagePartType type, JsonMessagePart messagePart, PaletteColor? color = null) { Type = type; Text = messagePart.Text; if (color.HasValue) { PaletteColor = color.Value; } else if (messagePart.Color.HasValue) { PaletteColor = ColorUtils.GetColor(messagePart.Color.Value); IsBackgroundColor = messagePart.Color.Value >= JsonMessagePartColor.BlackBg; } else { PaletteColor = null; } } public T GetColor<T>(Palette<T> palette) { return palette[PaletteColor]; } public override string ToString() { return Text; } } public enum MessagePartType { Text, Player, Item, Location, Entrance, HintStatus } 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.PaletteColor = (IsActivePlayer ? Archipelago.MultiClient.Net.Colors.PaletteColor.Magenta : Archipelago.MultiClient.Net.Colors.PaletteColor.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, int team, int slot, string message) : base(parts, players, team, slot) { Message = message; } } public class CollectLogMessage : PlayerSpecificLogMessage { internal CollectLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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, int team, int slot) : base(parts, players, team, slot) { } } public class HintItemSendLogMessage : ItemSendLogMessage { public bool IsFound { get; } internal HintItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, bool found, IItemInfoResolver itemInfoResolver) : base(parts, players, receiver, sender, item, itemInfoResolver) { IsFound = found; } } public class ItemCheatLogMessage : ItemSendLogMessage { internal ItemCheatLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot, NetworkItem item, IItemInfoResolver itemInfoResolver) : base(parts, players, slot, 0, item, team, itemInfoResolver) { } } public class ItemSendLogMessage : LogMessage { private PlayerInfo ActivePlayer { get; } public PlayerInfo Receiver { get; } public PlayerInfo Sender { get; } public bool IsReceiverTheActivePlayer => Receiver == ActivePlayer; public bool IsSenderTheActivePlayer => Sender == ActivePlayer; public bool IsRelatedToActivePlayer { get { if (!ActivePlayer.IsRelatedTo(Receiver)) { return ActivePlayer.IsRelatedTo(Sender); } return true; } } public ItemInfo Item { get; } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, IItemInfoResolver itemInfoResolver) : this(parts, players, receiver, sender, item, players.ActivePlayer.Team, itemInfoResolver) { } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, int team, IItemInfoResolver itemInfoResolver) : base(parts) { ActivePlayer = players.ActivePlayer ?? new PlayerInfo(); Receiver = players.GetPlayerInfo(team, receiver) ?? new PlayerInfo(); Sender = players.GetPlayerInfo(team, sender) ?? new PlayerInfo(); PlayerInfo player = players.GetPlayerInfo(team, item.Player) ?? new PlayerInfo(); Item = new ItemInfo(item, Receiver.Game, Sender.Game, itemInfoResolver, player); } } public class JoinLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal JoinLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot, string[] tags) : base(parts, players, team, slot) { Tags = tags; } } public class LeaveLogMessage : PlayerSpecificLogMessage { internal LeaveLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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 { private PlayerInfo ActivePlayer { get; } public PlayerInfo Player { get; } public bool IsActivePlayer => Player == ActivePlayer; public bool IsRelatedToActivePlayer => ActivePlayer.IsRelatedTo(Player); internal PlayerSpecificLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts) { ActivePlayer = players.ActivePlayer ?? new PlayerInfo(); Player = players.GetPlayerInfo(team, slot) ?? new PlayerInfo(); } } public class ReleaseLogMessage : PlayerSpecificLogMessage { internal ReleaseLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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, int team, int slot, string[] tags) : base(parts, players, team, slot) { Tags = tags; } } public class TutorialLogMessage : LogMessage { internal TutorialLogMessage(MessagePart[] parts) : base(parts) { } } } namespace Archipelago.MultiClient.Net.Helpers { public class ArchipelagoSocketHelper : BaseArchipelagoSocketHelper<ClientWebSocket>, IArchipelagoSocketHelper { public Uri Uri { get; } internal ArchipelagoSocketHelper(Uri hostUri) : base(CreateWebSocket(), 1024) { Uri = hostUri; SecurityProtocolType securityProtocolType = SecurityProtocolType.Tls13; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | securityProtocolType; } private static ClientWebSocket CreateWebSocket() { return new ClientWebSocket(); } public async Task ConnectAsync() { await ConnectToProvidedUri(Uri); StartPolling(); } private async Task ConnectToProvidedUri(Uri uri) { if (uri.Scheme != "unspecified") { try { await Socket.ConnectAsync(uri, CancellationToken.None); return; } catch (Exception e) { OnError(e); throw; } } List<Exception> errors = new List<Exception>(0); try { await Socket.ConnectAsync(uri.AsWss(), CancellationToken.None); if (Socket.State == WebSocketState.Open) { return; } } catch (Exception item) { errors.Add(item); Socket = CreateWebSocket(); } try { await Socket.ConnectAsync(uri.AsWs(), CancellationToken.None); } catch (Exception item2) { errors.Add(item2); OnError(new AggregateException(errors)); throw; } } } public class BaseArchipelagoSocketHelper<T> where T : WebSocket { private static readonly ArchipelagoPacketConverter Converter = new ArchipelagoPacketConverter(); private readonly BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>> sendQueue = new BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>>(); internal T Socket; private readonly int bufferSize; public bool Connected { get { if (Socket.State != WebSocketState.Open) { return Socket.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 BaseArchipelagoSocketHelper(T socket, int bufferSize = 1024) { Socket = socket; this.bufferSize = bufferSize; } internal void StartPolling() { if (this.SocketOpened != null) { this.SocketOpened(); } Task.Run((Func<Task?>)PollingLoop); Task.Run((Func<Task?>)SendLoop); } private async Task PollingLoop() { byte[] buffer = new byte[bufferSize]; while (Socket.State == WebSocketState.Open) { string message = null; try { message = await ReadMessageAsync(buffer); } catch (Exception e) { OnError(e); } OnMessageReceived(message); } } private async Task SendLoop() { while (Socket.State == WebSocketState.Open) { try { await HandleSendBuffer(); } catch (Exception e) { OnError(e); } await Task.Delay(20); } } private async Task<string> ReadMessageAsync(byte[] buffer) { using MemoryStream readStream = new MemoryStream(buffer.Length); WebSocketReceiveResult result; do { result = await Socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { try { await Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } catch { } OnSocketClosed(); } else { readStream.Write(buffer, 0, result.Count); } } while (!result.EndOfMessage); return Encoding.UTF8.GetString(readStream.ToArray()); } public async Task DisconnectAsync() { await Socket.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 (Socket.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 / (double)bufferSize); for (int i = 0; i < messagesCount; i++) { int num = bufferSize * i; int num2 = bufferSize; bool endOfMessage = i + 1 == messagesCount; if (num2 * (i + 1) > messageBuffer.Length) { num2 = messageBuffer.Length - num; } await Socket.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 = null; try { list = JsonConvert.DeserializeObject<List<ArchipelagoPacketBase>>(message, (JsonConverter[])(object)new JsonConverter[1] { Converter }); } catch (Exception e) { OnError(e); } if (list == null) { return; } foreach (ArchipelagoPacketBase item in list) { this.PacketReceived(item); } } catch (Exception e2) { OnError(e2); } } protected 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(); } return; } Team = connectedPacket.Team; Slot = connectedPacket.Slot; if (connectedPacket.SlotInfo != null && connectedPacket.SlotInfo.ContainsKey(Slot)) { Game = connectedPacket.SlotInfo[Slot].Game; } } 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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 == 8 && ((string)setReplyPacket.AdditionalArguments["Reference"]).TryParseNGuid(out var g) && operationSpecificCallbacks.TryGetValue(g, out var value)) { value(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments); operationSpecificCallbacks.Remove(g); } 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 key2 = Guid.NewGuid(); operationSpecificCallbacks[key2] = e.Callbacks; dictionary["Reference"] = JToken.op_Implicit(key2.ToString("N")); 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}"]; } private DataStorageElement GetRaceModeElement() { return this[Scope.ReadOnly, "race_mode"]; } 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 GetSlotData<Dictionary<string, object>>(slot); } public T GetSlotData<T>(int? slot = null) where T : class { return GetSlotDataElement(slot).To<T>(); } public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null) { return GetSlotDataAsync<Dictionary<string, object>>(slot); } public Task<T> GetSlotDataAsync<T>(int? slot = null) where T : class { return GetSlotDataElement(slot).GetAsync<T>(); } 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) { Get
ArchipelagoULTRAKILL.dll
Decompiled 10 hours 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 System.Text.RegularExpressions; 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.Config; using ArchipelagoULTRAKILL.Music; 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 ULTRAKILL.Cheats; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; 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("3.5.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("3.5.0.0")] namespace ArchipelagoULTRAKILL { 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 LevelManager { public static Dictionary<string, GameObject> skulls = new Dictionary<string, GameObject>(); public static Door redDoor; 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Invalid comparison between Unknown and I4 //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Invalid comparison between Unknown and I4 //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Invalid comparison between Unknown and I4 //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Invalid comparison between Unknown and I4 //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Invalid comparison between Unknown and I4 //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Invalid comparison between Unknown and I4 //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Invalid comparison between Unknown and I4 //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Invalid comparison between Unknown and I4 //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Invalid comparison between Unknown and I4 //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: 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)) { continue; } if (SceneHelper.CurrentScene == "Level 2-4") { if ((Object)(object)((Component)val).gameObject.transform.parent == (Object)null || ((Object)((Component)val).gameObject.transform.parent.parent).name != "Altar (1)") { continue; } } else if (SceneHelper.CurrentScene == "Level 7-S") { if (((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")) { continue; } } else if (SceneHelper.CurrentScene == "Level 8-1") { if (((Object)((Component)val).gameObject.transform.parent.parent.parent).name != "Inside") { continue; } } else if (SceneHelper.CurrentScene == "Level 8-2") { if (((int)val.itemType == 1 && ((Object)((Component)val).transform.parent.parent).name != "Altar (Blue) (1)") || ((int)val.itemType == 2 && ((Object)((Component)val).transform.parent.parent).name != "Altar (Red) (1)")) { continue; } } else if (SceneHelper.CurrentScene == "Level 8-3") { if (((Object)((Component)val).gameObject.transform.parent.parent.parent).name == "10 Nonstuff") { continue; } } else if (SceneHelper.CurrentScene == "Level 8-4") { if (((int)val.itemType == 1 && ((Object)((Component)val).transform.parent).name != "Bathroom") || ((int)val.itemType == 2 && ((Object)((Component)val).transform.parent.parent).name != "Altar (Red)")) { continue; } } else if (SceneHelper.CurrentScene == "Level 0-E") { if (((int)val.itemType == 1 && Object.op_Implicit((Object)(object)((Component)val).transform.parent.parent.parent)) || ((int)val.itemType == 2 && Object.op_Implicit((Object)(object)((Component)val).transform.parent.parent.parent))) { continue; } } else if (SceneHelper.CurrentScene == "Level 1-E" && (((int)val.itemType == 1 && ((Object)((Component)val).transform.parent.parent).name != "Altar (Blue) (1)") || (int)val.itemType == 2)) { continue; } 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) { DeactivateSkull(keyValuePair.Value); } } else if (((Object)keyValuePair.Value).name.Contains("Blue")) { if (!Core.data.unlockedSkulls.Contains(text + "_b")) { DeactivateSkull(keyValuePair.Value); } } else if (((Object)keyValuePair.Value).name.Contains("Red") && !Core.data.unlockedSkulls.Contains(text + "_r")) { DeactivateSkull(keyValuePair.Value); } } else if (j + 1 > Core.data.unlockedSkulls1_4) { DeactivateSkull(keyValuePair.Value); } } } public static void ActivateSkull(GameObject skull) { ItemPlaceZone val = default(ItemPlaceZone); if (((Component)skull.transform.parent).TryGetComponent<ItemPlaceZone>(ref val)) { val.elementChangeEffect.Play(); InstantiateObject[] altarElements = val.altarElements; foreach (InstantiateObject val2 in altarElements) { ((Component)val2).gameObject.SetActive(true); if (((Component)val2).gameObject.activeInHierarchy) { val2.Instantiate(); } } } else { Core.Logger.LogWarning((object)(((Object)skull).name + " GameObject has no ItemPlaceZone in parent")); } skull.SetActive(true); } public static void DeactivateSkull(GameObject skull) { ItemPlaceZone val = default(ItemPlaceZone); if (((Component)skull.transform.parent).TryGetComponent<ItemPlaceZone>(ref val)) { InstantiateObject[] altarElements = val.altarElements; foreach (InstantiateObject val2 in altarElements) { ((Component)val2).gameObject.SetActive(false); } } else { Core.Logger.LogWarning((object)(((Object)skull).name + " GameObject has no ItemPlaceZone in parent")); } skull.SetActive(false); } 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") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent.parent).gameObject); } } 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") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent.parent).gameObject); } } 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)")) { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent).gameObject); } } 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") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent.parent).gameObject); } } 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")) { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent).gameObject); } } 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") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent).gameObject); } } else if (SceneHelper.CurrentScene == "Level 6-1") { if ((Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "3 - Crossroads") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent).gameObject); } } else if (SceneHelper.CurrentScene == "Level 1-E" && (Object)(object)((Component)val).transform.parent.parent != (Object)null && ((Object)((Component)val).transform.parent.parent).name == "13-3 Connector") { GameObjectExtensions.GetOrAddComponent<ReverseDoorCloser>(((Component)((Component)val).transform.parent.parent).gameObject); } } } 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 class Multiworld : MonoBehaviour { [CompilerGenerated] private sealed class <Connect>d__30 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Multiworld <>4__this; private WeaponLoadout <loadout>5__1; private GameProgressMoneyAndGear <gameProgress>5__2; private LoginResult <loginResult>5__3; private LoginSuccessful <success>5__4; private string <totalLocations>5__5; private Dictionary<string, int>.KeyCollection.Enumerator <>s__6; private string <weapon>5__7; private long <locationId>5__8; private ScoutedItemInfo <info>5__9; private string <itemName>5__10; private string <playerName>5__11; private HashSet<string>.Enumerator <>s__12; private string <loc>5__13; private LoginFailure <failure>5__14; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Connect>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <loadout>5__1 = null; <gameProgress>5__2 = null; <loginResult>5__3 = null; <success>5__4 = null; <totalLocations>5__5 = null; <>s__6 = default(Dictionary<string, int>.KeyCollection.Enumerator); <weapon>5__7 = null; <info>5__9 = null; <itemName>5__10 = null; <playerName>5__11 = null; <>s__12 = default(HashSet<string>.Enumerator); <loc>5__13 = null; <failure>5__14 = null; <>1__state = -2; } private bool MoveNext() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0a75: Unknown result type (might be due to invalid IL or missing references) //IL_0ae2: Unknown result type (might be due to invalid IL or missing references) //IL_0e8a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Expected O, but got Unknown //IL_0ce4: Unknown result type (might be due to invalid IL or missing references) //IL_0ce9: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; if (Authenticated) { return false; } <loadout>5__1 = WeaponLoadout.Get(); Core.Logger.LogInfo((object)"Got loadout"); <gameProgress>5__2 = GameProgressSaver.GetGeneralProgress(); Core.LockAllWeapons(); 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); Core.Logger.LogInfo((object)string.Format("Attempting connection ({0} - {1} / {2})", Core.data.slot_name, apVersion, "3.5.0")); <loginResult>5__3 = Session.TryConnectAndLogin("ULTRAKILL", Core.data.slot_name, (ItemsHandlingFlags)7, apVersion, (string[])null, (string)null, (Core.data.password == "") ? null : Core.data.password, true); ref LoginSuccessful reference = ref <success>5__4; LoginResult obj = <loginResult>5__3; reference = (LoginSuccessful)(object)((obj is LoginSuccessful) ? obj : null); if (<success>5__4 != null) { Core.Logger.LogInfo((object)"Login successful"); Authenticated = true; PlayerConfig.isConnected.value = true; ((ConfigField)PlayerConfig.playerName).interactable = false; ((ConfigField)PlayerConfig.serverAddress).interactable = false; ((ConfigField)PlayerConfig.serverPassword).interactable = false; ((ConfigField)PlayerConfig.hintMode).interactable = false; ((ConfigField)PlayerConfig.chat).interactable = true; if (Core.DataExists()) { <>4__this.DoServerCheck(Session, <success>5__4.SlotData); } else { AllowConnect = true; } <>2__current = (object)new WaitUntil((Func<bool>)(() => AllowConnect.HasValue)); <>1__state = 1; return true; } ref LoginFailure reference2 = ref <failure>5__14; LoginResult obj2 = <loginResult>5__3; reference2 = (LoginFailure)(object)((obj2 is LoginFailure) ? obj2 : null); if (<failure>5__14 != null) { Core.Logger.LogInfo((object)"Login failed"); Authenticated = false; Core.Logger.LogError((object)string.Join("\n", <failure>5__14.Errors)); PlayerConfig.connectionInfo.text = string.Join("\n", <failure>5__14.Errors); Session.Socket.DisconnectAsync(); Session = null; CanGetItems = false; AllowConnect = null; ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; Core.SaveGeneralProgress(<gameProgress>5__2); } <failure>5__14 = null; break; } case 1: <>1__state = -1; if (!AllowConnect.Value) { LocationManager.itemQueue.Clear(); Disconnect(); return false; } Core.data.seed = Session.RoomState.Seed; TryGetSlotDataValue(ref Core.data.version, <success>5__4.SlotData, "version", string.Empty); Core.data.serverVersion = Session.RoomState.GeneratorVersion.ToString(); Core.Logger.LogInfo((object)string.Format("Server version: {0} / {1}", Session.RoomState.Version, (Core.data.version == string.Empty) ? "?" : Core.data.version)); TryGetStart(ref Core.data.unlockedLevels, <success>5__4.SlotData, "0-1"); TryGetGoal(ref Core.data.goal, <success>5__4.SlotData, "6-2"); TryGetSlotDataValue(ref Core.data.goalRequirement, <success>5__4.SlotData, "goal_requirement", 15); TryGetSlotDataValue(ref Core.data.perfectGoal, <success>5__4.SlotData, "perfect_goal", defaultValue: false); TryGetSlotDataValue(ref Core.data.secretExitUnlock, <success>5__4.SlotData, "secret_mission_unlock_type", defaultValue: true); TryGetSlotDataValue(ref Core.data.secretExitComplete, <success>5__4.SlotData, "secret_exit_behavior", defaultValue: true); TryGetEnemyOption(ref Core.data.enemyRewards, <success>5__4.SlotData, "enemy_rewards", EnemyOptions.Disabled); TryGetSlotDataValue(ref Core.data.challengeRewards, <success>5__4.SlotData, "challenge_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.pRankRewards, <success>5__4.SlotData, "p_rank_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.hankRewards, <success>5__4.SlotData, "hank_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.clashReward, <success>5__4.SlotData, "randomize_clash_mode", defaultValue: false); TryGetSlotDataValue(ref Core.data.fishRewards, <success>5__4.SlotData, "fish_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.cleanRewards, <success>5__4.SlotData, "cleaning_rewards", defaultValue: false); TryGetSlotDataValue(ref Core.data.chessReward, <success>5__4.SlotData, "chess_reward", defaultValue: false); TryGetSlotDataValue(ref Core.data.rocketReward, <success>5__4.SlotData, "rocket_race_reward", defaultValue: false); TryGetFire2(ref Core.data.randomizeFire2, <success>5__4.SlotData, "randomize_secondary_fire", Fire2Options.Disabled); TryGetSlotDataValue(ref Core.data.revForm, <success>5__4.SlotData, "revolver_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.shoForm, <success>5__4.SlotData, "shotgun_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.naiForm, <success>5__4.SlotData, "nailgun_form", WeaponForm.Standard); TryGetSlotDataValue(ref Core.data.randomizeSkulls, <success>5__4.SlotData, "randomize_skulls", defaultValue: false); TryGetSlotDataValue(ref Core.data.l1switch, <success>5__4.SlotData, "randomize_limbo_switches", defaultValue: false); TryGetSlotDataValue(ref Core.data.l7switch, <success>5__4.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()) { Core.Logger.LogInfo((object)"Doing first time setup for save file"); 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, <success>5__4.SlotData, "start_with_arm", defaultValue: true); TryGetSlotDataValue(ref Core.data.dashes, <success>5__4.SlotData, "starting_stamina", 3); TryGetSlotDataValue(ref Core.data.walljumps, <success>5__4.SlotData, "starting_walljumps", 3); TryGetSlotDataValue(ref Core.data.canSlide, <success>5__4.SlotData, "start_with_slide", defaultValue: true); TryGetSlotDataValue(ref Core.data.canSlam, <success>5__4.SlotData, "start_with_slam", defaultValue: true); TryGetSlotDataValue(ref Core.data.multiplier, <success>5__4.SlotData, "point_multiplier", 1); TryGetSlotDataValue(ref Core.data.musicRandomizer, <success>5__4.SlotData, "music_randomizer", defaultValue: false); if (Core.data.musicRandomizer) { Core.data.music = JsonConvert.DeserializeObject<Dictionary<string, string>>(<success>5__4.SlotData["music"].ToString()); } TryGetSlotDataValue(ref Core.data.cybergrindHints, <success>5__4.SlotData, "cybergrind_hints", defaultValue: true); try { ColorConfig.uiColorRandomizer.value = (ColorOptions)Enum.Parse(typeof(ColorOptions), <success>5__4.SlotData["ui_color_randomizer"].ToString()); } catch (KeyNotFoundException) { ColorConfig.uiColorRandomizer.value = ColorOptions.Off; } try { ColorConfig.gunColorRandomizer.value = (ColorOptions)Enum.Parse(typeof(ColorOptions), <success>5__4.SlotData["gun_color_randomizer"].ToString()); } catch (KeyNotFoundException) { ColorConfig.gunColorRandomizer.value = ColorOptions.Off; } Core.data.playerCount = Session.Players.Players[0].Count - 1; MonoSingleton<PrefsManager>.Instance.SetInt("difficulty", 4); GameProgressSaver.SetIntro(true); GameProgressSaver.SetTutorial(true); GameProgressSaver.UnlockWeaponCustomization((WeaponCustomizationType)0); GameProgressSaver.UnlockWeaponCustomization((WeaponCustomizationType)1); GameProgressSaver.UnlockWeaponCustomization((WeaponCustomizationType)2); GameProgressSaver.UnlockWeaponCustomization((WeaponCustomizationType)3); GameProgressSaver.UnlockWeaponCustomization((WeaponCustomizationType)4); GameProgressSaver.SaveProgress(34); GameProgressSaver.SetEncoreProgress(101); GameProgressSaver.SetPrime(1, 1); GameProgressSaver.SetPrime(2, 1); Core.SaveData(); if (ColorConfig.uiColorRandomizer.value != 0) { ColorRandomizer.RandomizeUIColors(); } if (ColorConfig.gunColorRandomizer.value != 0) { ColorRandomizer.RandomizeGunColors(); } Core.data.deathLink = bool.Parse(<success>5__4.SlotData["death_link"].ToString()); TryGetSlotDataValue(ref Core.data.deathLinkAmnesty, <success>5__4.SlotData, "death_link_amnesty", 1); } MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm0", 1); LocationManager.locations = ((JToken)(JObject)<success>5__4.SlotData["locations"]).ToObject<Dictionary<string, long>>(); ConfigManager.LoadStats(); LocationManager.RegenerateItemDefinitions(); Core.Logger.LogInfo((object)("Successfully connected to server as player \"" + Core.data.slot_name + "\".")); PlayerConfig.connectionInfo.text = "Successfully connected to server as player \"" + Core.data.slot_name + "\"."; ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Green; if (Core.data.completedLevels.Count < Core.data.goalRequirement) { UIManager.CreateGoalCounter(); } <totalLocations>5__5 = ((LocationManager.locations.Count == 0) ? "?" : LocationManager.locations.Count.ToString()); if (Core.data.deathLink) { EnableDeathLink(); } else { DeathLinkConfig.deathLinkStatus.text = "Death Link is <color=red>OFF</color>"; } Core.Logger.LogInfo((object)"Scouting shop items"); <>s__6 = Core.shopPrices.Keys.GetEnumerator(); try { while (<>s__6.MoveNext()) { <weapon>5__7 = <>s__6.Current; <locationId>5__8 = LocationManager.locations["shop_" + <weapon>5__7]; <info>5__9 = Session.Locations.ScoutLocationsAsync(false, new long[1] { LocationManager.locations["shop_" + <weapon>5__7] }).Result[<locationId>5__8]; <itemName>5__10 = ((ItemInfo)<info>5__9).ItemName; <playerName>5__11 = Session.Players.GetPlayerName(PlayerInfo.op_Implicit(<info>5__9.Player)); if (LocationManager.GetItemDefinition(<itemName>5__10) != null) { LocationManager.shopScouts.Add("shop_" + <weapon>5__7, new UKItem { itemName = <itemName>5__10, playerName = <playerName>5__11, type = LocationManager.GetItemDefinition(<itemName>5__10).Type }); } else { LocationManager.shopScouts.Add("shop_" + <weapon>5__7, new APItem { itemName = <itemName>5__10, playerName = <playerName>5__11, type = ((ItemInfo)<info>5__9).Flags }); } <info>5__9 = null; <itemName>5__10 = null; <playerName>5__11 = null; <weapon>5__7 = null; } } finally { ((IDisposable)<>s__6).Dispose(); } <>s__6 = default(Dictionary<string, int>.KeyCollection.Enumerator); <>s__12 = Core.data.@checked.GetEnumerator(); try { while (<>s__12.MoveNext()) { <loc>5__13 = <>s__12.Current; LocationManager.CheckLocation(<loc>5__13); <loc>5__13 = null; } } finally { ((IDisposable)<>s__12).Dispose(); } <>s__12 = default(HashSet<string>.Enumerator); CanGetItems = true; ((MonoBehaviour)Core.Instance).StartCoroutine("ApplyLoadout", (object)<loadout>5__1); <totalLocations>5__5 = null; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static Version apVersion = new Version(0, 6, 7); public static DeathLinkService DeathLinkService = null; public static DeathLink lastDeathLink = null; public static int currentDeathCount = 0; public static bool Authenticated; public static bool HintMode = false; public static ArchipelagoSession Session; public static List<string> messages = new List<string>(); public GameObject serverCheckBlocker; public TextMeshProUGUI serverCheckText; public static List<RecentItem> recentItems = new List<RecentItem>(); public static bool CanGetItems { get; private set; } = false; public static bool? AllowConnect { get; private set; } = null; public void SetupServerCheckBlocker() { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Expected O, but got Unknown if (!(SceneHelper.CurrentScene != "Main Menu")) { serverCheckBlocker = ((Component)((Component)Object.Instantiate<GameObject>(((Component)((Component)MonoSingleton<OptionsManager>.Instance.optionsMenu).transform.Find("Save Slots").Find("Reload Consent Blocker")).gameObject, UIManager.canvas.transform).transform.GetChild(0)).transform.parent).gameObject; ((Object)serverCheckBlocker).name = "Archipelago Server Check Blocker"; Object.Destroy((Object)(object)serverCheckBlocker.GetComponent<ComponentEvents>()); Object.Destroy((Object)(object)((Component)serverCheckBlocker.transform.Find("Consent")).GetComponent<Image>()); ((Component)serverCheckBlocker.transform.Find("Consent").Find("Panel")).GetComponent<RectTransform>().sizeDelta = new Vector2(0f, 180f); serverCheckText = ((Component)serverCheckBlocker.transform.Find("Consent").Find("Panel").Find("Text")).GetComponent<TextMeshProUGUI>(); GameObject gameObject = ((Component)serverCheckBlocker.transform.Find("Consent").Find("Panel").Find("Yes")).gameObject; ((TMP_Text)gameObject.GetComponentInChildren<TextMeshProUGUI>(true)).text = "YES"; Button component = gameObject.GetComponent<Button>(); ((UnityEventBase)component.onClick).SetPersistentListenerState(0, (UnityEventCallState)0); ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { AllowConnect = true; serverCheckBlocker.SetActive(false); }); GameObject gameObject2 = ((Component)serverCheckBlocker.transform.Find("Consent").Find("Panel").Find("No")).gameObject; ((TMP_Text)gameObject2.GetComponentInChildren<TextMeshProUGUI>(true)).text = "NO"; Button component2 = gameObject2.GetComponent<Button>(); ((UnityEventBase)component2.onClick).SetPersistentListenerState(0, (UnityEventCallState)0); ((UnityEventBase)component2.onClick).RemoveAllListeners(); ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { AllowConnect = false; serverCheckBlocker.SetActive(false); }); } } public void DoServerCheck(ArchipelagoSession session, Dictionary<string, object> slotData) { if (Core.data.seed != session.RoomState.Seed || Core.data.version != slotData["version"].ToString() || Core.data.serverVersion != session.RoomState.GeneratorVersion.ToString()) { ShowServerCheckBlocker(session, slotData); } else { AllowConnect = true; } } public void ShowServerCheckBlocker(ArchipelagoSession session, Dictionary<string, object> slotData) { if (!((Object)(object)serverCheckBlocker == (Object)null)) { ((TMP_Text)serverCheckText).text = "Server does not match saved data.\n\nSaved:\n<size=16>Seed: " + (Utility.IsNullOrWhiteSpace(Core.data.seed) ? "<color=grey>not saved</color>" : Core.data.seed) + "\nWorld Version: " + (Utility.IsNullOrWhiteSpace(Core.data.version) ? "<color=grey>not saved</color>" : Core.data.version) + "\nGenerator Version: " + (Utility.IsNullOrWhiteSpace(Core.data.serverVersion) ? "<color=grey>not saved</color>" : Core.data.serverVersion) + "</size>\n\nServer:\n<size=16>Seed: " + session.RoomState.Seed + string.Format("\nWorld Version: {0}", slotData["version"]) + $"\nGenerator Version: {session.RoomState.GeneratorVersion}</size>" + "\n\nConnect anyway?"; serverCheckBlocker.SetActive(true); } } public static void TryGetStart(ref HashSet<string> unlockedLevels, Dictionary<string, object> slotData, string defaultValue) { try { unlockedLevels.Add(slotData["start"].ToString()); Core.data.start = slotData["start"].ToString(); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)("No key found for start level. Using default value (" + defaultValue + ")")); unlockedLevels.Add(defaultValue); Core.data.start = defaultValue; } } public static void TryGetGoal(ref string goal, Dictionary<string, object> slotData, string defaultValue) { if (int.TryParse(slotData["goal"].ToString(), out var result)) { Core.Logger.LogWarning((object)"Using legacy goal option."); switch (result) { 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; } } else { goal = slotData["goal"].ToString(); } } public static void TryGetEnemyOption(ref EnemyOptions option, Dictionary<string, object> slotData, string key, EnemyOptions defaultValue) { try { option = (EnemyOptions)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { try { option = (EnemyOptions)int.Parse(slotData["boss_rewards"].ToString()); Core.Logger.LogInfo((object)"Using legacy enemy reward option."); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for enemy rewards. Using default value ({defaultValue})"); option = defaultValue; } } } public static void TryGetFire2(ref Fire2Options option, Dictionary<string, object> slotData, string key, Fire2Options defaultValue) { if (bool.TryParse(slotData[key].ToString(), out var result)) { Core.Logger.LogInfo((object)"Using legacy secondary fire option."); if (result) { option = Fire2Options.Split; } else { option = Fire2Options.Disabled; } return; } try { option = (Fire2Options)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 string option, Dictionary<string, object> slotData, string key, string defaultValue) { try { option = 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 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 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; } } [IteratorStateMachine(typeof(<Connect>d__30))] public IEnumerator Connect() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Connect>d__30(0) { <>4__this = this }; } public static bool ConnectBK() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) if (Authenticated) { return true; } 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); LoginResult val = Session.TryConnectAndLogin("", Core.data.slot_name, (ItemsHandlingFlags)0, apVersion, new string[1] { "HintGame" }, (string)null, (Core.data.password == "") ? null : Core.data.password, false); LoginSuccessful val2 = (LoginSuccessful)(object)((val is LoginSuccessful) ? val : null); if (val2 != null) { Authenticated = true; HintMode = true; PlayerConfig.isConnected.value = true; ((ConfigField)PlayerConfig.playerName).interactable = false; ((ConfigField)PlayerConfig.serverAddress).interactable = false; ((ConfigField)PlayerConfig.serverPassword).interactable = false; ((ConfigField)PlayerConfig.hintMode).interactable = false; ((ConfigField)PlayerConfig.chat).interactable = true; Core.Logger.LogInfo((object)("Successfully connected to server in hint mode as player \"" + Core.data.slot_name + "\".")); PlayerConfig.connectionInfo.text = "Successfully connected to server in hint mode as player \"" + Core.data.slot_name + "\"."; ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Green; } else { LoginFailure val3 = (LoginFailure)(object)((val is LoginFailure) ? val : null); if (val3 != null) { Authenticated = false; HintMode = false; Core.Logger.LogError((object)string.Join("\n", val3.Errors)); PlayerConfig.connectionInfo.text = string.Join("\n", val3.Errors); Session.Socket.DisconnectAsync(); Session = null; ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } } return val.Successful; } public static void Disconnect() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) PlayerConfig.isConnected.value = false; ((ConfigField)PlayerConfig.playerName).interactable = true; ((ConfigField)PlayerConfig.serverAddress).interactable = true; ((ConfigField)PlayerConfig.serverPassword).interactable = true; ((ConfigField)PlayerConfig.hintMode).interactable = true; ((ConfigField)PlayerConfig.chat).interactable = false; if (Session != null && Session.Socket != null) { Session.Socket.DisconnectAsync(); } if (SceneHelper.CurrentScene == "Main Menu") { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } UIManager.SetLogText(""); messages.Clear(); LocationManager.shopScouts = new Dictionary<string, AItem>(); Session = null; DeathLinkService = null; Authenticated = false; HintMode = false; CanGetItems = false; AllowConnect = null; } public static void SocketClosed(string reason) { Core.Logger.LogError((object)("Lost connection to Archipelago server. " + reason)); Disconnect(); } public static void ErrorReceived(Exception e, string message) { Core.Logger.LogError((object)message); if (e != null) { Core.Logger.LogError((object)e.ToString()); } Disconnect(); } public static void PacketReceived(ArchipelagoPacketBase packet) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Invalid comparison between Unknown and I4 //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_0580: Unknown result type (might be due to invalid IL or missing references) //IL_059a: Expected I4, but got Unknown //IL_07ec: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05d4: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Unknown result type (might be due to invalid IL or missing references) //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06ad: Unknown result type (might be due to invalid IL or missing references) //IL_06b0: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Expected I4, but got Unknown //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_06cd: Unknown result type (might be due to invalid IL or missing references) //IL_06ea: Unknown result type (might be due to invalid IL or missing references) //IL_0707: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) ArchipelagoPacketType packetType = packet.PacketType; ArchipelagoPacketType val = packetType; if ((int)val != 6) { return; } if (messages.Count >= UIManager.lines) { messages.RemoveAt(0); } PrintJsonPacket val2 = (PrintJsonPacket)(object)((packet is PrintJsonPacket) ? packet : null); string text = ""; string text2 = ""; string text3 = "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.White) + "FF>"; if ((int)val2.Data[0].Type.GetValueOrDefault() == 1 && Session.Players.GetPlayerName(int.Parse(val2.Data[0].Text)) == Core.data.slot_name && val2.Data[1].Text == " found their ") { string locationNameFromId = Session.Locations.GetLocationNameFromId(long.Parse(val2.Data[4].Text), (string)null); string itemName = Session.Items.GetItemName(long.Parse(val2.Data[2].Text), (string)null); ItemFlags value = val2.Data[2].Flags.Value; string text4 = ""; string locationColor = null; if (locationNameFromId.StartsWith("Enemy:") || locationNameFromId.StartsWith("Boss:")) { text4 = LocationManager.GetCurrentLevelImage(); locationColor = Core.CurrentLevelInfo?.Name; } else { text4 = LocationManager.GetLocationImage(locationNameFromId); } Core.data.recentLocations.Add(new RecentLocation(locationNameFromId, text4, locationColor, itemName, value, Core.data.slot_name)); if (Core.data.recentLocations.Count > 5) { Core.data.recentLocations.RemoveAt(0); } } else if ((int)val2.Data[0].Type.GetValueOrDefault() == 1 && Session.Players.GetPlayerName(int.Parse(val2.Data[0].Text)) == Core.data.slot_name && val2.Data[1].Text == " sent ") { string itemName2 = Session.Items.GetItemName(long.Parse(val2.Data[2].Text), Session.Players.GetPlayerInfo(val2.Data[2].Player.Value).Game); ItemFlags value2 = val2.Data[2].Flags.Value; string playerAlias = Session.Players.GetPlayerAlias(int.Parse(val2.Data[4].Text)); string locationNameFromId2 = Session.Locations.GetLocationNameFromId(long.Parse(val2.Data[6].Text), (string)null); string text5 = ""; string locationColor2 = null; if (locationNameFromId2.StartsWith("Enemy:") || locationNameFromId2.StartsWith("Boss:")) { text5 = LocationManager.GetCurrentLevelImage(); locationColor2 = Core.CurrentLevelInfo?.Name; } else { text5 = LocationManager.GetLocationImage(locationNameFromId2); } Core.data.recentLocations.Add(new RecentLocation(locationNameFromId2, text5, locationColor2, itemName2, value2, playerAlias)); if (Core.data.recentLocations.Count > 5) { Core.data.recentLocations.RemoveAt(0); } Color white = Color.white; if (LocationManager.GetItemDefinition(itemName2) != null) { white = LocationManager.GetItemDefinition(itemName2).Color(); LocationManager.messages.Add(new Message { image = LocationManager.GetItemDefinition(itemName2).Image, color = Colors.Gray, message = "FOUND: <color=#" + ColorUtility.ToHtmlStringRGBA(white) + ">" + itemName2.ToUpper() + "</color> (<color=#" + ColorUtility.ToHtmlStringRGBA(Colors.PlayerOther) + ">" + playerAlias + "</color>)" }); } else { white = LocationManager.GetAPMessageColor(val2.Data[2].Flags.Value); LocationManager.messages.Add(new Message { image = LocationManager.GetAPImage(val2.Data[2].Flags.Value), color = LocationManager.GetAPMessageColor(val2.Data[2].Flags.Value), message = "FOUND: <color=#" + ColorUtility.ToHtmlStringRGBA(white) + ">" + itemName2.ToUpper() + "</color> (<color=#" + ColorUtility.ToHtmlStringRGBA(Colors.PlayerOther) + ">" + playerAlias + "</color>)" }); } } JsonMessagePart[] data = val2.Data; foreach (JsonMessagePart val3 in data) { switch (val3.Type) { case 0L: { text3 = ((!(Session.Players.GetPlayerName(int.Parse(val3.Text)) == Core.data.slot_name)) ? ("<color=#" + ColorUtility.ToHtmlStringRGB(Colors.PlayerOther) + "FF>") : ("<color=#" + ColorUtility.ToHtmlStringRGB(Colors.PlayerSelf) + "FF>")); if (int.TryParse(val3.Text, out var result3)) { string text8 = Session.Players.GetPlayerAlias(result3) ?? $"Slot: {result3}"; text = text + text3 + text8 + "</color>"; text2 += text8; } else { text = text + text3 + val3.Text + "</color>"; text2 += val3.Text; } break; } case 2L: { text3 = val3.Flags switch { 0L => "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemAdvancement) + "FF>", 1L => "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemNeverExclude) + "FF>", 3L => "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemTrap) + "FF>", _ => "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.ItemFiller) + "FF>", }; if (long.TryParse(val3.Text, out var result2)) { string text7 = Session.Items.GetItemName(result2, Session.Players.GetPlayerInfo(val3.Player.Value).Game) ?? $"Item: {result2}"; text = text + text3 + text7 + "</color>"; text2 += text7; } else { text = text + text3 + val3.Text + "</color>"; text2 += val3.Text; } break; } case 4L: { text3 = "<color=#" + ColorUtility.ToHtmlStringRGB(Colors.Location) + "FF>"; if (long.TryParse(val3.Text, out var result)) { string text6 = Session.Locations.GetLocationNameFromId(result, Session.Players.GetPlayerInfo(val3.Player.Value).Game) ?? $"Location: {result}"; text = text + text3 + text6 + "</color>"; text2 += text6; } else { text = text + text3 + val3.Text + "</color>"; text2 += val3.Text; } break; } default: text += val3.Text; text2 += val3.Text; break; } } messages.Add(text); UIManager.SetLogText(string.Join("\n", messages.ToArray())); } public static void ItemReceived(ReceivedItemsHelper helper) { bool flag = LocationManager.ShouldGetItemAgain(LocationManager.GetItemDefinition(helper.PeekItem().ItemName).Type); bool silent = helper.Index <= Core.data.index && flag; if (helper.Index > Core.data.index || flag) { ItemInfo val = helper.PeekItem(); string itemName = val.ItemName; string playerName = Session.Players.GetPlayerName(PlayerInfo.op_Implicit(val.Player)); playerName = ((!(playerName == Core.data.slot_name)) ? ((Session.Players.GetPlayerAlias(PlayerInfo.op_Implicit(val.Player)) == "") ? "?" : Session.Players.GetPlayerAlias(PlayerInfo.op_Implicit(val.Player))) : null); if (helper.Index > Core.data.index) { Core.Logger.LogInfo((object)("Name: \"" + itemName + "\" | Type: " + LocationManager.GetItemDefinition(itemName).Type.ToString() + " | Player: \"" + playerName + "\"")); } UKType type = LocationManager.GetItemDefinition(itemName).Type; UKItem item = new UKItem { itemName = itemName, type = type, playerName = Core.data.slot_name }; LocationManager.itemQueue.Add(new QueuedItem(item, playerName, silent)); recentItems.Add(new RecentItem(itemName, playerName, helper.Index)); if (recentItems.Count > 5) { recentItems.RemoveAt(0); } if (helper.Index > Core.data.index) { Core.data.index++; } } helper.DequeueItem(); } public static void EnableDeathLink() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (DeathLinkService == null) { DeathLinkService = DeathLinkProvider.CreateDeathLinkService(Session); DeathLinkService.OnDeathLinkReceived += new DeathLinkReceivedHandler(DeathLinkReceived); } DeathLinkService.EnableDeathLink(); Core.data.deathLink = true; DeathLinkConfig.deathLinkStatus.text = "Death Link is <color=green>ON</color>"; DeathLinkConfig.UpdateDeathLinkCount(); if (Core.IsInLevel && (Object)(object)Core.uim.deathLinkMessage == (Object)null) { Core.uim.CreateDeathLinkMessage(); } } public static void DisableDeathLink() { if (DeathLinkService != null) { DeathLinkService.DisableDeathLink(); Core.data.deathLink = false; DeathLinkConfig.deathLinkStatus.text = "Death Link is <color=red>OFF</color>"; DeathLinkConfig.deathLinkCount.text = ""; } } public static void DeathLinkReceived(DeathLink deathLink) { if (Core.IsInLevel) { lastDeathLink = deathLink; } else { Core.Logger.LogWarning((object)"Received DeathLink, but player cannot be killed right now."); } } public static void SendCompletion() { Core.Logger.LogInfo((object)"Goal completed!"); ArchipelagoSession session = Session; if (session != null) { session.SetGoalAchieved(); } } public static void UpdateCompletedLevels() { if (Session != null) { Session.DataStorage[(Scope)3, "completedLevels"] = DataStorageElement.op_Implicit((Array)Core.data.completedLevels.ToArray()); } } public static bool ServerVersionIsAtLeast(string version) { if (Utility.IsNullOrWhiteSpace(Core.data.version) || Core.data.version == "?") { return false; } if (Core.data.version == version) { return true; } if (Core.data.version.CompareTo(version) < 0) { return false; } return true; } } public static class LocationManager { public static GameProgressMoneyAndGear generalProgress; public static Dictionary<string, long> locations = new Dictionary<string, long>(); public static Dictionary<string, AItem> shopScouts = new Dictionary<string, AItem>(); public static List<Message> messages = new List<Message>(); public static List<Powerup> powerupQueue = new List<Powerup>(); public static int soapWaiting = 0; public static List<QueuedItem> itemQueue = new List<QueuedItem>(); public static readonly List<string> fire2Weapons = new List<string> { "Revolver - Piercer", "Revolver - Marksman", "Revolver - Sharpshooter", "Shotgun - Core Eject", "Shotgun - Pump Charge", "Shotgun - Sawed-On", "Nailgun - Attractor", "Nailgun - Overheat", "Nailgun - JumpStart", "Rocket Launcher - Freezeframe", "Rocket Launcher - S.R.S. Cannon", "Rocket Launcher - Firestarter" }; public static List<ItemDefinition> ItemDefinitions { get; private set; } public static void RegenerateItemDefinitions() { ItemDefinitions = new List<ItemDefinition> { new ItemDefinition("Revolver - Piercer", UKType.Weapon, () => Colors.VariationBlue, (Core.data.revForm == WeaponForm.Standard) ? "rev" : "revalt"), new ItemDefinition("Revolver - Marksman", UKType.Weapon, () => Colors.VariationGreen, (Core.data.revForm == WeaponForm.Standard) ? "rev" : "revalt"), new ItemDefinition("Revolver - Sharpshooter", UKType.Weapon, () => Colors.VariationRed, (Core.data.revForm == WeaponForm.Standard) ? "rev" : "revalt"), new ItemDefinition("Revolver - Standard", UKType.WeaponAlt, () => Colors.WeaponAlt, "rev"), new ItemDefinition("Revolver - Alternate", UKType.WeaponAlt, () => Colors.WeaponAlt, "revalt"), new ItemDefinition("Shotgun - Core Eject", UKType.Weapon, () => Colors.VariationBlue, (Core.data.shoForm == WeaponForm.Standard) ? "sho" : "shoalt"), new ItemDefinition("Shotgun - Pump Charge", UKType.Weapon, () => Colors.VariationGreen, (Core.data.shoForm == WeaponForm.Standard) ? "sho" : "shoalt"), new ItemDefinition("Shotgun - Sawed-On", UKType.Weapon, () => Colors.VariationRed, (Core.data.shoForm == WeaponForm.Standard) ? "sho" : "shoalt"), new ItemDefinition("Shotgun - Standard", UKType.WeaponAlt, () => Colors.WeaponAlt, "sho"), new ItemDefinition("Shotgun - Alternate", UKType.WeaponAlt, () => Colors.WeaponAlt, "shoalt"), new ItemDefinition("Nailgun - Attractor", UKType.Weapon, () => Colors.VariationBlue, (Core.data.naiForm == WeaponForm.Standard) ? "nai" : "naialt"), new ItemDefinition("Nailgun - Overheat", UKType.Weapon, () => Colors.VariationGreen, (Core.data.naiForm == WeaponForm.Standard) ? "nai" : "naialt"), new ItemDefinition("Nailgun - JumpStart", UKType.Weapon, () => Colors.VariationRed, (Core.data.naiForm == WeaponForm.Standard) ? "nai" : "naialt"), new ItemDefinition("Nailgun - Standard", UKType.WeaponAlt, () => Colors.WeaponAlt, "nai"), new ItemDefinition("Nailgun - Alternate", UKType.WeaponAlt, () => Colors.WeaponAlt, "naialt"), new ItemDefinition("Railcannon - Electric", UKType.Weapon, () => Colors.VariationBlue, "rai"), new ItemDefinition("Railcannon - Screwdriver", UKType.Weapon, () => Colors.VariationGreen, "rai"), new ItemDefinition("Railcannon - Malicious", UKType.Weapon, () => Colors.VariationRed, "rai"), new ItemDefinition("Rocket Launcher - Freezeframe", UKType.Weapon, () => Colors.VariationBlue, "rock"), new ItemDefinition("Rocket Launcher - S.R.S. Cannon", UKType.Weapon, () => Colors.VariationGreen, "rock"), new ItemDefinition("Rocket Launcher - Firestarter", UKType.Weapon, () => Colors.VariationRed, "rock"), new ItemDefinition("Secondary Fire - Piercer", UKType.Fire2, () => Colors.VariationBlue, "rev0_fire2"), new ItemDefinition("Secondary Fire - Marksman", UKType.Fire2, () => Colors.VariationGreen, "rev2_fire2"), new ItemDefinition("Secondary Fire - Sharpshooter", UKType.Fire2, () => Colors.VariationRed, "rev1_fire2"), new ItemDefinition("Secondary Fire - Core Eject", UKType.Fire2, () => Colors.VariationBlue, "sho0_fire2"), new ItemDefinition("Secondary Fire - Pump Charge", UKType.Fire2, () => Colors.VariationGreen, "sho1_fire2"), new ItemDefinition("Secondary Fire - Sawed-On", UKType.Fire2, () => Colors.VariationRed, "sho2_fire2"), new ItemDefinition("Secondary Fire - Attractor", UKType.Fire2, () => Colors.VariationBlue, "nai0_fire2"), new ItemDefinition("Secondary Fire - Overheat", UKType.Fire2, () => Colors.VariationGreen, (Core.data.naiForm == WeaponForm.Standard) ? "naistd1_fire2" : "naialt1_fire2"), new ItemDefinition("Secondary Fire - JumpStart", UKType.Fire2, () => Colors.VariationRed, "nai2_fire2"), new ItemDefinition("Secondary Fire - Freezeframe", UKType.Fire2, () => Colors.VariationBlue, "rock0_fire2"), new ItemDefinition("Secondary Fire - S.R.S. Cannon", UKType.Fire2, () => Colors.VariationGreen, "rock1_fire2"), new ItemDefinition("Secondary Fire - Firestarter", UKType.Fire2, () => Colors.VariationRed, "rock2_fire2"), new ItemDefinition("Feedbacker", UKType.Arm, () => Colors.VariationBlue, "arm0"), new ItemDefinition("Knuckleblaster", UKType.Arm, () => Colors.VariationRed, "arm1"), new ItemDefinition("Whiplash", UKType.Arm, () => Colors.VariationGreen, "arm2"), new ItemDefinition("Stamina Bar", UKType.Ability, () => Colors.Stamina, "dash"), new ItemDefinition("Wall Jump", UKType.Ability, () => Colors.Stamina, "walljump"), new ItemDefinition("Slide", UKType.Ability, () => Colors.Stamina, "slide"), new ItemDefinition("Slam", UKType.Ability, () => Colors.Stamina, "slam"), new ItemDefinition("Blue Skull (0-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (0-S)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (0-S)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (1-1)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (1-1)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (1-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (1-2)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (1-3)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (1-3)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (1-4)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (2-3)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (2-3)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (2-4)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (2-4)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (4-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (4-2)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (4-3)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (4-4)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (5-1)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (5-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (5-2)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (5-3)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (5-3)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (6-1)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (7-1)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (7-1)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (7-2)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (7-S)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (7-S)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (8-1)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (8-1)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (8-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (8-2)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (8-3)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (8-3)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (8-4)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (8-4)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (0-E)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Red Skull (0-E)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Red Skull (1-E)", UKType.Skull, () => Colors.RedSkull, "skullr"), new ItemDefinition("Blue Skull (1-E)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("Blue Skull (P-2)", UKType.Skull, () => Colors.BlueSkull, "skullb"), new ItemDefinition("0-1: INTO THE FIRE", UKType.Level, () => Colors.Layer0, "layer0"), new ItemDefinition("0-2: THE MEATGRINDER", UKType.Level, () => Colors.Layer0, "layer0"), new ItemDefinition("0-3: DOUBLE DOWN", UKType.Level, () => Colors.Layer0, "layer0"), new ItemDefinition("0-4: A ONE-MACHINE ARMY", UKType.Level, () => Colors.Layer0, "layer0"), new ItemDefinition("0-5: CERBERUS", UKType.Level, () => Colors.Layer0, "layer0"), new ItemDefinition("0-S: SOMETHING WICKED", UKType.SecretMission, () => Colors.Layer0, "layer0"), new ItemDefinition("1-1: HEART OF THE SUNRISE", UKType.Level, () => Colors.Layer1, "layer1"), new ItemDefinition("1-2: THE BURNING WORLD", UKType.Level, () => Colors.Layer1, "layer1"), new ItemDefinition("1-3: HALLS OF SACRED REMAINS", UKType.Level, () => Colors.Layer1, "layer1"), new ItemDefinition("1-4: CLAIR DE LUNE", UKType.Level, () => Colors.Layer1, "layer1"), new ItemDefinition("1-S: THE WITLESS", UKType.SecretMission, () => Colors.Layer1, "layer1"), new ItemDefinition("2-1: BRIDGEBURNER", UKType.Level, () => Colors.Layer2, "layer2"), new ItemDefinition("2-2: DEATH AT 20,000 VOLTS", UKType.Level, () => Colors.Layer2, "layer2"), new ItemDefinition("2-3: SHEER HEART ATTACK", UKType.Level, () => Colors.Layer2, "layer2"), new ItemDefinition("2-4: COURT OF THE CORPSE KING", UKType.Level, () => Colors.Layer2, "layer2"), new ItemDefinition("2-S: ALL IMPERFECT LOVE SONG", UKType.SecretMission, () => Colors.Layer2, "layer2"), new ItemDefinition("3-1: BELLY OF THE BEAST", UKType.Level, () => Colors.Layer3, "layer3"), new ItemDefinition("3-2: IN THE FLESH", UKType.Level, () => Colors.Layer3, "layer3"), new ItemDefinition("4-1: SLAVES TO POWER", UKType.Level, () => Colors.Layer4, "layer4"), new ItemDefinition("4-2: GOD DAMN THE SUN", UKType.Level, () => Colors.Layer4, "layer4"), new ItemDefinition("4-3: A SHOT IN THE DARK", UKType.Level, () => Colors.Layer4, "layer4"), new ItemDefinition("4-4: CLAIR DE SOLEIL", UKType.Level, () => Colors.Layer4, "layer4"), new ItemDefinition("4-S: CLASH OF THE BRANDICOOT", UKType.SecretMission, () => Colors.Layer4, "layer4"), new ItemDefinition("5-1: IN THE WAKE OF POSEIDON", UKType.Level, () => Colors.Layer5, "layer5"), new ItemDefinition("5-2: WAVES OF THE STARLESS SEA", UKType.Level, () => Colors.Layer5, "layer5"), new ItemDefinition("5-3: SHIP OF FOOLS", UKType.Level, () => Colors.Layer5, "layer5"), new ItemDefinition("5-4: LEVIATHAN", UKType.Level, () => Colors.Layer5, "layer5"), new ItemDefinition("5-S: I ONLY SAY MORNING", UKType.SecretMission, () => Colors.Layer5, "layer5"), new ItemDefinition("6-1: CRY FOR THE WEEPER", UKType.Level, () => Colors.Layer6, "layer6"), new ItemDefinition("6-2: AESTHETICS OF HATE", UKType.Level, () => Colors.Layer6, "layer6"), new ItemDefinition("7-1: GARDEN OF FORKING PATHS", UKType.Level, () => Colors.Layer7, "layer7"), new ItemDefinition("7-2: LIGHT UP THE NIGHT", UKType.Level, () => Colors.Layer7, "layer7"), new ItemDefinition("7-3: NO SOUND, NO MEMORY", UKType.Level, () => Colors.Layer7, "layer7"), new ItemDefinition("7-4: ...LIKE ANTENNAS TO HEAVEN", UKType.Level, () => Colors.Layer7, "layer7"), new ItemDefinition("7-S: HELL BATH NO FURY", UKType.SecretMission, () => Colors.Layer7, "layer7"), new ItemDefinition("8-1: HURTBREAK WONDERLAND", UKType.Level, () => Colors.Layer8, "layer8"), new ItemDefinition("8-2: THROUGH THE MIRROR", UKType.Level, () => Colors.Layer8, "layer8"), new ItemDefinition("8-3: DISINTEGRATION LOOP", UKType.Level, () => Colors.Layer8, "layer8"), new ItemDefinition("8-4: FINAL FLIGHT", UKType.Level, () => Colors.Layer8, "layer8"), new ItemDefinition("0-E: THIS HEAT, AN EVIL HEAT", UKType.Level, () => Colors.Encore0, "layer0"), new ItemDefinition("1-E: ...THEN FELL THE ASHES", UKType.Level, () => Colors.Encore1, "layer1"), new ItemDefinition("P-1: SOUL SURVIVOR", UKType.Level, () => Colors.Prime, "layer3"), new ItemDefinition("P-2: WAIT OF THE WORLD", UKType.Level, () => Colors.Prime, "layer6"), new ItemDefinition("OVERTURE: THE MOUTH OF HELL", UKType.Layer, () => Colors.Layer0, "layer0"), new ItemDefinition("LAYER 1: LIMBO", UKType.Layer, () => Colors.Layer1, "layer1"), new ItemDefinition("LAYER 2: LUST", UKType.Layer, () => Colors.Layer2, "layer2"), new ItemDefinition("LAYER 3: GLUTTONY", UKType.Layer, () => Colors.Layer3, "layer3"), new ItemDefinition("LAYER 4: GREED", UKType.Layer, () => Colors.Layer4, "layer4"), new ItemDefinition("LAYER 5: WRATH", UKType.Layer, () => Colors.Layer5, "layer5"), new ItemDefinition("LAYER 6: HERESY", UKType.Layer, () => Colors.Layer6, "layer6"), new ItemDefinition("LAYER 7: VIOLENCE", UKType.Layer, () => Colors.Layer7, "layer7"), new ItemDefinition("LAYER 8: FRAUD", UKType.Layer, () => Colors.Layer8, "layer8"), new ItemDefinition("+10,000P", UKType.Points, () => Colors.Points, "points"), new ItemDefinition("Overheal", UKType.Powerup, () => Colors.Overheal, "overheal"), new ItemDefinition("Dual Wield", UKType.Powerup, () => Colors.DualWield, "dualwield"), new ItemDefinition("Infinite Stamina", UKType.Powerup, () => Colors.Stamina, "infinitestamina"), new ItemDefinition("Air Jump", UKType.Powerup, () => Colors.DoubleJump, "doublejump"), new ItemDefinition("Soap", UKType.Soap, () => Colors.White, "soap"), new ItemDefinition("Confusing Aura", UKType.Powerup, () => Colors.Confusion, "confusion"), new ItemDefinition("Quick Charge", UKType.Powerup, () => Colors.VariationBlue, "quickcharge"), new ItemDefinition("Hard Damage", UKType.Trap, () => Colors.Trap, "overheal"), new ItemDefinition("Stamina Limiter", UKType.Trap, () => Colors.Trap, "infinitestamina"), new ItemDefinition("Wall Jump Limiter", UKType.Trap, () => Colors.Trap, "walljumptrap"), new ItemDefinition("Weapon Malfunction", UKType.Trap, () => Colors.Trap, "quickcharge"), new ItemDefinition("Empty Ammunition", UKType.Trap, () => Colors.Trap, "quickcharge"), new ItemDefinition("Radiant Aura", UKType.Trap, () => Colors.Trap, "radiance"), new ItemDefinition("Hands-Free Mode", UKType.Trap, () => Colors.Trap, "noarms"), new ItemDefinition("Short-Term Sandstorm", UKType.Trap, () => Colors.Trap, "sandstorm"), new ItemDefinition("Limbo Switch I", UKType.LimboSwitch, () => Colors.Switch, "switch1"), new ItemDefinition("Limbo Switch II", UKType.LimboSwitch, () => Colors.Switch, "switch2"), new ItemDefinition("Limbo Switch III", UKType.LimboSwitch, () => Colors.Switch, "switch3"), new ItemDefinition("Limbo Switch IV", UKType.LimboSwitch, () => Colors.Switch, "switch4"), new ItemDefinition("Violence Switch I", UKType.ShotgunSwitch, () => Colors.Switch, "switch1"), new ItemDefinition("Violence Switch II", UKType.ShotgunSwitch, () => Colors.Switch, "switch2"), new ItemDefinition("Violence Switch III", UKType.ShotgunSwitch, () => Colors.Switch, "switch3"), new ItemDefinition("Clash Mode", UKType.ClashMode, () => Colors.Layer4, "clash") }; } public static ItemDefinition GetItemDefinition(string name) { foreach (ItemDefinition itemDefinition in ItemDefinitions) { if (itemDefinition.Name == name) { return itemDefinition; } } return null; } public static void CheckLocation(string loc) { bool flag = MonoSingleton<AssistController>.Instance.cheatsEnabled; if (SceneHelper.CurrentScene == "CreditsMuseum2") { flag = false; } if (!flag) { if (!Core.data.@checked.Contains(loc)) { Core.data.@checked.Add(loc); } if (locations.ContainsKey(loc) && Multiworld.Authenticated) { if (SceneHelper.CurrentScene != "Level 7-S") { Core.Logger.LogInfo((object)$"Checking location \"{loc}\" | {locations[loc]}"); } Multiworld.Session.Locations.CompleteLocationChecks(new long[1] { locations[loc] }); } else { Core.Logger.LogWarning((object)("Location \"" + loc + "\" does not exist.")); } } else { if (Object.op_Implicit((Object)(object)MonoSingleton<HudMessageReceiver>.Instance)) { MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Skipping location check because cheats are enabled!", "", "", 0, false, false, true); } Core.Logger.LogWarning((object)("Skipping location check \"" + loc + "\" because cheats are enabled!")); } } public static bool ShouldGetItemAgain(UKType type) { List<UKType> list = new List<UKType> { UKType.Weapon, UKType.WeaponAlt, UKType.Arm, UKType.Skull, UKType.Level, UKType.Layer, UKType.Fire2, UKType.LimboSwitch, UKType.ShotgunSwitch, UKType.ClashMode, UKType.SecretMission }; if (list.Contains(type)) { return true; } return false; } public static void GetUKItem(UKItem item, string sendingPlayer = null, bool silent = false, bool save = true) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_11ac: Unknown result type (might be due to invalid IL or missing references) //IL_11b1: Unknown result type (might be due to invalid IL or missing references) //IL_110d: Unknown result type (might be due to invalid IL or missing references) //IL_1112: Unknown result type (might be due to invalid IL or missing references) string text = ColorUtility.ToHtmlStringRGB(GetItemDefinition(item.itemName).Color()); string text2 = ColorUtility.ToHtmlStringRGB(Colors.PlayerOther); string text3 = ""; if (item.playerName == Core.data.slot_name) { if (item.type == UKType.Weapon && Core.data.randomizeFire2 == Fire2Options.Progressive && fire2Weapons.Contains(item.itemName)) { FieldInfo field = typeof(GameProgressMoneyAndGear).GetField(GetWeaponIdFromName(item.itemName), BindingFlags.Instance | BindingFlags.Public); if ((int)field.GetValue(generalProgress) > 0) { item.itemName = "Secondary Fire -" + item.itemName.Split(new char[1] { '-' }, 2)[1]; item.type = UKType.Fire2; } } switch (item.type) { case UKType.Weapon: { string weaponIdFromName2 = GetWeaponIdFromName(item.itemName); int num = 1; if ((weaponIdFromName2.Contains("rev") && Core.data.revForm == WeaponForm.Alternate) || (weaponIdFromName2.Contains("sho") && Core.data.shoForm == WeaponForm.Alternate) || (weaponIdFromName2.Contains("nai") && Core.data.naiForm == WeaponForm.Alternate)) { num = 2; } GameProgressSaver.AddGear(weaponIdFromName2); MonoSingleton<PrefsManager>.Instance.SetInt("weapon." + weaponIdFromName2, num); if (Core.CanGetWeapon) { MonoSingleton<GunSetter>.Instance.ResetWeapons(false); MonoSingleton<GunSetter>.Instance.ForceWeapon(weaponIdFromName2); if (MonoSingleton<FistControl>.Instance.shopping) { MonoSingleton<GunControl>.Instance.NoWeapon(); } } text3 = "WEAPON: "; generalProgress = GameProgressSaver.GetGeneralProgress(); break; } case UKType.WeaponAlt: { string weaponIdFromName = GetWeaponIdFromName(item.itemName); switch (weaponIdFromName) { case "revalt": if (Core.data.revForm == WeaponForm.Standard) { Core.data.revalt = true; GameProgressSaver.AddGear(weaponIdFromName); } else { Core.data.revstd = true; } break; case "shoalt": if (Core.data.shoForm == WeaponForm.Standard) { Core.data.shoalt = true; GameProgressSaver.AddGear(weaponIdFromName); } else { Core.data.shostd = true; } break; case "naialt": if (Core.data.naiForm == WeaponForm.Standard) { Core.data.naialt = true; GameProgressSaver.AddGear(weaponIdFromName); } else { Core.data.naistd = true; } break; default: Core.Logger.LogWarning((object)("Unknown WeaponAlt: " + weaponIdFromName)); break; } text3 = "WEAPON: "; break; } case UKType.Arm: if (Core.IsInLevel) { HudController.Instance.armIcon.SetActive(true); } if (item.itemName == "Feedbacker") { Core.data.hasArm = true; MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm0", 1); if (Core.CanGetWeapon) { MonoSingleton<FistControl>.Instance.ResetFists(); MonoSingleton<FistControl>.Instance.ForceArm(int.Parse(GetWeaponIdFromName(item.itemName).Substring(3, 1)), false); } } else { if (!Core.data.hasArm && item.itemName == "Knuckleblaster") { MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm0", 0); } GameProgressSaver.AddGear(GetWeaponIdFromName(item.itemName)); MonoSingleton<PrefsManager>.Instance.SetInt("weapon." + GetWeaponIdFromName(item.itemName), 1); if (Core.CanGetWeapon) { MonoSingleton<FistControl>.Instance.ResetFists(); MonoSingleton<FistControl>.Instance.ForceArm(int.Parse(GetWeaponIdFromName(item.itemName).Substring(3, 1)), false); } } text3 = "ARM: "; break; case UKType.Ability: if (item.itemName == "Stamina Bar" && Core.data.dashes < 3) { Core.data.dashes++; } else if (item.itemName == "Wall Jump" && Core.data.walljumps < 3) { Core.data.walljumps++; } else if (item.itemName == "Slide") { Core.data.canSlide = true; } else if (item.itemName == "Slam") { Core.data.canSlam = true; } text3 = "ABILITY: "; break; case UKType.Skull: if (!Core.data.randomizeSkulls) { return; } if (item.itemName.Contains("1-4")) { if (Core.data.unlockedSkulls1_4 == 4) { return; } Core.data.unlockedSkulls1_4++; if (SceneHelper.CurrentScene == "Level 1-4") { LevelManager.ActivateSkull(LevelManager.skulls.ElementAt(Core.data.unlockedSkulls1_4 - 1).Value); } } else if (item.itemName.Contains("5-1")) { if (Core.data.unlockedSkulls5_1 == 3) { return; } Core.data.unlockedSkulls5_1++; if (SceneHelper.CurrentScene == "Level 5-1") { LevelManager.ActivateSkull(LevelManager.skulls.ElementAt(Core.data.unlockedSkulls5_1 - 1).Value); } } else if (item.itemName.Contains("0-S")) { if (item.itemName.Contains("Blue")) { Core.data.unlockedSkulls.Add("0S_b"); } else if (item.itemName.Contains("Red")) { Core.data.unlockedSkulls.Add("0S_r"); } } else if (item.itemName.Contains("7-S")) { if (item.itemName.Contains("Blue")) { Core.data.unlockedSkulls.Add("7S_b"); } else if (item.itemName.Contains("Red")) { Core.data.unlockedSkulls.Add("7S_r"); } } else { string text4 = Core.GetLevelIdFromName(item.itemName.Substring(item.itemName.Length - 4, 3)).ToString(); if (item.itemName.Contains("Blue")) { text4 += "_b"; } else if (item.itemName.Contains("Red")) { text4 += "_r"; } Core.Logger.LogInfo((object)("Skull: " + text4)); Core.data.unlockedSkulls.Add(text4); } if (SceneHelper.CurrentScene == "Level 0-S") { if (item.itemName == "Blue Skull (0-S)") { LevelManager.ActivateSkull(LevelManager.skulls["SkullBlue"]); } else if (item.itemName == "Red Skull (0-S)") { LevelManager.ActivateSkull(LevelManager.skulls["SkullRed"]); } } else if (SceneHelper.CurrentScene == "Level 7-S") { if (item.itemName == "Blue Skull (7-S)") { LevelManager.ActivateSkull(LevelManager.skulls["SkullBlue"]); } else if (item.itemName == "Red Skull (7-S)") { LevelManager.ActivateSkull(LevelManager.skulls["SkullRed"]); } } else if (MonoSingleton<StatsManager>.Instance.levelNumber != 0 && Core.IsInLevel && item.itemName.Contains(Core.GetLevelNameFromId(MonoSingleton<StatsManager>.Instance.levelNumber))) { if (item.itemName.Contains("Blue")) { LevelManager.ActivateSkull(LevelManager.skulls["SkullBlue"]); } else if (item.itemName.Contains("Red")) { if (Core.CurrentLevelInfo.Id == 101) { LevelManager.redDoor.Open(false, false); } else { LevelManager.ActivateSkull(LevelManager.skulls["SkullRed"]); } } } if (SceneHelper.CurrentScene == "Main Menu") { SkullIcon[] array = Object.FindObjectsOfType<SkullIcon>(); foreach (SkullIcon skullIcon in array) { skullIcon.CheckSkull(); } } text3 = ((sendingPlayer != null) ? "GOT: " : "FOUND: "); break; case UKType.Level: Core.data.unlockedLevels.Add(item.itemName.Substring(0, 3)); text3 = "UNLOCKED: "; break; case UKType.SecretMission: GameProgressSaver.FoundSecretMission(int.Parse(item.itemName.Substring(0, 1))); text3 = "UNLOCKED: "; break; case UKType.Layer: { int num2 = ((!item.itemName.Contains("OVERTURE")) ? int.Parse(item.itemName[6].ToString()) : 0); foreach (LevelInfo levelInfo in Core.levelInfos) { if (levelInfo.Layer == num2) { Core.data.unlockedLevels.Add(levelInfo.Name); } } text3 = "UNLOCKED: "; break; } case UKType.Points: GameProgressSaver.AddMoney(10000); text3 = ((sendingPlayer != null) ? "GOT: " : "FOUND: "); break; case UKType.Powerup: switch (item.itemName) { case "Overheal": powerupQueue.Add(Powerup.Overheal); break; case "Dual Wield": powerupQueue.Add(Powerup.DualWield); break; case "Infinite Stamina": powerupQueue.Add(Powerup.InfiniteStamina); break; case "Air Jump": powerupQueue.Add(Powerup.DoubleJump); break; case "Confusing Aura": powerupQueue.Add(Powerup.Confusion); break; case "Quick Charge": powerupQueue.Add(Powerup.QuickCharge); break; default: Core.Logger.LogWarning((object)("Couldn't identify powerup: \"" + item.itemName + "\"")); break; } text3 = ((sendingPlayer != null) ? "GOT: " : "FOUND: "); break; case UKType.Trap: switch (item.itemName) { case "Hard Damage": powerupQueue.Add(Powerup.HardDamage); break; case "Stamina Limiter": powerupQueue.Add(Powerup.StaminaLimiter); break; case "Wall Jump Limiter": powerupQueue.Add(Powerup.WalljumpLimiter); break; case "Empty Ammunition": case "Weapon Malfunction": powerupQueue.Add(Powerup.EmptyAmmo); break; case "Radiant Aura": powerupQueue.Add(Powerup.Radiance); break; case "Hands-Free Mode": powerupQueue.Add(Powerup.NoArms); break; case "Short-Term Sandstorm": powerupQueue.Add(Powerup.Sandstorm); break; default: Core.Logger.LogWarning((object)("Couldn't identify trap: \"" + item.itemName + "\"")); break; } text3 = ((sendingPlayer != null) ? "GOT: " : "FOUND: "); break; case UKType.Soap: soapWaiting++; text3 = ((sendingPlayer != null) ? "GOT: " : "FOUND: "); break; case UKType.Fire2: Core.data.unlockedFire2.Add(GetWeaponIdFromName(item.itemName)); if ((Object)(object)Fire2HUD.Instance != (Object)null) { Fire2HUD.Instance.UpdateCurrentWeapon(); } text3 = "UNLOCKED: "; break; case UKType.LimboSwitch: if (item.itemName == "Limbo Switch I") { Core.data.limboSwitches[0] = true; } else if (item.itemName == "Limbo Switch II") { Core.data.limboSwitches[1] = true; } else if (item.itemName == "Limbo Switch III") { Core.data.limboSwitches[2] = true; } else if (item.itemName == "Limbo Switch IV") { Core.data.limboSwitches[3] = true; } if (Object.op_Implicit((Object)(object)Object.FindObjectOfType<LimboSwitchLock>())) { Traverse.Create((object)Object.FindObjectOfType<LimboSwitchLock>()).Field<int>("openedLocks").Value = 0; Object.FindObjectOfType<LimboSwitchLock>().CheckSaves(); Traverse.Create((object)Object.FindObjectOfType<LimboSwitchLock>()).Method("CheckLocks", Array.Empty<object>()).GetValue(); } text3 = "ACTIVATED: "; break; case UKType.ShotgunSwitch: if (item.itemName == "Violence Switch I") { Core.data.shotgunSwitches[0] = true; } else if (item.itemName == "Violence Switch II") { Core.data.shotgunSwitches[1] = true; } else if (item.itemName == "Violence Switch III") { Core.data.shotgunSwitches[2] = true; } if (Object.op_Implicit((Object)(object)Object.FindObjectOfType<LimboSwitchLock>())) { Traverse.Create((object)Object.FindObjectOfType<LimboSwitchLock>()).Field<int>("openedLocks").Value = 0; Object.FindObjectOfType<LimboSwitchLock>().CheckSaves(); Traverse.Create((object)Object.FindObjectOfType<LimboSwitchLock>()).Method("CheckLocks", Array.Empty<object>()).GetValue(); } text3 = "ACTIVATED: "; break; case UKType.ClashMode: { GameProgressMoneyAndGear val = GameProgressSaver.GetGeneralProgress(); val.clashModeUnlocked = true; Traverse.Create(typeof(GameProgressSaver)).Method("WriteFile", new object[2] { Traverse.Create(typeof(GameProgressSaver)).Property<string>("generalProgressPath", (object[])null).Value, val }).GetValue(); text3 = "UNLOCKED: "; break; } } text3 = text3 + "<color=#" + text + "FF>" + item.itemName.ToUpper() + "</color>"; if (sendingPlayer != null) { text3 = text3 + " (<color=#" + text2 + "FF>" + sendingPlayer + "</color>)"; } if (!silent) { messages.Add(new Message { image = GetItemDefinition(item.itemName).Image, color = GetItemDefinition(item.itemName).Color(), message = text3 }); } } else { text3 = "FOUND: <color=#" + text + "FF>" + item.itemName.ToUpper() + "</color> (<color=#" + text2 + "FF>" + item.playerName + "</color>)"; if (!silent) { messages.Add(new Message { image = GetItemDefinition(item.itemName).Image, color = Colors.Gray, message = text3 }); } } if (save) { Core.SaveData(); } ActStats.SetAllDirty(); } public static void GetRandomHint() { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Session == null) { return; } ReadOnlyCollection<long> allMissingLocations = Multiworld.Session.Locations.AllMissingLocations; IEnumerable<long> second = from h in ((IDataStorageWrapper)Multiworld.Session.DataStorage).GetHintsAsync((int?)null, (int?)null).Result where h.FindingPlayer == Multiworld.Session.ConnectionInfo.Slot select h.LocationId; long[] array = allMissingLocations.Except(second).ToArray(); if (array.Any()) { long num = array[Random.Range(0, array.Length)]; ScoutedItemInfo val = Multiworld.Session.Locations.ScoutLocationsAsync(true, new long[1] { num }).Result[num]; string locationNameFromId = Multiworld.Session.Locations.GetLocationNameFromId(((ItemInfo)val).LocationId, Multiworld.Session.Players.GetPlayerInfo(Multiworld.Session.ConnectionInfo.Slot).Game); string text = ""; Color white = Color.white; string image = "filler"; if (((ItemInfo)val).ItemGame == "ULTRAKILL" && GetItemDefinition(((ItemInfo)val).ItemName) != null) { text = ColorUtility.ToHtmlStringRGB(GetItemDefinition(((ItemInfo)val).ItemName).Color()); white = GetItemDefinition(((ItemInfo)val).ItemName).Color(); image = GetItemDefinition(((ItemInfo)val).ItemName).Image; } else { text = ColorUtility.ToHtmlStringRGB(GetAPMessageColor(((ItemInfo)val).Flags)); white = GetAPMessageColor(((ItemInfo)val).Flags); } string text2 = ColorUtility.ToHtmlStringRGB(Colors.PlayerOther); string text3 = ColorUtility.ToHtmlStringRGB(GetLocationColor(locationNameFromId.Substring(0, 3))); string text4 = "HINT: <color=#" + text + "FF>"; text4 = text4 + ((ItemInfo)val).ItemName.ToUpper() + "</color> "; if (Multiworld.Session.Players.GetPlayerName(PlayerInfo.op_Implicit(val.Player)) != Core.data.slot_name) { text4 = text4 + "(<color=#" + text2 + "FF>" + Multiworld.Session.Players.GetPlayerAlias(PlayerInfo.op_Implicit(val.Player)) + "</color>) "; } text4 = text4 + "at <color=#" + text3 + "FF>" + ((ItemInfo)val).LocationName + "</color>"; messages.Add(new Message { image = image, color = white, message = text4 }); if (!UIManager.displayingMessage && (Core.IsPlaying || SceneHelper.CurrentScene == "Endless")) { ((MonoBehaviour)Core.uim).StartCoroutine("DisplayMessage"); } } else { Core.Logger.LogWarning((object)"No locations available to hint."); } } public static Color GetLocationColor(string locationName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL o
websocket-sharp.dll
Decompiled 10 hours 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);