Decompiled source of ULTRArchipelago v0.1.0
Archipelago.MultiClient.Net.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; 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(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Jarno Westhof, Hussein Farran, Zach Parks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")] [assembly: AssemblyFileVersion("6.7.0.0")] [assembly: AssemblyInformationalVersion("6.7.0+c807746b6f1774cf1afe12af819acb078b55a333")] [assembly: AssemblyProduct("Archipelago.MultiClient.Net")] [assembly: AssemblyTitle("Archipelago.MultiClient.Net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")] [assembly: AssemblyVersion("6.7.0.0")] internal interface IConcurrentHashSet<T> { bool TryAdd(T item); bool Contains(T item); void UnionWith(T[] otherSet); T[] ToArray(); ReadOnlyCollection<T> AsToReadOnlyCollection(); ReadOnlyCollection<T> AsToReadOnlyCollectionExcept(IConcurrentHashSet<T> otherSet); } 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; } 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) { GetClientStatusElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onStatusUpdated(newValue.ToObject<ArchipelagoClientState>());
UltrakillArchipelago.dll
Decompiled 3 days 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.Diagnostics.CodeAnalysis; 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.Threading; 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.New; using ArchipelagoULTRAKILL.New.UI; using ArchipelagoULTRAKILL.New.Utils; using ArchipelagoULTRAKILL.Powerups; using ArchipelagoULTRAKILL.Properties; using ArchipelagoULTRAKILL.Structures; using BepInEx; using BepInEx.Logging; using GameConsole; using HarmonyLib; using Microsoft.CodeAnalysis; 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.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; using plog; using plog.Models; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: ComVisible(false)] [assembly: AssemblyCompany("UltrakillArchipelago")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2025 MaybeAshleyIdk")] [assembly: AssemblyDescription("Archipelago client implementation for ULTRAKILL")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+e1b6d22dc47de1e27cafcd7c446b54d728ef875c")] [assembly: AssemblyProduct("ULTRAKILL Archipelago Client Mod")] [assembly: AssemblyTitle("UltrakillArchipelago")] [assembly: AssemblyVersion("0.1.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ArchipelagoULTRAKILL { public static class AudioManager { private static readonly Dictionary<string, string> multiMusicBattle = new Dictionary<string, string> { ["1"] = "Assets/Music/0-1.wav", ["2"] = "Assets/Music/0-2.wav", ["3"] = "Assets/Music/0-1.wav", ["4"] = "Assets/Music/0-2.wav", ["6B"] = "Assets/Music/1-1.wav", ["7B"] = "Assets/Music/1-2 Noise Battle.wav", ["8"] = "Assets/Music/1-3.wav", ["10"] = "Assets/Music/2-1.wav", ["11"] = "Assets/Music/2-2.wav", ["12"] = "Assets/Music/2-3.wav", ["14A"] = "Assets/Music/3-1 Guts.wav", ["14B"] = "Assets/Music/3-1 Glory.wav", ["16"] = "Assets/Music/4-1.wav", ["17"] = "Assets/Music/4-2.wav", ["18A"] = "Assets/Music/4-3 Phase 1.wav", ["18B"] = "Assets/Music/4-3 Phase 2.wav", ["18C"] = "Assets/Music/4-3 Phase 3.wav", ["20"] = "Assets/Music/5-1.wav", ["22A"] = "Assets/Music/5-3.wav", ["22B"] = "Assets/Music/5-3 Aftermath.wav", ["24A"] = "Assets/Music/6-1.wav", ["26B"] = "Assets/Music/7-1.wav", ["27A"] = "Assets/Music/7-2 Intro Battle.wav", ["27B"] = "Assets/Music/7-2.wav", ["28B"] = "Assets/Music/7-3.wav", ["667A"] = "Assets/Music/P-2.wav" }; private static readonly Dictionary<string, string> multiMusicClean = new Dictionary<string, string> { ["1"] = "Assets/Music/0-1 Clean.wav", ["2"] = "Assets/Music/0-2 Clean.wav", ["3"] = "Assets/Music/0-1 Clean.wav", ["4"] = "Assets/Music/0-2 Clean.wav", ["6B"] = "Assets/Music/1-1 Clean.wav", ["7B"] = "Assets/Music/1-2 Noise Clean.wav", ["8"] = "Assets/Music/1-3 Clean.wav", ["10"] = "Assets/Music/2-1 Clean.wav", ["11"] = "Assets/Music/2-2 Clean.wav", ["12"] = "Assets/Music/2-3 Clean.wav", ["14A"] = "Assets/Music/3-1 Guts Clean.wav", ["14B"] = "Assets/Music/3-1 Glory Clean.wav", ["16"] = "Assets/Music/4-1 Clean.wav", ["17"] = "Assets/Music/4-2 Clean.wav", ["18A"] = "Assets/Music/4-3 Phase 1 Clean.wav", ["18B"] = "Assets/Music/4-3 Phase 2 Clean.wav", ["18C"] = "Assets/Music/4-3 Phase 3.wav", ["20"] = "Assets/Music/5-1 Clean.wav", ["22A"] = "Assets/Music/5-3 Clean.wav", ["22B"] = "Assets/Music/5-3 Aftermath Clean.wav", ["24A"] = "Assets/Music/6-1 Clean.wav", ["26B"] = "Assets/Music/7-1 Clean.wav", ["27A"] = "Assets/Music/7-2 Intro Clean.wav", ["27B"] = "Assets/Music/7-2 Clean.wav", ["28B"] = "Assets/Music/7-3 Clean.wav", ["667A"] = "Assets/Music/P-2 Clean.wav" }; private static readonly Dictionary<string, string> singleMusic = new Dictionary<string, string> { ["5"] = "Assets/Music/Bosses/Cerberus A.mp3", ["6A"] = "Assets/Music/Misc/A Thousand Greetings.wav", ["7A"] = "Assets/Music/Misc/A Thousand Greetings.wav", ["9A"] = "Assets/Music/Misc/Clair_de_lune_(Claude_Debussy)_Suite_bergamasque (CREATIVE COMMONS).ogg", ["9B"] = "Assets/Music/Bosses/V2 1-4.wav", ["13"] = "Assets/Music/Bosses/Minos Corpse B.wav", ["15A"] = "Assets/Music/Bosses/Gabriel 3-2 Intro.wav", ["15B"] = "Assets/Music/Bosses/Gabriel 3-2.wav", ["18D"] = "Assets/Music/Misc/themeofcancer.wav", ["19"] = "Assets/Music/Bosses/V2 4-4.wav", ["24B"] = "Assets/Music/6-1 Hall of Sacreligious Remains.wav", ["25A"] = "Assets/Music/Bosses/Gabriel 6-2 Intro B.wav", ["25B"] = "Assets/Music/Bosses/Gabriel 6-2.wav", ["26A"] = "Assets/Music/7-1 Intro.wav", ["26C"] = "Assets/Music/Misc/themeofcancer.wav", ["26D"] = "Assets/Music/Bosses/Minotaur A.wav", ["26E"] = "Assets/Music/Bosses/Minotaur B.wav", ["28A"] = "Assets/Music/7-3 Intro Clean.wav", ["666A"] = "Assets/Music/Bosses/Flesh Prison.wav", ["666B"] = "Assets/Music/Bosses/Minos Prime.wav", ["667B"] = "Assets/Music/Bosses/Flesh panopticon.wav", ["667C"] = "Assets/Music/Bosses/Sisyphus Prime.wav" }; public static AudioClip TestLoadAudioClip(string address) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Addressables.LoadAssetAsync<AudioClip>((object)address).WaitForCompletion(); } public static AudioClip LoadNewSingleTrack(AudioClip source, string id) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (singleMusic.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)singleMusic[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + singleMusic[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static AudioClip LoadNewCleanTrack(AudioClip source, string id) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (multiMusicClean.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)multiMusicClean[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + multiMusicClean[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static AudioClip LoadNewBattleTrack(AudioClip source, string id) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Core.data.music.ContainsKey(id)) { id = Core.data.music[id]; if (multiMusicBattle.ContainsKey(id)) { try { return Addressables.LoadAssetAsync<AudioClip>((object)multiMusicBattle[id]).WaitForCompletion(); } catch { Core.Logger.LogError((object)("Failed to load music track. (ID: " + id + " | Address: " + multiMusicBattle[id])); return source; } } Core.Logger.LogError((object)("Couldn't find address for key " + id + ". Returning original source.")); return source; } Core.Logger.LogError((object)("Music dictionary does not contain key " + id + ". Returning original source.")); return source; } public static void LoadMusicManagerTracks(string id, bool single = false) { if (single) { MonoSingleton<MusicManager>.Instance.cleanTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.cleanTheme.clip, id); MonoSingleton<MusicManager>.Instance.battleTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.battleTheme.clip, id); MonoSingleton<MusicManager>.Instance.bossTheme.clip = LoadNewSingleTrack(MonoSingleton<MusicManager>.Instance.bossTheme.clip, id); } else { MonoSingleton<MusicManager>.Instance.cleanTheme.clip = LoadNewCleanTrack(MonoSingleton<MusicManager>.Instance.cleanTheme.clip, id); MonoSingleton<MusicManager>.Instance.battleTheme.clip = LoadNewBattleTrack(MonoSingleton<MusicManager>.Instance.battleTheme.clip, id); MonoSingleton<MusicManager>.Instance.bossTheme.clip = LoadNewBattleTrack(MonoSingleton<MusicManager>.Instance.bossTheme.clip, id); } } public static void ChangeMusic() { if (Core.CurrentLevelInfo.Music == MusicType.Normal) { LoadMusicManagerTracks(Core.CurrentLevelInfo.Id.ToString()); } else { string currentScene = SceneHelper.CurrentScene; if (currentScene == null) { return; } int length = currentScene.Length; if (length != 9) { return; } switch (currentScene[6]) { default: return; case '0': if (!(currentScene == "Level 0-5")) { return; } foreach (AudioSource item in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if ((Object)(object)((Component)item).transform.parent != (Object)null && (((Object)((Component)item).transform.parent).name == "4 Contents" || ((Object)((Component)item).transform.parent).name == "4 Contents(Clone)") && ((Object)((Component)item).transform).name == "Music") { item.clip = LoadNewSingleTrack(item.clip, "5"); ((Component)((Component)item).transform.parent.Find("Enemies").Find("StatueEnemy (1)")).GetComponent<SoundChanger>().newSound = LoadNewSingleTrack(item.clip, "5"); } } break; case '1': switch (currentScene) { default: return; case "Level 1-1": LoadMusicManagerTracks("6A", single: true); foreach (MusicChanger item2 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item2).gameObject).name == "MusicChanger") { item2.clean = LoadNewCleanTrack(item2.clean, "6B"); item2.battle = LoadNewBattleTrack(item2.battle, "6B"); } } break; case "Level 1-2": LoadMusicManagerTracks("7A", single: true); foreach (MusicChanger item3 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item3).gameObject).name == "MusicActivator") { item3.clean = LoadNewCleanTrack(item3.clean, "7B"); item3.battle = LoadNewBattleTrack(item3.battle, "7B"); } } break; case "Level 1-4": foreach (AudioSource item4 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item4).gameObject).name == "Music - Clair de Lune") { item4.clip = LoadNewSingleTrack(item4.clip, "9A"); } else if (((Object)((Component)item4).gameObject).name == "Music - Versus") { item4.clip = LoadNewSingleTrack(item4.clip, "9B"); } } break; } break; case '2': if (!(currentScene == "Level 2-1")) { if (!(currentScene == "Level 2-4")) { return; } foreach (AudioSource item5 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item5).gameObject).name == "BossMusic") { item5.clip = LoadNewSingleTrack(item5.clip, "13"); } } break; } foreach (MusicChanger item6 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item6).gameObject).name == "Cube (1)") { item6.clean = LoadNewCleanTrack(item6.clean, "10"); item6.battle = LoadNewBattleTrack(item6.battle, "10"); } } break; case '3': if (!(currentScene == "Level 3-1")) { if (!(currentScene == "Level 3-2")) { return; } foreach (AudioSource item7 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item7).gameObject).name == "Music 2") { item7.clip = LoadNewSingleTrack(item7.clip, "15A"); } else if (((Object)((Component)item7).gameObject).name == "Music 3") { item7.clip = LoadNewSingleTrack(item7.clip, "15B"); } } break; } LoadMusicManagerTracks("14A"); foreach (MusicChanger item8 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item8).gameObject).name == "MusicChanger") { item8.clean = LoadNewCleanTrack(item8.clean, "14B"); item8.battle = LoadNewBattleTrack(item8.battle, "14B"); } } break; case '4': if (!(currentScene == "Level 4-3")) { if (!(currentScene == "Level 4-4")) { return; } foreach (AudioSource item9 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item9).gameObject).name == "Versus 2") { item9.clip = LoadNewSingleTrack(item9.clip, "19"); } } break; } foreach (MusicChanger item10 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item10).gameObject).name == "OnLight") { item10.clean = LoadNewCleanTrack(item10.clean, "18A"); item10.battle = LoadNewBattleTrack(item10.battle, "18A"); } else if (((Object)((Component)item10).gameObject).name == "Music Changer") { item10.clean = LoadNewCleanTrack(item10.clean, "18B"); item10.battle = LoadNewBattleTrack(item10.battle, "18B"); } else if (((Object)((Component)item10).gameObject).name == "Music Changer (Normal)") { item10.clean = LoadNewCleanTrack(item10.clean, "18B"); item10.battle = LoadNewBattleTrack(item10.battle, "18B"); } else if (((Object)((Component)item10).gameObject).name == "Music") { item10.clean = LoadNewCleanTrack(item10.clean, "18C"); item10.battle = LoadNewBattleTrack(item10.battle, "18C"); } else if (((Object)((Component)item10).gameObject).name == "Trigger (Fight)") { item10.clean = LoadNewSingleTrack(item10.clean, "18D"); item10.battle = LoadNewSingleTrack(item10.battle, "18D"); item10.boss = LoadNewSingleTrack(item10.boss, "18D"); } } break; case '5': if (!(currentScene == "Level 5-3")) { return; } LoadMusicManagerTracks("22A"); foreach (MusicChanger item11 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item11).gameObject).name == "InstantVer") { item11.clean = LoadNewCleanTrack(item11.clean, "22B"); item11.battle = LoadNewBattleTrack(item11.battle, "22B"); } else if (((Object)((Component)item11).gameObject).name == "NormalVer") { item11.clean = LoadNewCleanTrack(item11.clean, "22B"); item11.battle = LoadNewBattleTrack(item11.battle, "22B"); } } break; case '6': if (!(currentScene == "Level 6-1")) { if (!(currentScene == "Level 6-2")) { return; } foreach (AudioSource item12 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item12).gameObject).name == "Organ") { item12.clip = LoadNewSingleTrack(item12.clip, "25A"); } else if (((Object)((Component)item12).gameObject).name == "BossMusic") { item12.clip = LoadNewSingleTrack(item12.clip, "25B"); } } break; } foreach (MusicChanger item13 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item13).gameObject).name == "MusicChanger") { item13.clean = LoadNewCleanTrack(item13.clean, "24A"); item13.battle = LoadNewBattleTrack(item13.battle, "24A"); } } foreach (AudioSource item14 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item14).gameObject).name == "ClimaxMusic") { item14.clip = LoadNewSingleTrack(item14.clip, "24B"); } } break; case '7': switch (currentScene) { default: return; case "Level 7-1": foreach (MusicChanger item15 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item15).name == "LevelMusicStart") { item15.clean = LoadNewCleanTrack(item15.clean, "26B"); item15.battle = LoadNewBattleTrack(item15.battle, "26B"); item15.boss = LoadNewBattleTrack(item15.battle, "26B"); } } foreach (AudioSource item16 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)item16).name == "IntroMusic") { item16.clip = LoadNewSingleTrack(item16.clip, "26A"); } else if (((Object)item16).name == "BigJohnatronMusic") { item16.clip = LoadNewSingleTrack(item16.clip, "26C"); } else if (((Object)item16).name == "MinotaurPhase1Music") { item16.clip = LoadNewSingleTrack(item16.clip, "26D"); } else if (((Object)item16).name == "MinotaurPhase2Music") { item16.clip = LoadNewSingleTrack(item16.clip, "26E"); } } break; case "Level 7-2": LoadMusicManagerTracks("27A"); foreach (MusicChanger item17 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item17).name == "MusicActivator") { item17.clean = LoadNewCleanTrack(item17.clean, "27B"); item17.battle = LoadNewBattleTrack(item17.battle, "27B"); item17.boss = LoadNewBattleTrack(item17.battle, "27B"); } } break; case "Level 7-3": LoadMusicManagerTracks("28A", single: true); foreach (MusicChanger item18 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)item18).name == "SecondTrackStart") { item18.clean = LoadNewCleanTrack(item18.clean, "28B"); item18.battle = LoadNewBattleTrack(item18.battle, "28B"); item18.boss = LoadNewBattleTrack(item18.battle, "28B"); } } break; } break; case 'P': if (!(currentScene == "Level P-1")) { if (!(currentScene == "Level P-2")) { return; } foreach (MusicChanger item19 in Core.FindAllComponentsInCurrentScene<MusicChanger>()) { if (((Object)((Component)item19).gameObject).name == "DelayedMusicActivator") { item19.clean = LoadNewCleanTrack(item19.clean, "667A"); item19.battle = LoadNewBattleTrack(item19.battle, "667A"); item19.boss = LoadNewBattleTrack(item19.battle, "667A"); } } foreach (AudioSource item20 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item20).gameObject).name == "FleshPrison") { item20.clip = LoadNewSingleTrack(item20.clip, "667B"); } else if (((Object)((Component)item20).gameObject).name == "Sisyphus") { item20.clip = LoadNewSingleTrack(item20.clip, "667C"); } } break; } foreach (AudioSource item21 in Core.FindAllComponentsInCurrentScene<AudioSource>()) { if (((Object)((Component)item21).gameObject).name == "Chaos") { item21.clip = LoadNewSingleTrack(item21.clip, "666A"); } else if (((Object)((Component)item21).gameObject).name == "Music 3") { item21.clip = LoadNewSingleTrack(item21.clip, "666B"); } } break; } } Core.Logger.LogInfo((object)"Music changed successfully."); } } public static class ColorRandomizer { public static void RandomizeGunColors() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 2; j++) { if (j != 2 || (i != 4 && i != 5)) { bool flag = false; if (j == 2) { flag = true; } for (int k = 1; k <= 3; k++) { MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "r" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "g" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "b" }), Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat(string.Concat(new object[6] { "gunColor.", i.ToString(), ".", k.ToString(), flag ? ".a" : ".", "a" }), Random.Range(0f, 1f)); } } } } if (Core.IsPlaying) { MonoSingleton<GunColorController>.Instance.UpdateGunColors(); GunColorTypeGetter[] array = Object.FindObjectsOfType<GunColorTypeGetter>(); for (int l = 0; l < array.Length; l++) { array[l].UpdatePreview(); } } } public static void RandomizeUIColors() { for (int i = 1; i <= 3; i++) { string text = ".r"; if (i == 2) { text = ".g"; } if (i == 3) { text = ".b"; } MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hp" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hptext" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hpaft" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hphdmg" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.hpover" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stm" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stmchr" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.stmemp" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.raifull" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.raicha" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var0" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var1" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var2" + text, Random.Range(0f, 1f)); MonoSingleton<PrefsManager>.Instance.SetFloat("hudColor.var3" + text, Random.Range(0f, 1f)); } if (Core.IsPlaying) { MonoSingleton<ColorBlindSettings>.Instance.UpdateHudColors(); MonoSingleton<ColorBlindSettings>.Instance.UpdateWeaponColors(); } } } public static class ConfigManager { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static OnClick <>9__88_0; public static OnClick <>9__88_1; public static OnClick <>9__88_2; public static PostStringValueChangeEvent <>9__88_3; public static BoolValueChangeEventDelegate <>9__88_4; public static BoolValueChangeEventDelegate <>9__88_5; public static BoolValueChangeEventDelegate <>9__88_6; public static EnumValueChangeEventDelegate<LogFont> <>9__88_7; public static IntValueChangeEventDelegate <>9__88_8; public static IntValueChangeEventDelegate <>9__88_9; public static IntValueChangeEventDelegate <>9__88_10; public static OnClick <>9__88_11; public static OnClick <>9__88_12; public static OnClick <>9__88_13; internal void <Initialize>b__88_0() { if (Multiworld.Authenticated) { connectionInfo.text = "Already connected to server."; } else if (SceneHelper.CurrentScene != "Main Menu") { connectionInfo.text = "Can only connect to an Archipelago server on the main menu."; } else if ((GameProgressSaver.GetTutorial() || GameProgressSaver.GetIntro()) && !Core.DataExists() && !hintMode.value) { connectionInfo.text = "No Archipelago data found. Start a new save file before connecting."; } else if (Core.DataExists() && hintMode.value) { connectionInfo.text = "Can't use hint mode on a save file that already has randomizer data."; } else if (!Multiworld.Authenticated) { Core.data.slot_name = playerName.value; Core.data.host_name = serverAddress.value; Core.data.password = serverPassword.value; if (Core.data.password == "") { Core.data.password = null; } if (hintMode.value) { Multiworld.ConnectBK(); } else { ((MonoBehaviour)Core.mw).StartCoroutine("Connect"); } SyncDeathLinkFieldsState(); } } internal void <Initialize>b__88_1() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Authenticated) { Multiworld.Disconnect(); connectionInfo.text = "Disconnected from server."; SyncDeathLinkFieldsState(); if (SceneHelper.CurrentScene == "Main Menu") { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } } } internal void <Initialize>b__88_2() { if (Multiworld.Authenticated) { bool flag = (Core.data.deathLink = !Core.data.deathLink); if (flag) { Multiworld.EnableDeathLink(); } else { Multiworld.DisableDeathLink(); } deathLinkToggleButton.text = (flag ? "DISABLE DEATH LINK" : "ENABLE DEATH LINK"); SyncDeathLinkThresholdFieldState(); } } internal void <Initialize>b__88_3(string value) { if (Multiworld.Authenticated) { if (value != "") { Multiworld.Session.Say(value); } chat.value = ""; } } internal void <Initialize>b__88_4(BoolValueChangeEvent e) { GameObject recentLocationContainer = UIManager.recentLocationContainer; if (recentLocationContainer != null) { recentLocationContainer.SetActive(e.value); } } internal void <Initialize>b__88_5(BoolValueChangeEvent e) { GameObject recentItemContainer = UIManager.recentItemContainer; if (recentItemContainer != null) { recentItemContainer.SetActive(e.value); } } internal void <Initialize>b__88_6(BoolValueChangeEvent e) { ((Component)UIManager.log).gameObject.SetActive(e.value); } internal void <Initialize>b__88_7(EnumValueChangeEvent<LogFont> e) { UIManager.SetLogFont(e.value, reset: true); } internal void <Initialize>b__88_8(IntValueChangeEvent e) { UIManager.lines = e.value; while (Multiworld.messages.Count > e.value) { Multiworld.messages.RemoveAt(0); } } internal void <Initialize>b__88_9(IntValueChangeEvent e) { ((TMP_Text)UIManager.log).fontSize = e.value; } internal void <Initialize>b__88_10(IntValueChangeEvent e) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) ((Graphic)UIManager.log).color = new Color(1f, 1f, 1f, (float)e.value / 100f); } internal void <Initialize>b__88_11() { UIManager.SetLogText(""); Multiworld.messages.Clear(); } internal void <Initialize>b__88_12() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); } internal void <Initialize>b__88_13() { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", false); } } private const string DisableDeathLinkText = "DISABLE DEATH LINK"; private const string EnableDeathLinkText = "ENABLE DEATH LINK"; private const int DefaultDeathLinkThreshold = 3; public static PluginConfigurator config; public static ConfigPanel playerPanel; public static ConfigHeader dataInfo; public static BoolField isConnected; public static StringField playerName; public static StringField serverAddress; public static StringField serverPassword; public static BoolField hintMode; public static ButtonField connectButton; public static ButtonField disconnectButton; public static ConfigHeader connectionInfo; private static ButtonField? deathLinkToggleButton; private static IntField? deathLinkThresholdField; public static StringField chat; public static StringField start; public static StringField goal; public static StringField goalProgress; public static BoolField perfectGoal; public static StringField locationsChecked; public static EnumField<EnemyOptions> enemyRewards; public static BoolField challengeRewards; public static BoolField pRankRewards; public static BoolField hankRewards; public static BoolField clashReward; public static BoolField fishRewards; public static BoolField cleanRewards; public static BoolField chessReward; public static BoolField rocketReward; public static EnumField<Fire2Options> randomizeFire2; public static EnumField<WeaponForm> revForm; public static EnumField<WeaponForm> shoForm; public static EnumField<WeaponForm> naiForm; public static BoolField randomizeSkulls; public static BoolField randomizeLimbo; public static BoolField randomizeViolence; public static BoolField musicRandomizer; public static BoolField cybergrindHints; public static BoolField deathLink; public static ConfigPanel uiPanel; public static BoolField showRecentLocations; public static BoolField showRecentItems; public static BoolField showLog; public static EnumField<LogFont> logFont; public static IntField logLines; public static IntField logFontSize; public static IntField logOpacity; public static ButtonField logClear; public static ConfigPanel colorPanel; public static EnumField<ColorOptions> uiColorRandomizer; public static EnumField<ColorOptions> gunColorRandomizer; public static ButtonField enableCustomButton; public static ButtonField disableCustomButton; public static ColorField APPlayerSelf; public static ColorField APPlayerOther; public static ColorField APItemAdvancement; public static ColorField APItemNeverExclude; public static ColorField APItemFiller; public static ColorField APItemTrap; public static ColorField APLocation; public static ColorField layer0Color; public static ColorField layer1Color; public static ColorField layer2Color; public static ColorField layer3Color; public static ColorField layer4Color; public static ColorField layer5Color; public static ColorField layer6Color; public static ColorField layer7Color; public static ColorField encore0Color; public static ColorField encore1Color; public static ColorField primeColor; public static ColorField altColor; public static ColorField blueSkullColor; public static ColorField redSkullColor; public static ColorField switchColor; public static ColorField pointsColor; public static ColorField dualwieldColor; public static ColorField doublejumpColor; public static ColorField confusionColor; public static ColorField trapColor; public static ButtonField thunderstoreButton; public static ButtonField githubButton; public static ButtonField discordButton; public static ButtonField poptrackerButton; public static int DeathLinkThreshold { get { IntField? obj = deathLinkThresholdField; if (obj == null) { return 3; } return obj.value; } } public static void Initialize() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Expected O, but got Unknown //IL_02dd: Expected O, but got Unknown //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Expected O, but got Unknown //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Expected O, but got Unknown //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Expected O, but got Unknown //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Expected O, but got Unknown //IL_03eb: 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_03fc: Expected O, but got Unknown //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Expected O, but got Unknown //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Expected O, but got Unknown //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Expected O, but got Unknown //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Expected O, but got Unknown //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Expected O, but got Unknown //IL_0519: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Expected O, but got Unknown //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0540: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Expected O, but got Unknown //IL_055d: Unknown result type (might be due to invalid IL or missing references) //IL_0562: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Expected O, but got Unknown //IL_0693: Unknown result type (might be due to invalid IL or missing references) //IL_0698: Unknown result type (might be due to invalid IL or missing references) //IL_06a4: Expected O, but got Unknown //IL_06b5: Unknown result type (might be due to invalid IL or missing references) //IL_06ba: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Expected O, but got Unknown //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_06dc: Unknown result type (might be due to invalid IL or missing references) //IL_06e8: Expected O, but got Unknown //IL_06f9: Unknown result type (might be due to invalid IL or missing references) //IL_06fe: Unknown result type (might be due to invalid IL or missing references) //IL_070a: Expected O, but got Unknown //IL_071b: Unknown result type (might be due to invalid IL or missing references) //IL_0720: Unknown result type (might be due to invalid IL or missing references) //IL_072c: Expected O, but got Unknown //IL_073d: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Expected O, but got Unknown //IL_075a: Unknown result type (might be due to invalid IL or missing references) //IL_0770: Unknown result type (might be due to invalid IL or missing references) //IL_077a: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Expected O, but got Unknown //IL_07b3: Unknown result type (might be due to invalid IL or missing references) //IL_07bd: Expected O, but got Unknown //IL_0793: Unknown result type (might be due to invalid IL or missing references) //IL_0798: Unknown result type (might be due to invalid IL or missing references) //IL_079e: Expected O, but got Unknown //IL_07f2: Unknown result type (might be due to invalid IL or missing references) //IL_0809: Unknown result type (might be due to invalid IL or missing references) //IL_0813: Expected O, but got Unknown //IL_07d6: Unknown result type (might be due to invalid IL or missing references) //IL_07db: Unknown result type (might be due to invalid IL or missing references) //IL_07e1: Expected O, but got Unknown //IL_082c: Unknown result type (might be due to invalid IL or missing references) //IL_0831: Unknown result type (might be due to invalid IL or missing references) //IL_0837: Expected O, but got Unknown //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_08ce: Expected O, but got Unknown //IL_090d: Unknown result type (might be due to invalid IL or missing references) //IL_0917: Expected O, but got Unknown //IL_08e7: Unknown result type (might be due to invalid IL or missing references) //IL_08ec: Unknown result type (might be due to invalid IL or missing references) //IL_08f2: Expected O, but got Unknown //IL_0956: Unknown result type (might be due to invalid IL or missing references) //IL_0960: Expected O, but got Unknown //IL_0930: Unknown result type (might be due to invalid IL or missing references) //IL_0935: Unknown result type (might be due to invalid IL or missing references) //IL_093b: Expected O, but got Unknown //IL_0998: Unknown result type (might be due to invalid IL or missing references) //IL_09a2: Expected O, but got Unknown //IL_0979: Unknown result type (might be due to invalid IL or missing references) //IL_097e: Unknown result type (might be due to invalid IL or missing references) //IL_0984: Expected O, but got Unknown //IL_0a70: Unknown result type (might be due to invalid IL or missing references) //IL_0a7a: Expected O, but got Unknown //IL_09bb: Unknown result type (might be due to invalid IL or missing references) //IL_09c0: Unknown result type (might be due to invalid IL or missing references) //IL_09c6: Expected O, but got Unknown //IL_0ab2: Unknown result type (might be due to invalid IL or missing references) //IL_0abc: Expected O, but got Unknown //IL_0a93: Unknown result type (might be due to invalid IL or missing references) //IL_0a98: Unknown result type (might be due to invalid IL or missing references) //IL_0a9e: Expected O, but got Unknown //IL_0af1: Unknown result type (might be due to invalid IL or missing references) //IL_0b15: Unknown result type (might be due to invalid IL or missing references) //IL_0b1b: Unknown result type (might be due to invalid IL or missing references) //IL_0b25: Expected O, but got Unknown //IL_0b43: Unknown result type (might be due to invalid IL or missing references) //IL_0b49: Unknown result type (might be due to invalid IL or missing references) //IL_0b53: Expected O, but got Unknown //IL_0b71: Unknown result type (might be due to invalid IL or missing references) //IL_0b77: Unknown result type (might be due to invalid IL or missing references) //IL_0b81: Expected O, but got Unknown //IL_0b9f: Unknown result type (might be due to invalid IL or missing references) //IL_0ba5: Unknown result type (might be due to invalid IL or missing references) //IL_0baf: Expected O, but got Unknown //IL_0bcd: Unknown result type (might be due to invalid IL or missing references) //IL_0bd3: Unknown result type (might be due to invalid IL or missing references) //IL_0bdd: Expected O, but got Unknown //IL_0bfb: Unknown result type (might be due to invalid IL or missing references) //IL_0c01: Unknown result type (might be due to invalid IL or missing references) //IL_0c0b: Expected O, but got Unknown //IL_0c29: Unknown result type (might be due to invalid IL or missing references) //IL_0c2f: Unknown result type (might be due to invalid IL or missing references) //IL_0c39: Expected O, but got Unknown //IL_0c45: Unknown result type (might be due to invalid IL or missing references) //IL_0c69: Unknown result type (might be due to invalid IL or missing references) //IL_0c6f: Unknown result type (might be due to invalid IL or missing references) //IL_0c79: Expected O, but got Unknown //IL_0c97: Unknown result type (might be due to invalid IL or missing references) //IL_0c9d: Unknown result type (might be due to invalid IL or missing references) //IL_0ca7: Expected O, but got Unknown //IL_0cc5: Unknown result type (might be due to invalid IL or missing references) //IL_0ccb: Unknown result type (might be due to invalid IL or missing references) //IL_0cd5: Expected O, but got Unknown //IL_0cf3: Unknown result type (might be due to invalid IL or missing references) //IL_0cf9: Unknown result type (might be due to invalid IL or missing references) //IL_0d03: Expected O, but got Unknown //IL_0d21: Unknown result type (might be due to invalid IL or missing references) //IL_0d27: Unknown result type (might be due to invalid IL or missing references) //IL_0d31: Expected O, but got Unknown //IL_0d4f: Unknown result type (might be due to invalid IL or missing references) //IL_0d55: Unknown result type (might be due to invalid IL or missing references) //IL_0d5f: Expected O, but got Unknown //IL_0d7d: Unknown result type (might be due to invalid IL or missing references) //IL_0d83: Unknown result type (might be due to invalid IL or missing references) //IL_0d8d: Expected O, but got Unknown //IL_0dab: Unknown result type (might be due to invalid IL or missing references) //IL_0db1: Unknown result type (might be due to invalid IL or missing references) //IL_0dbb: Expected O, but got Unknown //IL_0dd9: Unknown result type (might be due to invalid IL or missing references) //IL_0ddf: Unknown result type (might be due to invalid IL or missing references) //IL_0de9: Expected O, but got Unknown //IL_0e07: Unknown result type (might be due to invalid IL or missing references) //IL_0e0d: Unknown result type (might be due to invalid IL or missing references) //IL_0e17: Expected O, but got Unknown //IL_0e35: Unknown result type (might be due to invalid IL or missing references) //IL_0e3b: Unknown result type (might be due to invalid IL or missing references) //IL_0e45: Expected O, but got Unknown //IL_0e63: Unknown result type (might be due to invalid IL or missing references) //IL_0e69: Unknown result type (might be due to invalid IL or missing references) //IL_0e73: Expected O, but got Unknown //IL_0e91: Unknown result type (might be due to invalid IL or missing references) //IL_0e97: Unknown result type (might be due to invalid IL or missing references) //IL_0ea1: Expected O, but got Unknown //IL_0ebf: Unknown result type (might be due to invalid IL or missing references) //IL_0ec5: Unknown result type (might be due to invalid IL or missing references) //IL_0ecf: Expected O, but got Unknown //IL_0eed: Unknown result type (might be due to invalid IL or missing references) //IL_0ef3: Unknown result type (might be due to invalid IL or missing references) //IL_0efd: Expected O, but got Unknown //IL_0f1b: Unknown result type (might be due to invalid IL or missing references) //IL_0f21: Unknown result type (might be due to invalid IL or missing references) //IL_0f2b: Expected O, but got Unknown //IL_0f49: Unknown result type (might be due to invalid IL or missing references) //IL_0f4f: Unknown result type (might be due to invalid IL or missing references) //IL_0f59: Expected O, but got Unknown //IL_0f77: Unknown result type (might be due to invalid IL or missing references) //IL_0f7d: Unknown result type (might be due to invalid IL or missing references) //IL_0f87: Expected O, but got Unknown //IL_0fa5: Unknown result type (might be due to invalid IL or missing references) //IL_0fab: Unknown result type (might be due to invalid IL or missing references) //IL_0fb5: Expected O, but got Unknown //IL_0fd3: Unknown result type (might be due to invalid IL or missing references) //IL_0fd9: Unknown result type (might be due to invalid IL or missing references) //IL_0fe3: Expected O, but got Unknown //IL_0ad5: Unknown result type (might be due to invalid IL or missing references) //IL_0ada: Unknown result type (might be due to invalid IL or missing references) //IL_0ae0: Expected O, but got Unknown if (config != null) { return; } config = PluginConfigurator.Create("Archipelago", "maybeAshleyIdk.ultrakillArchipelago"); string text = Path.Combine(Core.workingDir, "icon.png"); if (File.Exists(text)) { config.SetIconWithURL(text); } new ConfigHeader(config.rootPanel, "ARCHIPELAGO", 24); playerPanel = new ConfigPanel(config.rootPanel, "PLAYER SETTINGS", "playerPanel"); dataInfo = new ConfigHeader(config.rootPanel, "", 16); new ConfigHeader(config.rootPanel, "---", 24); uiPanel = new ConfigPanel(config.rootPanel, "UI SETTINGS", "uiPanel"); colorPanel = new ConfigPanel(config.rootPanel, "COLOR SETTINGS", "colorPanel"); isConnected = new BoolField(playerPanel, "CONNECTED TO SERVER?", "isConnected", false, false); ((ConfigField)isConnected).interactable = false; playerName = new StringField(playerPanel, "NAME", "playerName", "V1", false, true); serverAddress = new StringField(playerPanel, "ADDRESS", "serverAddress", "archipelago.gg", false, true); serverPassword = new StringField(playerPanel, "PASSWORD", "serverPassword", "", true, true); hintMode = new BoolField(playerPanel, "HINT MODE", "hintMode", false, false); new ConfigHeader(playerPanel, "Hint mode disables all randomization, and allows connecting to other games' slots to unlock hints while playing The Cyber Grind.", 12, (TextAlignmentOptions)257); connectionInfo = new ConfigHeader(playerPanel, "", 16, (TextAlignmentOptions)258); connectButton = new ButtonField(playerPanel, "CONNECT", "connectButton"); ButtonField obj = connectButton; object obj2 = <>c.<>9__88_0; if (obj2 == null) { OnClick val = delegate { if (Multiworld.Authenticated) { connectionInfo.text = "Already connected to server."; } else if (SceneHelper.CurrentScene != "Main Menu") { connectionInfo.text = "Can only connect to an Archipelago server on the main menu."; } else if ((GameProgressSaver.GetTutorial() || GameProgressSaver.GetIntro()) && !Core.DataExists() && !hintMode.value) { connectionInfo.text = "No Archipelago data found. Start a new save file before connecting."; } else if (Core.DataExists() && hintMode.value) { connectionInfo.text = "Can't use hint mode on a save file that already has randomizer data."; } else if (!Multiworld.Authenticated) { Core.data.slot_name = playerName.value; Core.data.host_name = serverAddress.value; Core.data.password = serverPassword.value; if (Core.data.password == "") { Core.data.password = null; } if (hintMode.value) { Multiworld.ConnectBK(); } else { ((MonoBehaviour)Core.mw).StartCoroutine("Connect"); } SyncDeathLinkFieldsState(); } }; <>c.<>9__88_0 = val; obj2 = (object)val; } obj.onClick += (OnClick)obj2; disconnectButton = new ButtonField(playerPanel, "DISCONNECT", "disconnectButton"); ButtonField obj3 = disconnectButton; object obj4 = <>c.<>9__88_1; if (obj4 == null) { OnClick val2 = delegate { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (Multiworld.Authenticated) { Multiworld.Disconnect(); connectionInfo.text = "Disconnected from server."; SyncDeathLinkFieldsState(); if (SceneHelper.CurrentScene == "Main Menu") { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } } }; <>c.<>9__88_1 = val2; obj4 = (object)val2; } obj3.onClick += (OnClick)obj4; deathLinkToggleButton = new ButtonField(playerPanel, Core.data.deathLink ? "DISABLE DEATH LINK" : "ENABLE DEATH LINK", "deathLinkToggleButton") { interactable = Multiworld.Authenticated }; ButtonField? obj5 = deathLinkToggleButton; object obj6 = <>c.<>9__88_2; if (obj6 == null) { OnClick val3 = delegate { if (Multiworld.Authenticated) { bool flag = (Core.data.deathLink = !Core.data.deathLink); if (flag) { Multiworld.EnableDeathLink(); } else { Multiworld.DisableDeathLink(); } deathLinkToggleButton.text = (flag ? "DISABLE DEATH LINK" : "ENABLE DEATH LINK"); SyncDeathLinkThresholdFieldState(); } }; <>c.<>9__88_2 = val3; obj6 = (object)val3; } obj5.onClick += (OnClick)obj6; deathLinkThresholdField = new IntField(playerPanel, "DEATH LINK THRESHOLD", "deathLinkThreshold", 3, 1, 999, true, true) { interactable = (((ConfigField)deathLinkToggleButton).interactable && !Core.data.deathLink) }; chat = new StringField(playerPanel, "CHAT", "chat", "", true, false) { interactable = false }; StringField obj7 = chat; object obj8 = <>c.<>9__88_3; if (obj8 == null) { PostStringValueChangeEvent val4 = delegate(string value) { if (Multiworld.Authenticated) { if (value != "") { Multiworld.Session.Say(value); } chat.value = ""; } }; <>c.<>9__88_3 = val4; obj8 = (object)val4; } obj7.postValueChangeEvent += (PostStringValueChangeEvent)obj8; new ConfigHeader(playerPanel, "-----", 24); start = new StringField(playerPanel, "START LEVEL", "start", "?", false, false) { interactable = false }; goal = new StringField(playerPanel, "GOAL LEVEL", "goal", "?", false, false) { interactable = false }; goalProgress = new StringField(playerPanel, "LEVELS COMPLETED", "goalProgress", "?", false, false) { interactable = false }; perfectGoal = new BoolField(playerPanel, "PERFECT GOAL", "perfectGoal", false) { interactable = false }; locationsChecked = new StringField(playerPanel, "LOCATIONS CHECKED", "locationsChecked", "?", false, false) { interactable = false }; EnumField<EnemyOptions> obj9 = new EnumField<EnemyOptions>(playerPanel, "ENEMY REWARDS", "enemyRewards", EnemyOptions.Disabled, false); ((ConfigField)obj9).interactable = false; enemyRewards = obj9; enemyRewards.SetEnumDisplayName(EnemyOptions.Disabled, "DISABLED"); enemyRewards.SetEnumDisplayName(EnemyOptions.Bosses, "BOSSES"); enemyRewards.SetEnumDisplayName(EnemyOptions.Extra, "EXTRA"); enemyRewards.SetEnumDisplayName(EnemyOptions.All, "All"); challengeRewards = new BoolField(playerPanel, "CHALLENGE REWARDS", "challengeRewards", false, false) { interactable = false }; pRankRewards = new BoolField(playerPanel, "P RANK REWARDS", "pRankRewards", false, false) { interactable = false }; hankRewards = new BoolField(playerPanel, "HANK REWARDS", "hankRewards", false, false) { interactable = false }; clashReward = new BoolField(playerPanel, "RANDOMIZE CLASH MODE", "clashReward", false, false) { interactable = false }; fishRewards = new BoolField(playerPanel, "FISH REWARDS", "fishRewards", false, false) { interactable = false }; cleanRewards = new BoolField(playerPanel, "CLEANING REWARDS", "cleanRewards", false, false) { interactable = false }; chessReward = new BoolField(playerPanel, "CHESS REWARD", "chessReward", false, false) { interactable = false }; rocketReward = new BoolField(playerPanel, "ROCKET RACE REWARD", "rocketReward", false, false) { interactable = false }; EnumField<Fire2Options> obj10 = new EnumField<Fire2Options>(playerPanel, "RANDOMIZE SECONDARY FIRE", "randomizeFire2", Fire2Options.Disabled); ((ConfigField)obj10).interactable = false; randomizeFire2 = obj10; randomizeFire2.SetEnumDisplayName(Fire2Options.Disabled, "DISABLED"); randomizeFire2.SetEnumDisplayName(Fire2Options.Split, "SPLIT"); randomizeFire2.SetEnumDisplayName(Fire2Options.Progressive, "PROGRESSIVE"); EnumField<WeaponForm> obj11 = new EnumField<WeaponForm>(playerPanel, "REVOLVER FORM", "revForm", WeaponForm.Standard); ((ConfigField)obj11).interactable = false; revForm = obj11; revForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); revForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); EnumField<WeaponForm> obj12 = new EnumField<WeaponForm>(playerPanel, "SHOTGUN FORM", "shoForm", WeaponForm.Standard); ((ConfigField)obj12).interactable = false; shoForm = obj12; shoForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); shoForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); EnumField<WeaponForm> obj13 = new EnumField<WeaponForm>(playerPanel, "NAILGUN FORM", "naiForm", WeaponForm.Standard); ((ConfigField)obj13).interactable = false; naiForm = obj13; naiForm.SetEnumDisplayName(WeaponForm.Standard, "STANDARD"); naiForm.SetEnumDisplayName(WeaponForm.Alternate, "ALTERNATE"); randomizeSkulls = new BoolField(playerPanel, "RANDOMIZE SKULLS", "randomizeSkulls", false, false) { interactable = false }; randomizeLimbo = new BoolField(playerPanel, "RANDOMIZE LIMBO SWITCHES", "randomizeLimbo", false, false) { interactable = false }; randomizeViolence = new BoolField(playerPanel, "RANDOMIZE VIOLENCE SWITCHES", "randomizeViolence", false, false) { interactable = false }; musicRandomizer = new BoolField(playerPanel, "MUSIC RANDOMIZER", "musicRandomizer", false, false) { interactable = false }; cybergrindHints = new BoolField(playerPanel, "UNLOCK HINTS IN CYBERGRIND", "cybergrindHints", false, false) { interactable = false }; deathLink = new BoolField(playerPanel, "DEATH LINK", "deathLink", false, false) { interactable = false }; new ConfigHeader(uiPanel, "PAUSE MENU", 24); showRecentLocations = new BoolField(uiPanel, "SHOW RECENT LOCATIONS", "showRecentLocations", true); BoolField obj14 = showRecentLocations; object obj15 = <>c.<>9__88_4; if (obj15 == null) { BoolValueChangeEventDelegate val5 = delegate(BoolValueChangeEvent e) { GameObject recentLocationContainer = UIManager.recentLocationContainer; if (recentLocationContainer != null) { recentLocationContainer.SetActive(e.value); } }; <>c.<>9__88_4 = val5; obj15 = (object)val5; } obj14.onValueChange += (BoolValueChangeEventDelegate)obj15; showRecentItems = new BoolField(uiPanel, "SHOW RECENT ITEMS", "showRecentItems", true); BoolField obj16 = showRecentItems; object obj17 = <>c.<>9__88_5; if (obj17 == null) { BoolValueChangeEventDelegate val6 = delegate(BoolValueChangeEvent e) { GameObject recentItemContainer = UIManager.recentItemContainer; if (recentItemContainer != null) { recentItemContainer.SetActive(e.value); } }; <>c.<>9__88_5 = val6; obj17 = (object)val6; } obj16.onValueChange += (BoolValueChangeEventDelegate)obj17; new ConfigHeader(uiPanel, "LOG", 24); showLog = new BoolField(uiPanel, "SHOW LOG", "showLog", true, true); BoolField obj18 = showLog; object obj19 = <>c.<>9__88_6; if (obj19 == null) { BoolValueChangeEventDelegate val7 = delegate(BoolValueChangeEvent e) { ((Component)UIManager.log).gameObject.SetActive(e.value); }; <>c.<>9__88_6 = val7; obj19 = (object)val7; } obj18.onValueChange += (BoolValueChangeEventDelegate)obj19; logFont = new EnumField<LogFont>(uiPanel, "FONT", "logFont", LogFont.Pixel1); logFont.SetEnumDisplayName(LogFont.Pixel1, "fs Tahoma 8px"); logFont.SetEnumDisplayName(LogFont.Pixel2, "VCR OSD MONO"); logFont.SetEnumDisplayName(LogFont.SansSerif, "Roboto"); logFont.onValueChange += delegate(EnumValueChangeEvent<LogFont> e) { UIManager.SetLogFont(e.value, reset: true); }; logLines = new IntField(uiPanel, "NUMBER OF MESSAGES", "logLines", 5, 1, 16, true, true); IntField obj20 = logLines; object obj21 = <>c.<>9__88_8; if (obj21 == null) { IntValueChangeEventDelegate val8 = delegate(IntValueChangeEvent e) { UIManager.lines = e.value; while (Multiworld.messages.Count > e.value) { Multiworld.messages.RemoveAt(0); } }; <>c.<>9__88_8 = val8; obj21 = (object)val8; } obj20.onValueChange += (IntValueChangeEventDelegate)obj21; logFontSize = new IntField(uiPanel, "FONT SIZE", "logFontSize", 20, 1, 32, true, true); IntField obj22 = logFontSize; object obj23 = <>c.<>9__88_9; if (obj23 == null) { IntValueChangeEventDelegate val9 = delegate(IntValueChangeEvent e) { ((TMP_Text)UIManager.log).fontSize = e.value; }; <>c.<>9__88_9 = val9; obj23 = (object)val9; } obj22.onValueChange += (IntValueChangeEventDelegate)obj23; logOpacity = new IntField(uiPanel, "OPACITY", "logOpacity", 100, 0, 100, true, true); IntField obj24 = logOpacity; object obj25 = <>c.<>9__88_10; if (obj25 == null) { IntValueChangeEventDelegate val10 = delegate(IntValueChangeEvent e) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) ((Graphic)UIManager.log).color = new Color(1f, 1f, 1f, (float)e.value / 100f); }; <>c.<>9__88_10 = val10; obj25 = (object)val10; } obj24.onValueChange += (IntValueChangeEventDelegate)obj25; logClear = new ButtonField(uiPanel, "CLEAR LOG", "logClear"); ButtonField obj26 = logClear; object obj27 = <>c.<>9__88_11; if (obj27 == null) { OnClick val11 = delegate { UIManager.SetLogText(""); Multiworld.messages.Clear(); }; <>c.<>9__88_11 = val11; obj27 = (object)val11; } obj26.onClick += (OnClick)obj27; uiColorRandomizer = new EnumField<ColorOptions>(colorPanel, "UI COLOR RANDOMIZER", "uiColorRandomizer", ColorOptions.Off, true); uiColorRandomizer.SetEnumDisplayName(ColorOptions.Off, "DISABLED"); uiColorRandomizer.SetEnumDisplayName(ColorOptions.Once, "ONCE"); uiColorRandomizer.SetEnumDisplayName(ColorOptions.EveryLoad, "EVERY NEW LEVEL LOADED"); gunColorRandomizer = new EnumField<ColorOptions>(colorPanel, "GUN COLOR RANDOMIZER", "gunColorRandomizer", ColorOptions.Off, true); gunColorRandomizer.SetEnumDisplayName(ColorOptions.Off, "DISABLED"); gunColorRandomizer.SetEnumDisplayName(ColorOptions.Once, "ONCE"); gunColorRandomizer.SetEnumDisplayName(ColorOptions.EveryLoad, "EVERY NEW LEVEL LOADED"); enableCustomButton = new ButtonField(colorPanel, "ENABLE ALL CUSTOM WEAPON COLORS", "enableCustomButton"); ButtonField obj28 = enableCustomButton; object obj29 = <>c.<>9__88_12; if (obj29 == null) { OnClick val12 = delegate { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", true); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", true); }; <>c.<>9__88_12 = val12; obj29 = (object)val12; } obj28.onClick += (OnClick)obj29; disableCustomButton = new ButtonField(colorPanel, "DISABLE ALL CUSTOM WEAPON COLORS", "disableCustomButton"); ButtonField obj30 = disableCustomButton; object obj31 = <>c.<>9__88_13; if (obj31 == null) { OnClick val13 = delegate { MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.1.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.2", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.3.a", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.4", false); MonoSingleton<PrefsManager>.Instance.SetBool("gunColorType.5", false); }; <>c.<>9__88_13 = val13; obj31 = (object)val13; } obj30.onClick += (OnClick)obj31; new ConfigHeader(colorPanel, "ARCHIPELAGO COLORS", 24); APPlayerSelf = new ColorField(colorPanel, "PLAYER (YOU)", "APPlayerSelf", new Color(0.93f, 0f, 0.93f), true); APPlayerOther = new ColorField(colorPanel, "PLAYER (OTHERS)", "APPlayerOther", new Color(0.98f, 0.98f, 0.82f), true); APItemFiller = new ColorField(colorPanel, "ITEM (FILLER)", "APItemFiller", new Color(0f, 0.93f, 0.93f), true); APItemNeverExclude = new ColorField(colorPanel, "ITEM (USEFUL)", "APItemNeverExclude", new Color(0.43f, 0.55f, 0.91f), true); APItemAdvancement = new ColorField(colorPanel, "ITEM (PROGRESSION)", "APItemAdvancement", new Color(0.69f, 0.6f, 0.94f), true); APItemTrap = new ColorField(colorPanel, "ITEM (TRAP)", "APItemTrap", new Color(0.98f, 0.5f, 0.45f), true); APLocation = new ColorField(colorPanel, "LOCATION", "APLocation", new Color(0f, 1f, 0.5f), true); new ConfigHeader(colorPanel, "ITEM / LOCATION COLORS", 24); layer0Color = new ColorField(colorPanel, "LAYER 0", "layer0Color", new Color(1f, 0.5f, 0.25f), true); layer1Color = new ColorField(colorPanel, "LAYER 1", "layer1Color", new Color(0.2667f, 1f, 0.2706f), true); layer2Color = new ColorField(colorPanel, "LAYER 2", "layer2Color", new Color(0.765f, 0.25f, 1f), true); layer3Color = new ColorField(colorPanel, "LAYER 3", "layer3Color", new Color(1f, 0.9479f, 0.8566f), true); layer4Color = new ColorField(colorPanel, "LAYER 4", "layer4Color", new Color(1f, 1f, 0.25f), true); layer5Color = new ColorField(colorPanel, "LAYER 5", "layer5Color", new Color(0.251f, 0.9059f, 1f), true); layer6Color = new ColorField(colorPanel, "LAYER 6", "layer6Color", new Color(1f, 0.2353f, 0.2353f), true); layer7Color = new ColorField(colorPanel, "LAYER 7", "layer7Color", new Color(0.8f, 0.8f, 0.8f), true); encore0Color = new ColorField(colorPanel, "ENCORE 0", "encore0Color", new Color(0.6431f, 0.8745f, 0.9882f), true); encore1Color = new ColorField(colorPanel, "ENCORE 1", "encore1Color", new Color(0.5f, 0.5f, 0.5f), true); primeColor = new ColorField(colorPanel, "PRIME SANCTUMS", "primeColor", new Color(1f, 0.2353f, 0.2353f), true); altColor = new ColorField(colorPanel, "ALTERNATE WEAPON", "altColor", new Color(1f, 0.65f, 0f), true); blueSkullColor = new ColorField(colorPanel, "BLUE SKULL", "blueSkullColor", new Color(0.251f, 0.9059f, 1f), true); redSkullColor = new ColorField(colorPanel, "RED SKULL", "redSkullColor", new Color(1f, 0.2353f, 0.2353f), true); switchColor = new ColorField(colorPanel, "SWITCH", "switchColor", new Color(0.25f, 0.3f, 1f), true); pointsColor = new ColorField(colorPanel, "POINTS", "pointsColor", new Color(1f, 0.65f, 0f), true); dualwieldColor = new ColorField(colorPanel, "DUAL WIELD", "dualwieldColor", new Color(1f, 1f, 0.25f), true); doublejumpColor = new ColorField(colorPanel, "AIR JUMP", "doublejumpColor", new Color(1f, 1f, 0.6f), true); confusionColor = new ColorField(colorPanel, "CONFUSING AURA", "confusionColor", new Color(0.8242f, 1f, 0.1289f), true); trapColor = new ColorField(colorPanel, "TRAP", "trapColor", new Color(0.7f, 0.7f, 0.7f), true); } private static void SyncDeathLinkFieldsState() { SyncDeathLinkToggleButtonState(); SyncDeathLinkThresholdFieldState(); } private static void SyncDeathLinkToggleButtonState() { ButtonField val = deathLinkToggleButton; if (val != null) { ((ConfigField)val).interactable = Multiworld.Authenticated; val.text = (Core.data.deathLink ? "DISABLE DEATH LINK" : "ENABLE DEATH LINK"); } } private static void SyncDeathLinkThresholdFieldState() { IntField val = deathLinkThresholdField; if (val != null) { ButtonField val2 = deathLinkToggleButton; ((ConfigField)val).interactable = val2 != null && ((ConfigField)val2).interactable && !Core.data.deathLink; } } public static void LoadConnectionInfo() { if (Core.data.slot_name != null) { playerName.value = Core.data.slot_name; } if (Core.data.host_name != null) { serverAddress.value = Core.data.host_name; } if (Core.data.password != null) { serverPassword.value = Core.data.password; } } public static void LoadStats() { dataInfo.text = Core.data.ToString(); start.value = Core.data.start; goal.value = Core.data.goal; goalProgress.value = $"{Core.data.completedLevels.Count} / {Core.data.goalRequirement}"; perfectGoal.value = Core.data.perfectGoal; string arg = ((LocationManager.locations.Count == 0) ? "?" : LocationManager.locations.Count.ToString()); locationsChecked.value = $"{[email protected]} / {arg}"; enemyRewards.value = Core.data.enemyRewards; challengeRewards.value = Core.data.challengeRewards; pRankRewards.value = Core.data.pRankRewards; hankRewards.value = Core.data.hankRewards; clashReward.value = Core.data.clashReward; fishRewards.value = Core.data.fishRewards; cleanRewards.value = Core.data.cleanRewards; chessReward.value = Core.data.chessReward; rocketReward.value = Core.data.rocketReward; randomizeFire2.value = Core.data.randomizeFire2; revForm.value = Core.data.revForm; shoForm.value = Core.data.shoForm; naiForm.value = Core.data.naiForm; randomizeSkulls.value = Core.data.randomizeSkulls; randomizeLimbo.value = Core.data.l1switch; randomizeViolence.value = Core.data.l7switch; musicRandomizer.value = Core.data.musicRandomizer; cybergrindHints.value = Core.data.cybergrindHints; deathLink.value = Core.data.deathLink; SyncDeathLinkFieldsState(); } public static void ResetStatsDefaults() { if ((GameProgressSaver.GetTutorial() || GameProgressSaver.GetIntro()) && !Core.DataExists()) { dataInfo.text = "Current slot is not randomized."; } else { dataInfo.text = Core.data.ToString(); } start.value = "?"; goal.value = "?"; goalProgress.value = "?"; perfectGoal.value = false; locationsChecked.value = "?"; enemyRewards.value = EnemyOptions.Disabled; challengeRewards.value = false; pRankRewards.value = false; hankRewards.value = false; clashReward.value = false; fishRewards.value = false; cleanRewards.value = false; chessReward.value = false; rocketReward.value = false; randomizeFire2.value = Fire2Options.Disabled; revForm.value = WeaponForm.Standard; shoForm.value = WeaponForm.Standard; naiForm.value = WeaponForm.Standard; randomizeSkulls.value = false; randomizeLimbo.value = false; randomizeViolence.value = false; musicRandomizer.value = false; cybergrindHints.value = false; deathLink.value = false; } } [BepInPlugin("maybeAshleyIdk.ultrakillArchipelago", "Archipelago Client", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("trpg.archipelagoultrakill")] public class Core : BaseUnityPlugin { [CompilerGenerated] private sealed class <ApplyLoadout>d__65 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public WeaponLoadout loadout; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyLoadout>d__65(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func<bool>)(() => Multiworld.Session.Items.Index == data.index && LocationManager.itemQueue.Count == 0)); <>1__state = 1; return true; case 1: <>1__state = -1; loadout.Set(); Logger.LogInfo((object)"Set loadout"); 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 const string PluginGUID = "maybeAshleyIdk.ultrakillArchipelago"; public const string PluginName = "Archipelago Client"; public const string PluginVersion = "0.1.0"; public static string workingPath; public static string workingDir; public static GameObject obj; public static UIManager uim; public static Multiworld mw; public static Data data = new Data(); public static bool firstTimeLoad = false; public static readonly List<LevelInfo> levelInfos = new List<LevelInfo> { new LevelInfo("0-1", 1, 0, hasSecrets: true, MusicType.Normal, SkullsType.None), new LevelInfo("0-2", 2, 0, hasSecrets: true, MusicType.Normal, SkullsType.Normal, new List<string> { "2_b" }), new LevelInfo("0-3", 3, 0, hasSecrets: true, MusicType.Normal, SkullsType.None), new LevelInfo("0-4", 4, 0, hasSecrets: true, MusicType.Normal, SkullsType.None), new LevelInfo("0-5", 5, 0, hasSecrets: false, MusicType.Special2, SkullsType.None), new LevelInfo("1-1", 6, 1, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "6_b", "6_r" }), new LevelInfo("1-2", 7, 1, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "7_r", "7_b" }), new LevelInfo("1-3", 8, 1, hasSecrets: true, MusicType.Normal, SkullsType.Normal, new List<string> { "8_r", "8_b" }), new LevelInfo("1-4", 9, 1, hasSecrets: false, MusicType.Special, SkullsType.Special), new LevelInfo("2-1", 10, 2, hasSecrets: true, MusicType.Special, SkullsType.None), new LevelInfo("2-2", 11, 2, hasSecrets: true, MusicType.Normal, SkullsType.None), new LevelInfo("2-3", 12, 2, hasSecrets: true, MusicType.Normal, SkullsType.Normal, new List<string> { "12_r", "12_b" }), new LevelInfo("2-4", 13, 2, hasSecrets: false, MusicType.Special, SkullsType.Normal, new List<string> { "13_r", "13_b" }), new LevelInfo("3-1", 14, 3, hasSecrets: true, MusicType.Special, SkullsType.None), new LevelInfo("3-2", 15, 3, hasSecrets: false, MusicType.Special, SkullsType.None), new LevelInfo("4-1", 16, 4, hasSecrets: true, MusicType.Normal, SkullsType.None), new LevelInfo("4-2", 17, 4, hasSecrets: true, MusicType.Normal, SkullsType.Normal, new List<string> { "17_r", "17_b" }), new LevelInfo("4-3", 18, 4, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "18_b" }), new LevelInfo("4-4", 19, 4, hasSecrets: false, MusicType.Special, SkullsType.Normal, new List<string> { "19_b" }), new LevelInfo("5-1", 20, 5, hasSecrets: true, MusicType.Normal, SkullsType.Special), new LevelInfo("5-2", 21, 5, hasSecrets: true, MusicType.Skip, SkullsType.Normal, new List<string> { "21_r", "21_b" }), new LevelInfo("5-3", 22, 5, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "22_r", "22_b" }), new LevelInfo("5-4", 23, 5, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("6-1", 24, 6, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "24_r" }), new LevelInfo("6-2", 25, 6, hasSecrets: false, MusicType.Special, SkullsType.None), new LevelInfo("7-1", 26, 7, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "26_b", "26_r" }), new LevelInfo("7-2", 27, 7, hasSecrets: true, MusicType.Special, SkullsType.Normal, new List<string> { "27_r" }), new LevelInfo("7-3", 28, 7, hasSecrets: true, MusicType.Special, SkullsType.None), new LevelInfo("7-4", 29, 7, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("0-E", 100, 0, hasSecrets: false, MusicType.Skip, SkullsType.Normal, new List<string> { "100_r", "100_b" }), new LevelInfo("1-E", 101, 1, hasSecrets: false, MusicType.Skip, SkullsType.Normal, new List<string> { "101_b", "101_r" }), new LevelInfo("P-1", 666, 3, hasSecrets: false, MusicType.Special, SkullsType.None), new LevelInfo("P-2", 667, 6, hasSecrets: false, MusicType.Special, SkullsType.Normal, new List<string> { "667_b" }) }; public static readonly List<LevelInfo> secretMissionInfos = new List<LevelInfo> { new LevelInfo("0-S", 0, 0, hasSecrets: false, MusicType.Skip, SkullsType.Normal, new List<string> { "0S_r", "0S_b" }), new LevelInfo("1-S", 0, 1, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("2-S", 0, 2, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("4-S", 0, 4, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("5-S", 0, 5, hasSecrets: false, MusicType.Skip, SkullsType.None), new LevelInfo("7-S", 0, 7, hasSecrets: false, MusicType.Skip, SkullsType.Normal, new List<string> { "7S_b", "7S_r" }) }; public static readonly Dictionary<string, int> shopPrices = new Dictionary<string, int> { ["rev2"] = 7500, ["rev1"] = 12500, ["sho1"] = 12500, ["sho2"] = 25000, ["nai1"] = 25000, ["nai2"] = 35000, ["rai1"] = 100000, ["rai2"] = 100000, ["rock1"] = 75000, ["rock2"] = 75000 }; public static ManualLogSource Logger { get; } = Logger.CreateLogSource("Archipelago"); public static Logger PLogger { get; } = new Logger("Archipelago"); public static Core Instance { get; private set; } public static bool IsInIntro => GameStateManager.Instance.IsStateActive("intro"); public static bool IsPitFalling => GameStateManager.Instance.IsStateActive("pit-falling"); public static bool IsPaused { get { if (!GameStateManager.Instance.IsStateActive("pause")) { return GameStateManager.Instance.IsStateActive("pit-falling"); } return true; } } public static bool IsInLevel { get { if (!GameStateManager.Instance.IsStateActive("main-menu")) { return !GameStateManager.Instance.IsStateActive("intro"); } return false; } } public static bool IsPlaying { get { if (IsInLevel && !IsPaused) { return Object.op_Implicit((Object)(object)PlayerHelper.Instance); } return false; } } public static bool CanGetWeapon { get { if (IsInLevel && Object.op_Implicit((Object)(object)PlayerHelper.Instance)) { return Object.op_Implicit((Object)(object)MonoSingleton<GunSetter>.Instance); } return false; } } public static bool HasNoArms { get { if (!data.hasArm) { return GameProgressSaver.GetGeneralProgress().arm1 < 1; } return false; } } public static List<string> AllLevels { get { List<string> list = new List<string>(); foreach (LevelInfo levelInfo in levelInfos) { list.Add(levelInfo.Name); } return list; } } public static bool CurrentLevelHasInfo { get { if (SceneHelper.CurrentScene.Contains("-S")) { return true; } if (SceneHelper.CurrentScene.Contains("Level ")) { return !SceneHelper.IsSceneRankless; } return false; } } public static LevelInfo CurrentLevelInfo { get { if (SceneHelper.CurrentScene == "Level 0-S") { return secretMissionInfos[0]; } if (SceneHelper.CurrentScene == "Level 1-S") { return secretMissionInfos[1]; } if (SceneHelper.CurrentScene == "Level 2-S") { return secretMissionInfos[2]; } if (SceneHelper.CurrentScene == "Level 4-S") { return secretMissionInfos[3]; } if (SceneHelper.CurrentScene == "Level 5-S") { return secretMissionInfos[4]; } if (SceneHelper.CurrentScene == "Level 7-S") { return secretMissionInfos[5]; } if (CurrentLevelHasInfo) { return GetLevelInfo(SceneHelper.CurrentLevelNumber); } return null; } } public static bool CurrentLevelHasSkulls { get { LevelInfo currentLevelInfo = CurrentLevelInfo; if (currentLevelInfo != null && currentLevelInfo.Skulls > SkullsType.None) { return data.randomizeSkulls; } return false; } } public static bool CurrentLevelHasSwitches { get { LevelInfo currentLevelInfo = CurrentLevelInfo; if (currentLevelInfo == null || currentLevelInfo.Id != 9 || !data.l1switch) { LevelInfo currentLevelInfo2 = CurrentLevelInfo; if (currentLevelInfo2 != null && currentLevelInfo2.Id == 27) { return data.l7switch; } return false; } return true; } } public static LevelInfo GetLevelInfo(int id) { foreach (LevelInfo levelInfo in levelInfos) { if (levelInfo.Id == id) { return levelInfo; } } Logger.LogWarning((object)$"No level info for ID {id}."); return null; } public static LevelInfo GetLevelInfo(string name) { foreach (LevelInfo levelInfo in levelInfos) { if (levelInfo.Name == name) { return levelInfo; } } Logger.LogWarning((object)("No level info for name " + name + ".")); return null; } public static int GetLevelIdFromName(string name) { LevelInfo levelInfo = GetLevelInfo(name); if (levelInfo == null) { Logger.LogWarning((object)("No level info for name " + name + ".")); return 0; } return levelInfo.Id; } public static string GetLevelNameFromId(int id) { LevelInfo levelInfo = GetLevelInfo(id); if (levelInfo == null) { Logger.LogWarning((object)$"No level info for ID {id}."); return null; } return levelInfo.Name; } public void Awake() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) Instance = this; new Harmony("archipelago").PatchAll(); workingPath = Assembly.GetExecutingAssembly().Location; workingDir = Path.GetDirectoryName(workingPath); ConfigManager.Initialize(); SceneManager.sceneLoaded += OnSceneLoaded; LocationManager.RegenerateItemDefinitions(); AsyncOperationHandle<Sprite> val = Addressables.LoadAssetAsync<Sprite>((object)"Assets/Textures/UI/Controls/Round_VertHandle_Invert 1.png"); UIManager.menuSprite1 = val.WaitForCompletion(); Addressables.Release<Sprite>(val); AsyncOperationHandle<Sprite> val2 = Addressables.LoadAssetAsync<Sprite>((object)"Assets/Textures/UI/Controls/Round_BorderLarge.png"); UIManager.menuSprite2 = val2.WaitForCompletion(); Addressables.Release<Sprite>(val2); AsyncOperationHandle<TMP_FontAsset> val3 = Addressables.LoadAssetAsync<TMP_FontAsset>((object)"Assets/Fonts/Terminal/fs-tahoma-8px-v2 SDF.asset"); UIManager.fontSecondary = val3.WaitForCompletion(); Addressables.Release<TMP_FontAsset>(val3); } public void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) if (SceneHelper.CurrentScene == "Intro" || SceneHelper.CurrentScene == "Bootstrap" || SceneHelper.CurrentScene == null) { return; } if ((Object)(object)obj == (Object)null) { obj = new GameObject { name = "Archipelago" }; Object.DontDestroyOnLoad((Object)(object)obj); obj.transform.localPosition = new Vector3(960f, 540f, 0f); uim = obj.AddComponent<UIManager>(); mw = obj.AddComponent<Multiworld>(); } ((MonoBehaviour)uim).StopCoroutine("DisplayMessage"); UIManager.displayingMessage = false; UIManager.levels.Clear(); UIManager.secrets.Clear(); UIManager.createdSkullIcons = false; UIManager.createdSwitchIcons = false; uim.deathLinkMessage = null; Multiworld.DeathLinkManager?.RemoveQueuedDeathLink(); LevelManager.skulls.Clear(); ConfigManager.connectionInfo.text = ""; if (ConfigManager.uiColorRandomizer.value == ColorOptions.EveryLoad) { ColorRandomizer.RandomizeUIColors(); } if (ConfigManager.gunColorRandomizer.value == ColorOptions.EveryLoad) { ColorRandomizer.RandomizeGunColors(); } if (SceneHelper.CurrentScene == "Main Menu") { bool flag = DataExists(); UIManager.FindMenuObjects(); mw.SetupServerCheckBlocker(); if (flag && GameProgressSaver.GetTutorial() && !firstTimeLoad) { LoadData(); ConfigManager.LoadConnectionInfo(); ConfigManager.LoadStats(); firstTimeLoad = true; } else if (!flag) { ConfigManager.ResetStatsDefaults(); } UIManager.CreateMenuUI(); if (flag && Multiworld.Authenticated) { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Green; } else if (flag && !Multiworld.Authenticated) { ((Graphic)UIManager.menuIcon.GetComponent<Image>()).color = Colors.Red; } if ((Object)(object)UIManager.log == (Object)null) { uim.CreateLogObject(); } if (flag && data.randomizeSkulls) { UIManager.CreateMenuSkullIcons(); } if (flag && (data.l1switch || data.l7switch)) { UIManager.CreateMenuSwitchIcons(); } if (data.completedLevels.Count >= data.goalRequirement) { if (data.goal.Contains("-S")) { GameProgressSaver.FoundSecretMission(int.Parse(data.goal.Substring(0, 1))); } else if (!data.unlockedLevels.Contains(data.goal)) { data.unlockedLevels.Add(data.goal); } } } else if (IsInLevel && DataExists()) { UIManager.CreateMessageUI(); } else if (SceneHelper.CurrentScene == "Endless" && Multiworld.HintMode) { UIManager.CreateMessageUI(); } if (!IsInIntro) { ((Component)MonoSingleton<OptionsManager>.Instance.optionsMenu).gameObject.AddComponent<OptionsMenuState>(); } if (DataExists() && (Object)(object)UIManager.log != (Object)null) { UIManager.AdjustLogBounds(); } if (DataExists() && SceneHelper.CurrentScene == "Level 0-1") { LevelManager.ChangeIntro(); } else if (DataExists() && SceneHelper.CurrentScene == "Level 1-2" && GameProgressSaver.GetGeneralProgress().nai0 == 0) { LevelManager.DeactivateNailgun(); } else if (DataExists() && (SceneHelper.CurrentScene == "Level 1-4" || SceneHelper.CurrentScene == "Level 5-3") && data.hankRewards) { LevelManager.FindHank(); } else if (DataExists() && SceneHelper.CurrentScene == "CreditsMuseum2") { LevelManager.FindRocketRaceButton(); } } public static bool DataExists() { return File.Exists(Path.Combine(GameProgressSaver.BaseSavePath, $"Slot{GameProgressSaver.currentSlot + 1}") + "\\archipelago.json"); } public static bool DataExists(int slotId) { return File.Exists(Path.Combine(GameProgressSaver.BaseSavePath, $"Slot{slotId}") + "\\archipelago.json"); } public static void SaveData() { string path = Path.Combine(GameProgressSaver.BaseSavePath, $"Slot{GameProgressSaver.currentSlot + 1}") + "\\archipelago.json"; byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject((object)data)); File.WriteAllBytes(path, bytes); } public static void LoadData() { string path = Path.Combine(GameProgressSaver.BaseSavePath, $"Slot{GameProgressSaver.currentSlot + 1}") + "\\archipelago.json"; if (File.Exists(path)) { using (StreamReader streamReader = new StreamReader(path)) { data = JsonConvert.DeserializeObject<Data>(streamReader.ReadToEnd()); } Logger.LogInfo((object)("Loaded Archipelago data for slot " + (GameProgressSaver.currentSlot + 1) + ".")); LocationManager.RegenerateItemDefinitions(); } else { Logger.LogError((object)("Archipelago data for slot " + (GameProgressSaver.currentSlot + 1) + " does not exist.")); } } public static void DeleteData(int slot) { string path = Path.Combine(GameProgressSaver.BaseSavePath, $"Slot{slot + 1}") + "\\archipelago.json"; if (File.Exists(path)) { File.Delete(path); } } public static void LockAllWeapons() { GameProgressMoneyAndGear obj = (LocationManager.generalProgress = GameProgressSaver.GetGeneralProgress()); obj.rev0 = 0; obj.rev1 = 0; obj.rev2 = 0; obj.sho0 = 0; obj.sho1 = 0; obj.sho2 = 0; obj.nai0 = 0; obj.nai1 = 0; obj.nai2 = 0; obj.rock0 = 0; obj.rock1 = 0; obj.rock2 = 0; SaveGeneralProgress(obj); } public static void SaveGeneralProgress(GameProgressMoneyAndGear progress) { Traverse val = Traverse.Create(typeof(GameProgressSaver)); val.Method("WriteFile", new object[2] { val.Property<string>("generalProgressPath", (object[])null).Value, progress }).GetValue(); } public static bool IsFire2Unlocked(string weapon) { if (data.randomizeFire2 == Fire2Options.Disabled) { return true; } return data.unlockedFire2.Contains(weapon); } public static bool CanBreakGlass() { GameProgressMoneyAndGear generalProgress = GameProgressSaver.GetGeneralProgress(); if (generalProgress.rev0 > 0) { if (data.revForm == WeaponForm.Standard && IsFire2Unlocked("rev0")) { return true; } if (data.revForm == WeaponForm.Alternate) { return true; } } if (generalProgress.rev1 > 0) { if (data.revForm == WeaponForm.Standard && IsFire2Unlocked("rev1")) { return true; } if (data.revForm == WeaponForm.Alternate) { return true; } } if (generalProgress.rev2 > 0) { if (data.revForm == WeaponForm.Standard && IsFire2Unlocked("rev2")) { return true; } if (data.revForm == WeaponForm.Alternate) { return true; } } if (generalProgress.sho0 > 0) { if (data.shoForm == WeaponForm.Standard && IsFire2Unlocked("sho0")) { return true; } if (data.shoForm == WeaponForm.Alternate) { return true; } } if (generalProgress.sho1 > 0) { if (data.shoForm == WeaponForm.Standard && IsFire2Unlocked("sho1")) { return true; } if (data.shoForm == WeaponForm.Alternate) { return true; } } if (generalProgress.sho2 > 0 && data.shoForm == WeaponForm.Alternate) { return true; } if (generalProgress.rai0 > 0) { return true; } if (generalProgress.rai2 > 0) { return true; } if (generalProgress.rock0 > 0) { return true; } if (generalProgress.rock1 > 0) { return true; } if (generalProgress.rock2 > 0) { return true; } if (generalProgress.arm1 > 0) { return true; } return false; } public static List<string> SearchAssetKeys(string contains) { List<string> list = new List<string>(); foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators) { if (!(resourceLocator is ResourceLocationMap)) { continue; } foreach (string key in resourceLocator.Keys) { if (key.Contains(contains)) { list.Add(key); } } } return list; } public static List<T> FindAllComponentsInCurrentScene<T>() where T : Behaviour { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) List<T> list = new List<T>(); T[] array = Resources.FindObjectsOfTypeAll<T>(); foreach (T val in array) { Scene val2 = ((Component)(object)val).gameObject.scene; string name = ((Scene)(ref val2)).name; val2 = SceneManager.GetActiveScene(); if (name == ((Scene)(ref val2)).name) { list.Add(val); } } return list; } public static void ValidateArms() { bool flag = false; bool flag2 = GameProgressSaver.CheckGear("arm1") == 1; if (flag2 && !data.hasArm && MonoSingleton<PrefsManager>.Instance.GetInt("weapon.arm0", 0) == 1) { MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm0", 0); flag = true; } if (MonoSingleton<PrefsManager>.Instance.GetInt("weapon.arm0", 0) == 0 && MonoSingleton<PrefsManager>.Instance.GetInt("weapon.arm1", 0) == 0) { if (flag2) { MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm1", 1); } else { MonoSingleton<PrefsManager>.Instance.SetInt("weapon.arm0", 1); } flag = true; } if (flag) { MonoSingleton<FistControl>.Instance.ResetFists(); } } [IteratorStateMachine(typeof(<ApplyLoadout>d__65))] public IEnumerator ApplyLoadout(WeaponLoadout loadout) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ApplyLoadout>d__65(0) { loadout = loadout }; } } public class Data { public string seed = string.Empty; public string version = string.Empty; public string serverVersion = string.Empty; public long index; public string host_name; public string slot_name; public string password; public HashSet<string> @checked = new HashSet<string>(); public int playerCount = 1; public List<RecentLocation> recentLocations = new List<RecentLocation>(); public HashSet<string> unlockedLevels = new HashSet<string>(); public HashSet<string> unlockedSecrets = new HashSet<string>(); public HashSet<string> completedLevels = new HashSet<string>(); public HashSet<string> purchasedItems = new HashSet<string>(); public string start = "0-1"; public string goal = "6-2"; public int goalRequirement = 20; public bool perfectGoal; public EnemyOptions enemyRewards; public bool challengeRewards; public bool pRankRewards; public bool hankRewards; public bool clashReward; public bool fishRewards; public bool cleanRewards; public bool chessReward; public bool rocketReward; public bool hasArm = true; public int dashes = 3; public int walljumps = 3; public bool canSlide = true; public bool canSlam = true; public int multiplier = 1; public WeaponForm revForm; public bool revstd = true; public bool revalt; public WeaponForm shoForm; public bool shostd = true; public bool shoalt; public WeaponForm naiForm; public bool naistd = true; public bool naialt; public Fire2Options randomizeFire2; public HashSet<string> unlockedFire2 = new HashSet<string>(); public bool randomizeSkulls; public HashSet<string> unlockedSkulls = new HashSet<string>(); public int unlockedSkulls1_4; public int unlockedSkulls5_1; public bool l1switch; public bool l7switch; public bool[] limboSwitches = new bool[4]; public bool[] shotgunSwitches = new bool[3]; public bool musicRandomizer; public Dictionary<string, string> music = new Dictionary<string, string>(); public bool cybergrindHints = true; public bool deathLink; public override string ToString() { if (!Utility.IsNullOrWhiteSpace(slot_name)) { if (@checked.Count != 1) { return $"Slot {GameProgressSaver.currentSlot + 1} | {slot_name} | {@checked.Count} locations checked."; } return $"Slot {GameProgressSaver.currentSlot + 1} | {slot_name} | {@checked.Count} location checked."; } return "No data for current slot."; } } public static class LevelManager { public static Dictionary<string, GameObject> skulls = new Dictionary<string, GameObject>(); public static Door redDoor; public static void FindSkulls() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0038: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 //IL_00e3: Unknown result type (might be due to invalid IL o