The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of PEAKPELAGO v0.4.8
plugins/PeakArchipelagoPluginDLL/Archipelago.MultiClient.Net.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Authentication; using System.Text; using System.Text.RegularExpressions; using System.Threading; 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; using WebSocketSharp; [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: 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: 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; } 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 volatile bool awaitingRoomInfo; private volatile bool expectingLoginResult; private LoginResult loginResult; 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) { awaitingRoomInfo = false; } } else if (expectingLoginResult) { expectingLoginResult = false; loginResult = LoginResult.FromPacket(packet); } } public LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true) { connectionInfo.SetConnectionParameters(game, tags, itemsHandlingFlags, uuid); try { awaitingRoomInfo = true; expectingLoginResult = true; loginResult = null; Socket.Connect(); DateTime utcNow = DateTime.UtcNow; while (awaitingRoomInfo) { if (DateTime.UtcNow - utcNow > TimeSpan.FromSeconds(4.0)) { Socket.Disconnect(); return new LoginFailure("Connection timed out."); } Thread.Sleep(25); } Socket.SendPacket(BuildConnectPacket(name, password, version, requestSlotData)); utcNow = DateTime.UtcNow; while (expectingLoginResult) { if (DateTime.UtcNow - utcNow > TimeSpan.FromSeconds(4.0)) { Socket.Disconnect(); return new LoginFailure("Connection timed out."); } Thread.Sleep(25); } Thread.Sleep(50); return loginResult; } catch (ArchipelagoSocketClosedException) { return new LoginFailure("Socket closed unexpectedly."); } } 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 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 void GetAsync<T>(Action<T> callback) { GetAsync(delegate(JToken t) { callback(t.ToObject<T>()); }); } public void GetAsync(Action<JToken> callback) { Context.GetAsync(Context.Key, callback); } 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((object?)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 (object)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 Action<string, Action<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 = ((object)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 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 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 Or(long i) { return new OperationSpecification { OperationType = OperationType.Or, Value = JToken.op_Implicit(i) }; } public static OperationSpecification And(long i) { return new OperationSpecification { OperationType = OperationType.And, Value = JToken.op_Implicit(i) }; } 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 : IArchipelagoSocketHelper { private const SslProtocols Tls13 = SslProtocols.Tls13; private const SslProtocols Tls12 = SslProtocols.Tls12; private static readonly ArchipelagoPacketConverter Converter = new ArchipelagoPacketConverter(); internal WebSocket webSocket; public Uri Uri { get; } public bool Connected { get { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (webSocket != null) { if ((int)webSocket.ReadyState != 1) { return (int)webSocket.ReadyState == 2; } return true; } return false; } } public event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived; public event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent; public event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived; public event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed; public event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened; internal ArchipelagoSocketHelper(Uri hostUrl) { Uri = hostUrl; } private WebSocket CreateWebSocket(Uri uri) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown WebSocket val = new WebSocket(uri.ToString(), new string[0]); if (val.IsSecure) { val.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; } val.OnMessage += OnMessageReceived; val.OnError += OnError; val.OnClose += OnClose; val.OnOpen += OnOpen; return val; } public void Connect() { ConnectToProvidedUri(Uri); } private void ConnectToProvidedUri(Uri uri) { if (uri.Scheme != "unspecified") { try { webSocket = CreateWebSocket(uri); webSocket.Connect(); return; } catch (Exception e) { OnError(e); return; } } List<Exception> list = new List<Exception>(); try { try { ConnectToProvidedUri(uri.AsWss()); } catch (Exception item) { list.Add(item); throw; } if (webSocket.IsAlive) { return; } try { ConnectToProvidedUri(uri.AsWs()); } catch (Exception item2) { list.Add(item2); throw; } } catch { try { ConnectToProvidedUri(uri.AsWs()); } catch (Exception item3) { list.Add(item3); OnError(new Archipelago.MultiClient.Net.Exceptions.AggregateException(list)); } } } public void Disconnect() { if (webSocket != null && webSocket.IsAlive) { webSocket.Close(); } } public void DisconnectAsync() { if (webSocket != null && webSocket.IsAlive) { webSocket.CloseAsync(); } } public void SendPacket(ArchipelagoPacketBase packet) { SendMultiplePackets(packet); } public void SendMultiplePackets(List<ArchipelagoPacketBase> packets) { SendMultiplePackets(packets.ToArray()); } public void SendMultiplePackets(params ArchipelagoPacketBase[] packets) { if (webSocket != null && webSocket.IsAlive) { string text = JsonConvert.SerializeObject((object)packets); webSocket.Send(text); if (this.PacketsSent != null) { this.PacketsSent(packets); } return; } throw new ArchipelagoSocketClosedException(); } public void SendPacketAsync(ArchipelagoPacketBase packet, Action<bool> onComplete = null) { SendMultiplePacketsAsync(new List<ArchipelagoPacketBase> { packet }, onComplete); } public void SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets, Action<bool> onComplete = null) { SendMultiplePacketsAsync(onComplete, packets.ToArray()); } public void SendMultiplePacketsAsync(Action<bool> onComplete = null, params ArchipelagoPacketBase[] packets) { if (webSocket.IsAlive) { string text = JsonConvert.SerializeObject((object)packets); webSocket.SendAsync(text, onComplete); if (this.PacketsSent != null) { this.PacketsSent(packets); } return; } throw new ArchipelagoSocketClosedException(); } private void OnOpen(object sender, EventArgs e) { if (this.SocketOpened != null) { this.SocketOpened(); } } private void OnClose(object sender, CloseEventArgs e) { if ((!(Uri.Scheme == "unspecified") || sender != webSocket || !(webSocket.Url.Scheme == "wss")) && this.SocketClosed != null) { this.SocketClosed(e.Reason); } } private void OnMessageReceived(object sender, MessageEventArgs e) { if (!e.IsText || this.PacketReceived == null) { return; } List<ArchipelagoPacketBase> list = null; try { list = JsonConvert.DeserializeObject<List<ArchipelagoPacketBase>>(e.Data, (JsonConverter[])(object)new JsonConverter[1] { Converter }); } catch (Exception e2) { OnError(e2); } if (list == null) { return; } foreach (ArchipelagoPacketBase item in list) { this.PacketReceived(item); } } private void OnError(object sender, ErrorEventArgs e) { if (this.ErrorReceived != null) { this.ErrorReceived(e.Exception, e.Message); } } private void OnError(Exception e) { if (this.ErrorReceived != null) { this.ErrorReceived(e, e.Message); } } } 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, Action<JToken>> asyncRetrievalCallbacks = new Dictionary<string, Action<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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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 (asyncRetrievalCallbacks.TryGetValue(datum.Key, out var value3)) { value3(datum.Value); asyncRetrievalCallbacks.Remove(datum.Key); } } } private void GetAsync(string key, Action<JToken> callback) { if (!asyncRetrievalCallbacks.ContainsKey(key)) { asyncRetrievalCallbacks[key] = callback; } else { Dictionary<string, Action<JToken>> dictionary = asyncRetrievalCallbacks; dictionary[key] = (Action<JToken>)Delegate.Combine(dictionary[key], callback); } socket.SendPacketAsync(new GetPacket { Keys = new string[1] { key } }); } 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) { JToken value = null; GetAsync(key, delegate(JToken v) { value = v; }); int num = 0; while (value == null) { Thread.Sleep(10); if (++num > 200) { 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(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 value; } 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 void GetHintsAsync(Action<Hint[]> onHintsRetrieved, int? slot = null, int? team = null) { GetHintsElement(slot, team).GetAsync(delegate(JToken t) { onHintsRetrieved((t != null) ? t.ToObject<Hint[]>() : null); }); } 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(onHintsUpdated, slot, team); } } 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 void GetSlotDataAsync(Action<Dictionary<string, object>> onSlotDataRetrieved, int? slot = null) { GetSlotDataElement(slot).GetAsync(delegate(JToken t) { onSlotDataRetrieved((t != null) ? t.ToObject<Dictionary<string, object>>() : null); }); } public void GetSlotDataAsync<T>(Action<T> onSlotDataRetrieved, int? slot = null) where T : class { GetSlotDataElement(slot).GetAsync(delegate(JToken t) { onSlotDataRetrieved((t != null) ? t.ToObject<T>() : null); }); } public Dictionary<string, string[]> GetItemNameGroups(string game = null) { return GetItemNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public void GetItemNameGroupsAsync(Action<Dictionary<string, string[]>> onItemNameGroupsRetrieved, string game = null) { GetItemNameGroupsElement(game).GetAsync(delegate(JToken t) { onItemNameGroupsRetrieved((t != null) ? t.ToObject<Dictionary<string, string[]>>() : null); }); } public Dictionary<string, string[]> GetLocationNameGroups(string game = null) { return GetLocationNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public void GetLocationNameGroupsAsync(Action<Dictionary<string, string[]>> onLocationNameGroupsRetrieved, string game = null) { GetLocationNameGroupsElement(game).GetAsync(delegate(JToken t) { onLocationNameGroupsRetrieved((t != null) ? t.ToObject<Dictionary<string, string[]>>() : null); }); } public ArchipelagoClientState GetClientStatus(int? slot = null, int? team = null) { return GetClientStatusElement(slot, team).To<ArchipelagoClientState?>().GetValueOrDefault(); } public void GetClientStatusAsync(Action<ArchipelagoClientState> onStatusRetrieved, int? slot = null, int? team = null) { GetClientStatusElement(slot, team).GetAsync(delegate(JToken t) { onStatusRetrieved(t.ToObject<ArchipelagoClientState?>().GetValueOrDefault()); }); } public void TrackClientStatus(Action<ArchipelagoClientState> onStatusUpdated, bool retrieveCurrentClientStatus = true, int? slot = null, int? team = null) { GetClientStatusElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onStatusUpdated(newValue.ToObject<ArchipelagoClientState>()); }; if (retrieveCurrentClientStatus) { GetClientStatusAsync(onStatusUpdated, slot, team); } } public bool GetRaceMode() { return GetRaceModeElement().To<int?>().GetValueOrDefault() > 0; } public void GetRaceModeAsync(Action<bool> onRaceModeRetrieved) { GetRaceModeElement().GetAsync(delegate(JToken t) { onRaceModeRetrieved(t.ToObject<int?>().GetValueOrDefault() > 0); }); } } public interface IDataStorageWrapper { Hint[] GetHints(int? slot = null, int? team = null); void GetHintsAsync(Action<Hint[]> onHintsRetrieved, int? slot = null, int? team = null); void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null); Dictionary<string, object> GetSlotData(int? slot = null); T GetSlotData<T>(int? slot = null) where T : class; void GetSlotDataAsync(Action<Dictionary<string, object>> onSlotDataRetrieved, int? slot = null); void GetSlotDataAsync<T>(Action<T> onSlotDataRetrieved, int? slot = null) where T : class; Dictionary<string, string[]> GetItemNameGroups(string game = null); void GetItemNameGroupsAsync(Action<Dictionary<string, string[]>> onItemNameGroupsRetrieved, string game = null); Dictionary<string, string[]> GetLocationNameGroups(string game = null); void GetLocationNameGroupsAsync(Action<Dictionary<string, string[]>> onLocationNameGroupsRetrieved, string game = null); ArchipelagoClientState GetClientStatus(int? slot = null, int? team = null); void GetClientStatusAsync(Action<ArchipelagoClientState> onStatusRetrieved, int? slot = null, int? team = null); void TrackClientStatus(Action<ArchipelagoClientState> onStatusUpdated, bool retrieveCurrentClientStatus = true, int? slot = null, int? team = null); bool GetRaceMode(); void GetRaceModeAsync(Action<bool> onRaceModeRetrieved); } public interface IHintsHelper { void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] locationIds); void CreateHints(HintStatus hintStatus = HintStatus.Unspecified, params long[] locationIds); void UpdateHintStatus(int player, long locationId, HintStatus newHintStatus); Hint[] GetHints(int? slot = null, int? team = null); void GetHintsAsync(Action<Hint[]> onHintsRetrieved, int? slot = null, int? team = null); void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null); } public class HintsHelper : IHintsHelper { private readonly IArchipelagoSocketHelper socket; private readonly ILocationCheckHelper locationCheckHelper; private readonly IRoomStateHelper roomStateHelper; private readonly IPlayerHelper players; private readonly IDataStorageHelper dataStorageHelper; internal HintsHelper(IArchipelagoSocketHelper socket, IPlayerHelper players, ILocationCheckHelper locationCheckHelper, IRoomStateHelper roomStateHelper, IDataStorageHelper dataStorageHelper) { this.socket = socket; this.players = players; this.locationCheckHelper = locationCheckHelper; this.roomStateHelper = roomStateHelper; this.dataStorageHelper = dataStorageHelper; } public void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] locationIds) { if (roomStateHelper.Version < new Version(0, 6, 2)) { locationCheckHelper.ScoutLocationsAsync(null, createAsHint: true, locationIds); return; } socket.SendPacket(new CreateHintsPacket { Locations = locationIds, Player = player, Status = hintStatus }); } public void CreateHints(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) { int slot = players.ActivePlayer.Slot; CreateHints(slot, hintStatus, ids); } public void UpdateHintStatus(int player, long locationId, HintStatus newHintStatus) { socket.SendPacket(new UpdateHintPacket { Location = locationId, Player = player, Status = newHintStatus }); } public Hint[] GetHints(int? slot = null, int? team = null) { return dataStorageHelper.GetHints(slot, team); } public void GetHintsAsync(Action<Hint[]> onHintsRetrieved, int? slot = null, int? team = null) { dataStorageHelper.GetHintsAsync(onHintsRetrieved, slot, team); } public void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null) { dataStorageHelper.TrackHints(onHintsUpdated, retrieveCurrentlyUnlockedHints, slot, team); } } public class ArchipelagoSocketHelperDelagates { public delegate void PacketReceivedHandler(ArchipelagoPacketBase packet); public delegate void PacketsSentHandler(ArchipelagoPacketBase[] packets); public delegate void ErrorReceivedHandler(Exception e, string message); public delegate void SocketClosedHandler(string reason); public delegate void SocketOpenedHandler(); } public interface IArchipelagoSocketHelper { Uri Uri { get; } bool Connected { get; } event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived; event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent; event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived; event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed; event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened; void SendPacket(ArchipelagoPacketBase packet); void SendMultiplePackets(List<ArchipelagoPacketBase> packets); void SendMultiplePackets(params ArchipelagoPacketBase[] packets); void Connect(); void Disconnect(); void SendPacketAsync(ArchipelagoPacketBase packet, Action<bool> onComplete = null); void SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets, Action<bool> onComplete = null); void SendMultiplePacketsAsync(Action<bool> onComplete = null, params ArchipelagoPacketBase[] packets); } public interface ILocationCheckHelper { ReadOnlyCollection<long> AllLocations { get; } ReadOnlyCollection<long> AllLocationsChecked { get; } ReadOnlyCollection<long> AllMissingLocations { get; } event LocationCheckHelper.CheckedLocationsUpdatedHandler CheckedLocationsUpdated; void CompleteLocationChecks(params long[] ids); void CompleteLocationChecksAsync(Action<bool> onComplete, params long[] ids); void ScoutLocationsAsync(Action<Dictionary<long, ScoutedItemInfo>> callback = null, HintCreationPolicy hintCreationPolicy = HintCreationPolicy.None, params long[] ids); void ScoutLocationsAsync(Action<Dictionary<long, ScoutedItemInfo>> callback = null, bool createAsHint = false, params long[] ids); void ScoutLocationsAsync(Action<Dictionary<long, ScoutedItemInfo>> callback = null, params long[] ids); long GetLocationIdFromName(string game, string locationName); string GetLocationNameFromId(long locationId, string game = null); } public class LocationCheckHelper : ILocationCheckHelper { public delegate void CheckedLocationsUpdatedHandler(ReadOnlyCollection<long> newCheckedLocations); private readonly IConcurrentHashSet<long> allLocations = new ConcurrentHashSet<long>(); private readonly IConcurrentHashSet<long> locationsChecked = new ConcurrentHashSet<long>(); private readonly IConcurrentHashSet<long> serverConfirmedChecks = new ConcurrentHashSet<long>(); private ReadOnlyCollection<long> missingLocations = new ReadOnlyCollection<long>(new long[0]); private readonly IArchipelagoSocketHelper socket; private readonly IItemInfoResolver itemInfoResolver; private readonly IConnectionInfoProvider connectionInfoProvider; private readonly IPlayerHelper players; private bool awaitingLocationInfoPacket; private Action<LocationInfoPacket> locationInfoPacketCallback; public ReadOnlyCollection<long> AllLocations => allLocations.AsToReadOnlyCollection(); public ReadOnlyCollection<long> AllLocationsChecked => locationsChecked.AsToReadOnlyCollection(); public ReadOnlyCollection<long> AllMissingLocations => missingLocations; public event CheckedLocationsUpdatedHandler CheckedLocationsUpdated; internal LocationCheckHelper(IArchipelagoSocketHelper socket, IItemInfoResolver itemInfoResolver, IConnectionInfoProvider connectionInfoProvider, IPlayerHelper players) { this.socket = socket; this.itemInfoResolver = itemInfoResolver; this.connectionInfoProvider = connectionInfoProvider; this.players = players; socket.PacketReceived += Socket_PacketReceived; } private void Socket_PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket))
plugins/PeakArchipelagoPluginDLL/Newtonsoft.Json.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
#define DEBUG using System; 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.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Xml; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: CLSCompliant(true)] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("11.0.1")] [assembly: AssemblyInformationalVersion("11.0.1-beta2+bdfeb80d3eb277241ce8f051a360c9461b33afc5")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET 3.5")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("11.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = num & _mask; Entry[] entries = _entries; for (Entry entry = entries[num3]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; _mask = num; } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { return value ? True : False; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { return (!nullable) ? "0.0" : Null; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (text.IndexOf('.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringBuilder sb = new StringBuilder(256); StringWriter stringWriter = new StringWriter(sb, CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if ((object)converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization = MemberSerialization.OptOut; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { return type == JsonContainerType.Array || type == JsonContainerType.Constructor; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int value2) { return value2; } int num; try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array3 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array2 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double value2) { return value2; } double num = Convert.ToDouble(value, CultureInfo.InvariantCulture); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = Convert.ToBoolean(Value, CultureInfo.InvariantCulture); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal value2) { return value2; } decimal num; try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { return Read() && MoveToContent(); } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { JsonSerializerSettings settings = JsonConvert.DefaultSettings?.Invoke(); return Create(settings); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); JsonSerializerInternalReader jsonSerializerInternalReader = new JsonSerializerInternalReader(this); jsonSerializerInternalReader.Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); JsonSerializerInternalReader jsonSerializerInternalReader = new JsonSerializerInternalReader(this); object result = jsonSerializerInternalReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); JsonSerializerInternalWriter jsonSerializerInternalWriter = new JsonSerializerInternalWriter(this); jsonSerializerInternalWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType) { ValidationUtils.ArgumentNotNull(objectType, "objectType"); if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } public class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling.GetValueOrDefault(); } set { _metadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling; } set { TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling.GetValueOrDefault(); } set { _typeNameAssemblyFormatHandling = value; } } public ConstructorHandling ConstructorHandling { get { return _constructorHandling.GetValueOrDefault(); } set { _constructorHandling = value; } } public IContractResolver? ContractResolver { get; set; } public IEqualityComparer? EqualityComparer { get; set; } [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] public IReferenceResolver? ReferenceResolver { get { return ReferenceResolverProvider?.Invoke(); } set { IReferenceResolver value2 = value; ReferenceResolverProvider = ((value2 != null) ? ((Func<IReferenceResolver>)(() => value2)) : null); } } public Func<IReferenceResolver?>? ReferenceResolverProvider { get; set; } public ITraceWriter? TraceWriter { get; set; } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public SerializationBinder? Binder { get { if (SerializationBinder == null) { return null; } if (SerializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { SerializationBinder = ((value == null) ? null : new SerializationBinderAdapter(value)); } } public ISerializationBinder? SerializationBinder { get; set; } public EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error { get; set; } public StreamingContext Context { get { return _context ?? DefaultContext; } set { _context = value; } } public string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public int? MaxDepth { get { return _maxDepthSet ? _maxDepth : new int?(64); } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public CultureInfo Culture { get { return _culture ?? DefaultCulture; } set { _culture = value; } } public bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } static JsonSerializerSettings() { DefaultContext = default(StreamingContext); DefaultCulture = CultureInfo.InvariantCulture; } [DebuggerStepThrough] public JsonSerializerSettings() { Converters = new List<JsonConverter>(); } } internal enum ReadType { Read, ReadAsInt32, ReadAsInt64, ReadAsBytes, ReadAsString, ReadAsDecimal, ReadAsDateTime, ReadAsDateTimeOffset, ReadAsDouble, ReadAsBoolean } public class JsonTextReader : JsonReader, IJsonLineInfo { private const char UnicodeReplacementChar = '\ufffd'; private readonly TextReader _reader; private char[]? _chars; private int _charsUsed; private int _charPos; private int _lineStartPos; private int _lineNumber; private bool _isEndOfFile; private StringBuffer _stringBuffer; private StringReference _stringReference; private IArrayPool<char>? _arrayPool; internal int LargeBufferLength { get; set; } = 1073741823; internal char[]? CharBuffer { get { return _chars; } set { _chars = value; } } internal int CharPos => _charPos; public JsonNameTable? PropertyNameTable { get; set; } public IArrayPool<char>? ArrayPool { get { return _arrayPool; } set { if (value == null) { throw new ArgumentNullException("value"); } _arrayPool = value; } } public int LineNumber { get { if (base.CurrentState == State.Start && LinePosition == 0 && TokenType != JsonToken.Comment) { return 0; } return _lineNumber; } } public int LinePosition => _charPos - _lineStartPos; public JsonTextReader(TextReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } _reader = reader; _lineNumber = 1; } private void EnsureBufferNotEmpty() { if (_stringBuffer.IsEmpty) { _stringBuffer = new StringBuffer(_arrayPool, 1024); } } private void SetNewLine(bool hasNextChar) { MiscellaneousUtils.Assert(_chars != null); if (hasNextChar && _chars[_charPos] == '\n') { _charPos++; } OnNewLine(_charPos); } private void OnNewLine(int pos) { _lineNumber++; _lineStartPos = pos; } private void ParseString(char quote, ReadType readType) { _charPos++; ShiftBufferIfNeeded(); ReadStringIntoBuffer(quote); ParseReadString(quote, readType); } private void ParseReadString(char quote, ReadType readType) { SetPostValueState(updateIndex: true); switch (readType) { case ReadType.ReadAsBytes: { Guid g; byte[] value2 = ((_stringReference.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((_stringReference.Length != 36 || !ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g)) ? Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) : g.ToByteArray())); SetToken(JsonToken.Bytes, value2, updateIndex: false); return; } case ReadType.ReadAsString: { string value = _stringReference.ToString(); SetToken(JsonToken.String, value, updateIndex: false); _quoteChar = quote; return; } case ReadType.ReadAsInt32: case ReadType.ReadAsDecimal: case ReadType.ReadAsBoolean: return; } if (_dateParseHandling != 0) { DateTimeOffset dt2; if (readType switch { ReadType.ReadAsDateTime => 1, ReadType.ReadAsDateTimeOffset => 2, _ => (int)_dateParseHandling, } == 1) { if (DateTimeUtils.TryParseDateTime(_stringReference, base.DateTimeZoneHandling, base.DateFormatString, base.Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return; } } else if (DateTimeUtils.TryParseDateTimeOffset(_stringReference, base.DateFormatString, base.Culture, out dt2)) { SetToken(JsonToken.Date, dt2, updateIndex: false); return; } } SetToken(JsonToken.String, _stringReference.ToString(), updateIndex: false); _quoteChar = quote; } private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count) { Buffer.BlockCopy(src, srcOffset * 2, dst, dstOffset *
plugins/PeakArchipelagoPluginDLL/PeakArchipelago.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; 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.MessageLog.Messages; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Linq; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("PeakArchipelago")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Archipelago integration for PEAK")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c8126b715ac71c62860b6ac03e9fc6a78e33a496")] [assembly: AssemblyProduct("PeakArchipelago")] [assembly: AssemblyTitle("PeakArchipelago")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Peak.AP { public class HardRingLinkService { private static class HardRingLinkPatches { [HarmonyPatch(typeof(MountainProgressHandler), "CheckAreaAchievement")] public static class MountainProgressPeakReachedPatch { private static void Postfix(ProgressPoint pointReached) { try { if (_instance == null || !_instance._isEnabled) { return; } string text = "Unknown"; if (pointReached != null) { FieldInfo field = ((object)pointReached).GetType().GetField("title"); if (field != null) { text = ((string)field.GetValue(pointReached)) ?? "Unknown"; } } _instance._log.LogInfo((object)("[PeakPelago] Player reached peak: " + text)); int num = 0; if (text.ToUpper() == "PEAK") { num = 200; _instance._log.LogInfo((object)$"[PeakPelago] Final PEAK reached, sending +{num} rings via Hard Ring Link"); } else if (!string.IsNullOrEmpty(text) && text.ToUpper() != "UNKNOWN") { num = 100; _instance._log.LogInfo((object)$"[PeakPelago] Peak '{text}' reached, sending +{num} rings via Hard Ring Link"); } if (num > 0) { _instance.SendHardRingLink(num); } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] MountainProgressPeakReachedPatch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Character), "RPCA_Die")] public static class CharacterDeathPatch { private static void Postfix(Character __instance) { try { if (_instance != null && _instance._isEnabled) { if ((Object)(object)PeakArchipelagoPlugin._instance != (Object)null && PeakArchipelagoPlugin._instance._isDyingFromDeathLink) { _instance._log.LogDebug((object)"[PeakPelago] Death was from DeathLink, not sending Hard Ring Link"); return; } string text = __instance.characterName ?? "Unknown"; _instance._log.LogInfo((object)("[PeakPelago] Character died: " + text + ", sending -75 rings via Hard Ring Link")); _instance.SendHardRingLink(-75); } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] CharacterDeathPatch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Character), "FinishZombifying")] public static class CharacterZombifyPatch { private static void Postfix(Character __instance) { try { if (_instance != null && _instance._isEnabled) { if ((Object)(object)PeakArchipelagoPlugin._instance != (Object)null && PeakArchipelagoPlugin._instance._isDyingFromDeathLink) { _instance._log.LogDebug((object)"[PeakPelago] Zombification was from DeathLink, not sending Hard Ring Link"); return; } string text = __instance.characterName ?? "Unknown"; _instance._log.LogInfo((object)("[PeakPelago] Character zombified: " + text + ", sending -75 rings via Hard Ring Link")); _instance.SendHardRingLink(-75); } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] CharacterZombifyPatch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Scoutmaster), "SetCurrentTarget")] public static class ScoutmasterSetTargetPatch { [HarmonyPatch(typeof(Scoutmaster), "OnDisable")] public static class ScoutmasterOnDisablePatch { private static void Postfix() { _hasSpawnedThisSession = false; } } private static bool _hasSpawnedThisSession; private static void Postfix(Scoutmaster __instance, Character setCurrentTarget) { try { if (_instance != null && _instance._isEnabled && (Object)(object)setCurrentTarget != (Object)null && !_hasSpawnedThisSession) { _hasSpawnedThisSession = true; _instance._log.LogInfo((object)("[PeakPelago] Scoutmaster spawned/activated (targeting " + setCurrentTarget.characterName + "), sending -45 rings via Hard Ring Link")); _instance.SendHardRingLink(-45); } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] ScoutmasterSetTargetPatch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(ItemCooking), "Wreck")] public static class ItemCookingWreckPatch { private static void Postfix(ItemCooking __instance) { try { if (_instance != null && _instance._isEnabled && (Object)(object)((ItemComponent)__instance).item != (Object)null && (Object)(object)((ItemComponent)__instance).item.holderCharacter != (Object)null) { string text = ((Object)((ItemComponent)__instance).item).name ?? "Unknown"; string text2 = ((ItemComponent)__instance).item.holderCharacter.characterName ?? "Unknown"; _instance._log.LogInfo((object)("[PeakPelago] Item wrecked from cooking: " + text + " (held by " + text2 + "), sending -15 rings via Hard Ring Link")); _instance.SendHardRingLink(-15); } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] ItemCookingWreckPatch error: " + ex.Message)); } } } } private static HardRingLinkService _instance; public static void SetInstance(HardRingLinkService instance) { _instance = instance; } } private readonly ManualLogSource _log; private ArchipelagoSession _session; private bool _isEnabled; private int _connectionId; private Harmony _harmony; private ArchipelagoNotificationManager _notifications; public HardRingLinkService(ManualLogSource log, ArchipelagoNotificationManager notifications) { _log = log; _connectionId = Random.Range(int.MinValue, int.MaxValue); _notifications = notifications; } public void Initialize(ArchipelagoSession session, bool enabled) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown _session = session; _isEnabled = enabled; if (_session != null && _isEnabled) { _session.Socket.PacketReceived += new PacketReceivedHandler(OnPacketReceived); _harmony = new Harmony("com.mickemoose.peak.ap.hardringlink"); _harmony.PatchAll(typeof(HardRingLinkPatches)); HardRingLinkPatches.SetInstance(this); _log.LogInfo((object)$"[PeakPelago] Hard Ring Link service initialized (Connection ID: {_connectionId})"); } } public void SetEnabled(bool enabled) { _isEnabled = enabled; _log.LogInfo((object)("[PeakPelago] Hard Ring Link " + (enabled ? "enabled" : "disabled"))); } public void SendHardRingLink(int amount) { //IL_006b: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (_session == null || !_isEnabled) { return; } try { Dictionary<string, JToken> data = new Dictionary<string, JToken> { { "time", JToken.FromObject((object)DateTimeOffset.UtcNow.ToUnixTimeSeconds()) }, { "source", JToken.FromObject((object)_connectionId) }, { "amount", JToken.FromObject((object)amount) } }; BouncePacket val = new BouncePacket { Tags = new List<string> { "HardRingLink" }, Data = data }; _session.Socket.SendPacket((ArchipelagoPacketBase)(object)val); string text = ((amount > 0) ? "positive" : "negative"); _log.LogInfo((object)$"[PeakPelago] Sent Hard Ring Link: {amount} rings ({text})"); if (text == "positive") { _notifications.ShowRingLinkNotification($"HardRingLink: Sent +{amount} ring(s)"); } else { _notifications.ShowRingLinkNotification($"HardRingLink: Sent -{amount} ring(s)"); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to send Ring Link: " + ex.Message)); } } private void OnPacketReceived(ArchipelagoPacketBase packet) { try { BouncePacket val = (BouncePacket)(object)((packet is BouncePacket) ? packet : null); if (val != null && val.Tags != null && val.Tags.Contains("HardRingLink") && _isEnabled) { HandleHardRingLinkReceived(val.Data); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error handling Ring Link packet: " + ex.Message)); } } private void HandleHardRingLinkReceived(Dictionary<string, JToken> data) { try { if (data.ContainsKey("source") && data["source"].ToObject<int>() == _connectionId) { _log.LogDebug((object)"[PeakPelago] Ignoring own Hard Ring Link"); } else if (data.ContainsKey("amount")) { int num = data["amount"].ToObject<int>(); string text = ((num > 0) ? "positive" : "negative"); _log.LogInfo((object)$"[PeakPelago] Hard Ring Link received: {num} rings ({text})"); if (text == "positive") { _notifications.ShowRingLinkNotification($"HardRingLink: +{num} ring(s)!"); } else { _notifications.ShowRingLinkNotification($"HardRingLink: -{num} ring(s)!"); } ApplyRingLinkEffect(num); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to handle Hard Ring Link: " + ex.Message)); } } private void ApplyRingLinkEffect(int amount) { try { if (Character.AllCharacters == null || Character.AllCharacters.Count == 0) { _log.LogWarning((object)"[PeakPelago] Cannot apply Hard Ring Link - no characters found"); return; } float num = (float)amount / 100f; List<Character> list = Character.AllCharacters.Where((Character c) => (Object)(object)c != (Object)null && ((Component)c).gameObject.activeInHierarchy && !c.data.dead).ToList(); foreach (Character item in list) { if (num > 0f) { CharacterData data = item.data; data.extraStamina += num; } else if (num < 0f) { float num2 = Mathf.Abs(num); if (item.data.extraStamina > 0f) { float num3 = Mathf.Min(item.data.extraStamina, num2); CharacterData data2 = item.data; data2.extraStamina -= num3; num2 -= num3; } if (num2 > 0f) { item.data.staminaDelta = Mathf.Max(0f, item.data.staminaDelta - num2); } } string arg = ((amount > 0) ? "added" : "deducted"); _log.LogInfo((object)$"[PeakPelago] Hard Ring Link {arg}: {Mathf.Abs(num)} stamina (from {amount} rings)"); } _log.LogInfo((object)$"[PeakPelago] Hard Ring Link applied to {list.Count} character(s)"); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to apply Hard Ring Link: " + ex.Message)); } } public void Cleanup() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (_session != null) { _session.Socket.PacketReceived -= new PacketReceivedHandler(OnPacketReceived); } if (_harmony != null) { _harmony.UnpatchSelf(); } HardRingLinkPatches.SetInstance(null); _session = null; _isEnabled = false; } } public class RingLinkService { private static class RingLinkPatches { [HarmonyPatch(typeof(Item), "Awake")] public static class ItemAwakePatch { private static void Postfix(Item __instance) { try { if (_instance == null || !_instance._isEnabled) { return; } __instance.OnConsumed = (Action)Delegate.Combine(__instance.OnConsumed, (Action)delegate { if (_instance != null && _instance._isEnabled && !((Object)(object)__instance.holderCharacter == (Object)null)) { int num = CalculateRingValue(__instance); if (num != 0) { string arg = ((num > 0) ? "positive" : "negative"); _instance._log.LogInfo((object)$"[PeakPelago] Item consumed: {((Object)__instance).name}, sending {num} rings ({arg})"); _instance.SendRingLink(num); } } }); } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] ItemAwake patch error: " + ex.Message)); } } } private static int CalculateRingValue(Item item) { string name = ((Object)item).name; if (HasPoisonEffects(item)) { float num = CalculatePoisonPenalty(item); if (num > 0f) { _instance._log.LogInfo((object)$"[PeakPelago] Item {name} is poisonous, penalty: {num}"); return -Mathf.RoundToInt(num * 100f); } } float num2 = 0f; if (name.Contains("Apple Berry")) { num2 += 0.1f; } if (name.Contains("Berrynana")) { num2 += 0.2f; } if (name.Contains("Clusterberry")) { num2 += 0.35f; } if (name.Contains("Kingberry")) { num2 += 0.15f; } if (name.Contains("Marshmallow")) { num2 += 0.5f; } if (name.Contains("Mushroom")) { num2 += 0.07f; } if (name.Contains("Sports Drink")) { num2 += 0.15f; } if (name.Contains("Energy Drink")) { num2 += 0.25f; } if (name.Contains("Winterberry") || name.Contains("Shroomberry")) { num2 += 0.35f; } if (name.Contains("Honeycomb")) { num2 += 0.15f; } if (name.Contains("Coconut_half")) { num2 += 0.35f; } if (name.Contains("AloeVera")) { num2 += 0.35f; } if (name.Contains("Glizzy")) { num2 += 0.69f; } if (name.Contains("Milk")) { num2 += 0.4f; } if (name.Contains("Turkey")) { num2 += 0.75f; } if (name.Contains("Napberry")) { num2 += 1f; } if (name.Contains("Prickleberry")) { num2 += 0.15f; } if (name.Contains("Cure-All")) { num2 += 0.3f; } if (name.Contains("MedicinalRoot")) { num2 += 0.25f; } if (name.Contains("Granola Bar")) { num2 += 0.15f; } if (name.Contains("Scout Cookies") || name.Contains("ScoutCookies")) { num2 += 0.3f; } if (name.Contains("Trail Mix") || name.Contains("TrailMix")) { num2 += 0.25f; } if (name.Contains("Airline Food")) { num2 += 0.35f; } if (name.Contains("Lollipop")) { num2 += 0.2f; } if (name.Contains("Egg") && !name.Contains("Turkey")) { num2 += 0.15f; } return Mathf.RoundToInt(num2 * 100f); } private static bool HasPoisonEffects(Item item) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 try { if ((Object)(object)((Component)item).GetComponent<Action_InflictPoison>() != (Object)null) { return true; } Action_ModifyStatus[] components = ((Component)item).GetComponents<Action_ModifyStatus>(); if (components != null) { Action_ModifyStatus[] array = components; foreach (Action_ModifyStatus val in array) { if ((int)val.statusType == 3 && val.changeAmount > 0f) { return true; } } } if ((Object)(object)((Component)item).GetComponent<Action_AddOrRemoveThorns>() != (Object)null) { return true; } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] Error checking poison effects: " + ex.Message)); } } return false; } private static float CalculatePoisonPenalty(Item item) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 float num = 0f; try { Action_InflictPoison component = ((Component)item).GetComponent<Action_InflictPoison>(); if ((Object)(object)component != (Object)null) { FieldInfo field = ((object)component).GetType().GetField("poisonAmount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { float num2 = (float)field.GetValue(component); num += num2 * 0.05f; } else { num += 0.05f; } if (num < 0.01f) { num = 0.05f; } } Action_ModifyStatus[] components = ((Component)item).GetComponents<Action_ModifyStatus>(); if (components != null) { Action_ModifyStatus[] array = components; foreach (Action_ModifyStatus val in array) { if ((int)val.statusType == 3 && val.changeAmount > 0f) { num += val.changeAmount * 0.05f; } } } if ((Object)(object)((Component)item).GetComponent<Action_AddOrRemoveThorns>() != (Object)null) { num += 0.05f; } } catch (Exception ex) { if (_instance != null) { _instance._log.LogError((object)("[PeakPelago] Error calculating poison penalty: " + ex.Message)); } num = 0.05f; } if (num < 0.01f) { num = 0.05f; } return num; } } private static RingLinkService _instance; public static void SetInstance(RingLinkService instance) { _instance = instance; } } private readonly ManualLogSource _log; private ArchipelagoSession _session; private bool _isEnabled; private int _connectionId; private Harmony _harmony; private ArchipelagoNotificationManager _notifications; public RingLinkService(ManualLogSource log, ArchipelagoNotificationManager notifications) { _log = log; _connectionId = Random.Range(int.MinValue, int.MaxValue); _notifications = notifications; } public void Initialize(ArchipelagoSession session, bool enabled) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown _session = session; _isEnabled = enabled; if (_session != null && _isEnabled) { _session.Socket.PacketReceived += new PacketReceivedHandler(OnPacketReceived); _harmony = new Harmony("com.mickemoose.peak.ap.ringlink"); _harmony.PatchAll(typeof(RingLinkPatches)); RingLinkPatches.SetInstance(this); _log.LogInfo((object)$"[PeakPelago] Ring Link service initialized (Connection ID: {_connectionId})"); } } public void SetEnabled(bool enabled) { _isEnabled = enabled; _log.LogInfo((object)("[PeakPelago] Ring Link " + (enabled ? "enabled" : "disabled"))); } public void SendRingLink(int amount) { //IL_006b: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (_session == null || !_isEnabled) { return; } try { Dictionary<string, JToken> data = new Dictionary<string, JToken> { { "time", JToken.FromObject((object)DateTimeOffset.UtcNow.ToUnixTimeSeconds()) }, { "source", JToken.FromObject((object)_connectionId) }, { "amount", JToken.FromObject((object)amount) } }; BouncePacket val = new BouncePacket { Tags = new List<string> { "RingLink" }, Data = data }; _session.Socket.SendPacket((ArchipelagoPacketBase)(object)val); string text = ((amount > 0) ? "positive" : "negative"); _log.LogInfo((object)$"[PeakPelago] Sent Ring Link: {amount} rings ({text})"); if (text == "positive") { _notifications.ShowRingLinkNotification($"RingLink: Sent +{amount} ring(s)"); } else { _notifications.ShowRingLinkNotification($"RingLink: Sent -{amount} ring(s)"); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to send Ring Link: " + ex.Message)); } } private void OnPacketReceived(ArchipelagoPacketBase packet) { try { BouncePacket val = (BouncePacket)(object)((packet is BouncePacket) ? packet : null); if (val != null && val.Tags != null && val.Tags.Contains("RingLink") && _isEnabled) { HandleRingLinkReceived(val.Data); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error handling Ring Link packet: " + ex.Message)); } } private void HandleRingLinkReceived(Dictionary<string, JToken> data) { try { if (data.ContainsKey("source") && data["source"].ToObject<int>() == _connectionId) { _log.LogDebug((object)"[PeakPelago] Ignoring own Ring Link"); } else if (data.ContainsKey("amount")) { int num = data["amount"].ToObject<int>(); string text = ((num > 0) ? "positive" : "negative"); _log.LogInfo((object)$"[PeakPelago] Ring Link received: {num} rings ({text})"); if (text == "positive") { _notifications.ShowRingLinkNotification($"RingLink: +{num} ring(s)!"); } else { _notifications.ShowRingLinkNotification($"RingLink: -{num} ring(s)!"); } ApplyRingLinkEffect(num); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to handle Ring Link: " + ex.Message)); } } private void ApplyRingLinkEffect(int amount) { try { if (Character.AllCharacters == null || Character.AllCharacters.Count == 0) { _log.LogWarning((object)"[PeakPelago] Cannot apply Ring Link - no characters found"); return; } float num = (float)amount / 100f; List<Character> list = Character.AllCharacters.Where((Character c) => (Object)(object)c != (Object)null && ((Component)c).gameObject.activeInHierarchy && !c.data.dead).ToList(); foreach (Character item in list) { if (num > 0f) { CharacterData data = item.data; data.extraStamina += num; } else if (num < 0f) { float num2 = Mathf.Abs(num); if (item.data.extraStamina > 0f) { float num3 = Mathf.Min(item.data.extraStamina, num2); CharacterData data2 = item.data; data2.extraStamina -= num3; num2 -= num3; } if (num2 > 0f) { item.data.staminaDelta = Mathf.Max(0f, item.data.staminaDelta - num2); } } string arg = ((amount > 0) ? "added" : "deducted"); _log.LogInfo((object)$"[PeakPelago] Ring Link {arg}: {Mathf.Abs(num)} stamina (from {amount} rings)"); } _log.LogInfo((object)$"[PeakPelago] Ring Link applied to {list.Count} character(s)"); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to apply Ring Link: " + ex.Message)); } } public void Cleanup() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (_session != null) { _session.Socket.PacketReceived -= new PacketReceivedHandler(OnPacketReceived); } if (_harmony != null) { _harmony.UnpatchSelf(); } RingLinkPatches.SetInstance(null); _session = null; _isEnabled = false; } } public class TrapLinkService { private readonly ManualLogSource _log; private ArchipelagoSession _session; private bool _isEnabled; private string _playerName; private LinkedList<string> _trapQueue = new LinkedList<string>(); private string _priorityTrap; private float _lastTrapActivation; private const float TRAP_ACTIVATION_COOLDOWN = 2f; private Action<string, bool> _applyTrapEffect; private Dictionary<string, string> _peakToStandardMapping; private Dictionary<string, string> _standardToPeakMapping; private HashSet<string> _enabledTraps; private ArchipelagoNotificationManager _notifications; public TrapLinkService(ManualLogSource log, ArchipelagoNotificationManager notifications) { _log = log; _notifications = notifications; InitializeTrapMappings(); } private void InitializeTrapMappings() { _peakToStandardMapping = new Dictionary<string, string> { { "Spawn Bee Swarm", "Bee Trap" }, { "Dynamite", "Bomb" }, { "Banana Peel Trap", "Banana Peel Trap" }, { "Minor Poison Trap", "Poison Mushroom" }, { "Poison Trap", "Poison Trap" }, { "Deadly Poison Trap", "Poison Trap" }, { "Tornado Trap", "Meteor Trap" }, { "Swap Trap", "Swap Trap" }, { "Nap Time Trap", "Stun Trap" }, { "Hungry Hungry Camper Trap", "Depletion Trap" }, { "Balloon Trap", "Gravity Trap" }, { "Slip Trap", "Slip Trap" }, { "Freeze Trap", "Freeze Trap" }, { "Cold Trap", "Ice Trap" }, { "Hot Trap", "Fire Trap" }, { "Injury Trap", "Damage Trap" }, { "Cactus Ball Trap", "Spike Ball Trap" }, { "Instant Death Trap", "Instant Death Trap" }, { "Yeet Trap", "Whoops! Trap" }, { "Tumbleweed Trap", "Tip Trap" }, { "Zombie Horde Trap", "Spooky Time" }, { "Gust Trap", "Get Out Trap" }, { "Mandrake Trap", "OmoTrap" }, { "Fungal Infection Trap", "Posession Trap" } }; _standardToPeakMapping = new Dictionary<string, string> { { "Bee Trap", "Spawn Bee Swarm" }, { "Eject Ability", "Yeet Trap" }, { "Whoops! Trap", "Yeet Trap" }, { "Banana Peel Trap", "Banana Peel Trap" }, { "Banana Trap", "Banana Peel Trap" }, { "Slip Trap", "Slip Trap" }, { "Poison Mushroom", "Minor Poison Trap" }, { "Poison Trap", "Poison Trap" }, { "TNT Barrel Trap", "Dynamite" }, { "Swap Trap", "Swap Trap" }, { "Flip Trap", "Slip Trap" }, { "Stun Trap", "Nap Time Trap" }, { "Paralyze Trap", "Nap Time Trap" }, { "Slowness Trap", "Nap Time Trap" }, { "Slow Trap", "Nap Time Trap" }, { "Depletion Trap", "Hungry Hungry Camper Trap" }, { "Dry Trap", "Hungry Hungry Camper Trap" }, { "Gravity Trap", "Balloon Trap" }, { "Bubble Trap", "Balloon Trap" }, { "Spring Trap", "Balloon Trap" }, { "Freeze Trap", "Freeze Trap" }, { "Ice Trap", "Cold Trap" }, { "Ice Floor Trap", "Cold Trap" }, { "Frozen Trap", "Freeze Trap" }, { "Fire Trap", "Hot Trap" }, { "Icy Hot Pants Trap", "Hot Trap" }, { "Damage Trap", "Injury Trap" }, { "Double Damage", "Injury Trap" }, { "Electrocution Trap", "Injury Trap" }, { "Spike Ball Trap", "Cactus Ball Trap" }, { "Cursed Ball Trap", "Cactus Ball Trap" }, { "Instant Death Trap", "Instant Death Trap" }, { "One Hit KO", "Instant Death Trap" }, { "Tip Trap", "Tumbleweed Trap" }, { "Items to Bombs", "Items to Bombs" }, { "Spooky Time", "Zombie Horde Trap" }, { "Army Trap", "Zombie Horde Trap" }, { "Police Trap", "Zombie Horde Trap" }, { "Meteor Trap", "Tornado Trap" }, { "Get Out Trap", "Gust Trap" }, { "Resistance Trap", "Gust Trap" }, { "OmoTrap", "Mandrake Trap" }, { "Posession Trap", "Fungal Infection Trap" } }; _log.LogInfo((object)$"[PeakPelago] Initialized trap mappings: {_peakToStandardMapping.Count} outgoing, {_standardToPeakMapping.Count} incoming"); } public void Initialize(ArchipelagoSession session, bool enabled, string playerName, HashSet<string> enabledTraps, Action<string, bool> applyTrapEffectCallback) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown _session = session; _isEnabled = enabled; _playerName = playerName; _enabledTraps = enabledTraps ?? new HashSet<string>(); _applyTrapEffect = applyTrapEffectCallback; if (_session != null && _isEnabled) { _session.Socket.PacketReceived += new PacketReceivedHandler(OnPacketReceived); _log.LogInfo((object)("[PeakPelago] Trap Link service initialized for player: " + _playerName)); _log.LogInfo((object)("[PeakPelago] Enabled traps: " + string.Join(", ", _enabledTraps))); } } public void SetEnabled(bool enabled) { _isEnabled = enabled; _log.LogInfo((object)("[PeakPelago] Trap Link " + (enabled ? "enabled" : "disabled"))); } public void SendTrapLink(string peakTrapName, bool fromTrapLink = false) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown if (_session == null || !_isEnabled || fromTrapLink) { return; } try { string text = peakTrapName; if (_peakToStandardMapping.TryGetValue(peakTrapName, out var value)) { text = value; _log.LogDebug((object)("[PeakPelago] Mapped '" + peakTrapName + "' to '" + text + "' for sending")); Dictionary<string, JToken> data = new Dictionary<string, JToken> { { "time", JToken.FromObject((object)DateTimeOffset.UtcNow.ToUnixTimeSeconds()) }, { "source", JToken.FromObject((object)_playerName) }, { "trap_name", JToken.FromObject((object)text) } }; BouncePacket val = new BouncePacket { Tags = new List<string> { "TrapLink" }, Data = data }; _session.Socket.SendPacket((ArchipelagoPacketBase)(object)val); _log.LogInfo((object)("[PeakPelago] Sent Trap Link: '" + text + "' (from '" + peakTrapName + "')")); _notifications.ShowTrapLinkNotification("TrapLink: sent " + text); } else { _log.LogWarning((object)("[PeakPelago] No standardized mapping for '" + peakTrapName + "', sending as-is")); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to send Trap Link: " + ex.Message)); } } private void OnPacketReceived(ArchipelagoPacketBase packet) { try { BouncePacket val = (BouncePacket)(object)((packet is BouncePacket) ? packet : null); if (val != null && val.Tags != null && val.Tags.Contains("TrapLink") && _isEnabled) { HandleTrapLinkReceived(val.Data); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error handling Trap Link packet: " + ex.Message)); } } private void HandleTrapLinkReceived(Dictionary<string, JToken> data) { try { if (data.ContainsKey("source") && data["source"].ToObject<string>() == _playerName) { _log.LogDebug((object)"[PeakPelago] Ignoring own Trap Link"); } else if (data.ContainsKey("trap_name")) { string text = data["trap_name"].ToObject<string>(); string text2 = (data.ContainsKey("source") ? data["source"].ToObject<string>() : "Unknown"); _log.LogInfo((object)("[PeakPelago] Trap Link received: '" + text + "'")); string text3 = MapToPeakTrap(text); if (text3 != null && _enabledTraps.Contains(text3)) { _priorityTrap = text3; _notifications.ShowTrapLinkNotification("TrapLink: received " + text + " from " + text2); _log.LogInfo((object)("[PeakPelago] Set priority trap: '" + text3 + "' (from '" + text + "')")); } else if (text3 == null) { _log.LogDebug((object)("[PeakPelago] No PEAK mapping for trap '" + text + "'")); } else { _log.LogDebug((object)("[PeakPelago] Trap '" + text3 + "' not enabled")); } } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to handle Trap Link: " + ex.Message)); } } private string MapToPeakTrap(string externalTrapName) { if (_standardToPeakMapping.TryGetValue(externalTrapName, out var value)) { return value; } return null; } public void Update() { if (!_isEnabled || _session == null || Time.time - _lastTrapActivation < 2f) { return; } if (_priorityTrap != null) { if (CanActivateTrap(_priorityTrap)) { ActivateTrap(_priorityTrap, fromTrapLink: true); _lastTrapActivation = Time.time; } else { _log.LogDebug((object)("[PeakPelago] Priority trap '" + _priorityTrap + "' not activatable, discarding")); } _priorityTrap = null; } else if (_trapQueue.Count > 0) { string value = _trapQueue.First.Value; _trapQueue.RemoveFirst(); if (CanActivateTrap(value)) { ActivateTrap(value, fromTrapLink: false); _lastTrapActivation = Time.time; } } } private bool CanActivateTrap(string trapName) { if ((Object)(object)Character.localCharacter == (Object)null) { return false; } if (Character.localCharacter.data.dead) { return false; } if (Character.localCharacter.data.fullyPassedOut) { return false; } return true; } private void ActivateTrap(string trapName, bool fromTrapLink) { try { _log.LogInfo((object)$"[PeakPelago] Activating trap: '{trapName}' (fromTrapLink: {fromTrapLink})"); _applyTrapEffect?.Invoke(trapName, fromTrapLink); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to activate trap '" + trapName + "': " + ex.Message)); } } public void QueueTrap(string trapName) { if (_isEnabled && _enabledTraps.Contains(trapName)) { _trapQueue.AddLast(trapName); _log.LogInfo((object)("[PeakPelago] Queued trap: '" + trapName + "'")); } } public void Cleanup() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (_session != null) { _session.Socket.PacketReceived -= new PacketReceivedHandler(OnPacketReceived); } _session = null; _isEnabled = false; _trapQueue.Clear(); _priorityTrap = null; } } public class ArchipelagoUI : MonoBehaviour { private const int BACKGROUND_RECT_X_COORD = 10; private const int BACKGROUND_RECT_Y_COORD = 30; private string _serverUrl = "archipelago.gg"; private string _port = "38281"; private string _slotName = string.Empty; private string _password = string.Empty; private int _fontSize = 12; private PeakArchipelagoPlugin _plugin; private const string PREFS_SERVER = "PeakPelago_ServerUrl"; private const string PREFS_PORT = "PeakPelago_Port"; private const string PREFS_SLOT = "PeakPelago_SlotName"; private const string PREFS_PASSWORD = "PeakPelago_Password"; private const string PREFS_FONTSIZE = "PeakPelago_FontSize"; public void Initialize(PeakArchipelagoPlugin plugin) { _plugin = plugin; LoadSettings(); } private void LoadSettings() { _serverUrl = PlayerPrefs.GetString("PeakPelago_ServerUrl", "archipelago.gg"); _port = PlayerPrefs.GetString("PeakPelago_Port", "38281"); _slotName = PlayerPrefs.GetString("PeakPelago_SlotName", string.Empty); _password = PlayerPrefs.GetString("PeakPelago_Password", string.Empty); _fontSize = PlayerPrefs.GetInt("PeakPelago_FontSize", 12); } private void SaveSettings() { PlayerPrefs.SetString("PeakPelago_ServerUrl", _serverUrl); PlayerPrefs.SetString("PeakPelago_Port", _port); PlayerPrefs.SetString("PeakPelago_SlotName", _slotName); PlayerPrefs.SetString("PeakPelago_Password", _password); PlayerPrefs.SetInt("PeakPelago_FontSize", _fontSize); PlayerPrefs.Save(); } private void OnGUI() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Invalid comparison between Unknown and I4 //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Invalid comparison between Unknown and I4 //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Invalid comparison between Unknown and I4 GUIStyle val = new GUIStyle(GUI.skin.label); GUIStyle val2 = new GUIStyle(GUI.skin.button); GUIStyle val3 = new GUIStyle(GUI.skin.textField); _setFontSize(val, val2, val3); val.normal.textColor = Color.white; int num = (int)Math.Round(320.0 * ((double)_fontSize / 12.0)); int num2 = _fontSize + 8; int num3 = 16; int num4 = 36; int num5 = num / 2; bool num6 = (Object)(object)_plugin != (Object)null && _plugin.Status == "Connected"; bool isMasterClient = PhotonNetwork.IsMasterClient; bool flag = PhotonNetwork.IsConnected && PhotonNetwork.CurrentRoom != null; if (!num6) { if (isMasterClient || !flag) { int num7 = 12 + num2 * 6; _drawShadedRectangle(new Rect(10f, (float)(num4 - 6), (float)num, (float)num7)); GUI.Label(new Rect((float)num3, (float)num4, (float)num5, (float)num2), "PeakPelago font size: ", val); if (GUI.Button(new Rect((float)(num3 + num5), (float)num4, (float)(_fontSize * 2), (float)num2), "-", val2)) { _fontSize = Mathf.Max(8, _fontSize - 1); SaveSettings(); } if (GUI.Button(new Rect((float)(num3 + num5 + _fontSize * 2 + 8), (float)num4, (float)(_fontSize * 2), (float)num2), "+", val2)) { _fontSize = Mathf.Min(24, _fontSize + 1); SaveSettings(); } num4 += num2; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; int num8 = num - num5; bool flag2 = (int)Event.current.type == 4 && (int)Event.current.keyCode == 13; string serverUrl = _serverUrl; string port = _port; string slotName = _slotName; string password = _password; GUI.Label(new Rect((float)num3, (float)num4, (float)num5, (float)num2), "Server: ", val); _serverUrl = GUI.TextField(new Rect((float)num5, (float)num4, (float)num8, (float)num2), _serverUrl, val3); num4 += num2; GUI.Label(new Rect((float)num3, (float)num4, (float)num5, (float)num2), "Port: ", val); _port = GUI.TextField(new Rect((float)num5, (float)num4, (float)num8, (float)num2), _port, val3); num4 += num2; GUI.Label(new Rect((float)num3, (float)num4, (float)num5, (float)num2), "Slot Name: ", val); _slotName = GUI.TextField(new Rect((float)num5, (float)num4, (float)num8, (float)num2), _slotName, val3); num4 += num2; GUI.Label(new Rect((float)num3, (float)num4, (float)num5, (float)num2), "Password: ", val); _password = GUI.TextField(new Rect((float)num5, (float)num4, (float)num8, (float)num2), _password, val3); num4 += num2; if (_serverUrl != serverUrl || _port != port || _slotName != slotName || _password != password) { SaveSettings(); } if (flag2 && (int)Event.current.type == 4) { flag2 = false; } if ((GUI.Button(new Rect((float)num3, (float)num4, (float)(76 + _fontSize * 2), (float)num2), "Connect", val2) || flag2) && !string.IsNullOrEmpty(_serverUrl) && !string.IsNullOrEmpty(_slotName)) { SaveSettings(); _plugin.SetConnectionDetails(_serverUrl, _port, _slotName, _password); _plugin.Connect(); } } else { int num9 = 12 + num2; _drawShadedRectangle(new Rect(10f, (float)(num4 - 6), (float)num, (float)num9)); GUI.Label(new Rect((float)num3, (float)num4, (float)num, (float)num2), "Archipelago: Connected to Host", val); } } else { int num10 = 12 + num2; _drawShadedRectangle(new Rect(10f, (float)(num4 - 6), (float)num, (float)num10)); string text = ((!isMasterClient && flag) ? "Archipelago connected through host." : "Archipelago configured."); GUI.Label(new Rect((float)num3, (float)num4, (float)num, (float)num2), text, val); } } private void _drawShadedRectangle(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.5f); GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } private void _setFontSize(params GUIStyle[] styles) { for (int i = 0; i < styles.Length; i++) { styles[i].fontSize = _fontSize; } } } public class ArchipelagoNotificationManager { private readonly ManualLogSource _log; private readonly string _localSlotName; private PlayerConnectionLog _connectionLog; private PhotonView _photonView; private readonly Color _mySlotColor = new Color(0.7f, 0.4f, 1f); public ArchipelagoNotificationManager(ManualLogSource log, string localSlotName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) _log = log; _localSlotName = localSlotName; } public void SetPhotonView(PhotonView photonView) { _photonView = photonView; } private void FindConnectionLog() { if ((Object)(object)_connectionLog == (Object)null) { _connectionLog = Object.FindFirstObjectByType<PlayerConnectionLog>(); if ((Object)(object)_connectionLog != (Object)null) { _log.LogInfo((object)"[PeakPelago] Found PlayerConnectionLog for notifications"); } } } private Color GetColorForClassification(ItemFlags classification) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) return (Color)((int)classification switch { 1 => new Color(0.69f, 0.01f, 0.76f), 2 => new Color(0f, 0.32f, 1f), 4 => new Color(0.92f, 0.47f, 0f), _ => new Color(0.7f, 0.7f, 0.7f), }); } private string GetColorTag(Color c) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return "<color=#" + ColorUtility.ToHtmlStringRGB(c) + ">"; } private void ShowItemNotificationLocal(string fromName, string toName, string itemName, ItemFlags classification) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) try { FindConnectionLog(); if ((Object)(object)_connectionLog == (Object)null) { _log.LogDebug((object)"[PeakPelago] PlayerConnectionLog not found, cannot display notification"); return; } bool num = fromName.Equals(_localSlotName, StringComparison.OrdinalIgnoreCase); bool flag = toName.Equals(_localSlotName, StringComparison.OrdinalIgnoreCase); Color c = (num ? _mySlotColor : _connectionLog.userColor); Color c2 = (flag ? _mySlotColor : _connectionLog.userColor); Color colorForClassification = GetColorForClassification(classification); string colorTag = GetColorTag(c); string colorTag2 = GetColorTag(c2); string colorTag3 = GetColorTag(colorForClassification); string text = colorTag + fromName + "</color> sent " + colorTag3 + itemName + "</color> to " + colorTag2 + toName + "</color>"; MethodInfo method = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(_connectionLog, new object[1] { text }); if (flag && (Object)(object)_connectionLog.sfxJoin != (Object)null) { _connectionLog.sfxJoin.Play(default(Vector3)); } _log.LogDebug((object)("[PeakPelago] Displayed notification: " + fromName + " -> " + itemName + " -> " + toName)); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error displaying item notification: " + ex.Message)); } } public void ShowItemNotification(string fromName, string toName, string itemName, ItemFlags classification) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowItemNotificationRPC", (RpcTarget)0, new object[4] { fromName, toName, itemName, (int)classification }); } else { ShowItemNotificationLocal(fromName, toName, itemName, classification); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting item notification: " + ex.Message)); } } public void ReceiveItemNotificationRPC(string fromName, string toName, string itemName, int classificationInt) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) ItemFlags classification = (ItemFlags)classificationInt; ShowItemNotificationLocal(fromName, toName, itemName, classification); } private void ShowSimpleMessageLocal(string message) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) try { FindConnectionLog(); if ((Object)(object)_connectionLog == (Object)null) { _log.LogDebug((object)"[PeakPelago] PlayerConnectionLog not found, cannot display message"); return; } MethodInfo method = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { string text = GetColorTag(_connectionLog.joinedColor) + message + "</color>"; method.Invoke(_connectionLog, new object[1] { text }); _log.LogDebug((object)("[PeakPelago] Displayed message: " + message)); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error displaying simple message: " + ex.Message)); } } public void ShowSimpleMessage(string message) { try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowSimpleMessageRPC", (RpcTarget)0, new object[1] { message }); } else { ShowSimpleMessageLocal(message); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting simple message: " + ex.Message)); } } public void ReceiveSimpleMessageRPC(string message) { ShowSimpleMessageLocal(message); } private void ShowWarningMessageLocal(string message) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { FindConnectionLog(); if (!((Object)(object)_connectionLog == (Object)null)) { MethodInfo method = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { string text = GetColorTag(_connectionLog.leftColor) + message + "</color>"; method.Invoke(_connectionLog, new object[1] { text }); } } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error displaying warning message: " + ex.Message)); } } public void ShowWarningMessage(string message) { try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowWarningMessageRPC", (RpcTarget)0, new object[1] { message }); } else { ShowWarningMessageLocal(message); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting warning message: " + ex.Message)); } } public void ReceiveWarningMessageRPC(string message) { ShowWarningMessageLocal(message); } private void ShowColoredMessageLocal(string message, Color color) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { FindConnectionLog(); if (!((Object)(object)_connectionLog == (Object)null)) { MethodInfo method = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { string text = GetColorTag(color) + message + "</color>"; method.Invoke(_connectionLog, new object[1] { text }); } } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error displaying colored message: " + ex.Message)); } } public void ShowColoredMessage(string message, Color color) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowColoredMessageRPC", (RpcTarget)0, new object[4] { message, color.r, color.g, color.b }); } else { ShowColoredMessageLocal(message, color); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting colored message: " + ex.Message)); } } public void ReceiveColoredMessageRPC(string message, float r, float g, float b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ShowColoredMessageLocal(message, new Color(r, g, b)); } private void ShowHeroTitleLocal(string message) { try { if ((Object)(object)GUIManager.instance != (Object)null) { GUIManager.instance.SetHeroTitle(message, (AudioClip)null); } else { _log.LogWarning((object)"[PeakPelago] Cannot show hero title - GUIManager not found"); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error showing hero title: " + ex.Message)); } } public void ShowHeroTitle(string message) { try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowHeroTitleRPC", (RpcTarget)0, new object[1] { message }); } else { ShowHeroTitleLocal(message); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting hero title: " + ex.Message)); } } public void ReceiveHeroTitleRPC(string message) { ShowHeroTitleLocal(message); } private void ShowDeathLinkLocal(string cause, string source) { //IL_004d: 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) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) try { FindConnectionLog(); if ((Object)(object)_connectionLog == (Object)null) { return; } MethodInfo method = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { string colorTag = GetColorTag(new Color(1f, 0.2f, 0.2f)); string colorTag2 = GetColorTag(_connectionLog.userColor); string text = colorTag + "Death Link:</color> " + source + " " + colorTag2 + cause + "</color>"; method.Invoke(_connectionLog, new object[1] { text }); if ((Object)(object)_connectionLog.sfxLeave != (Object)null) { _connectionLog.sfxLeave.Play(default(Vector3)); } } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error displaying death link: " + ex.Message)); } } public void ShowDeathLink(string cause, string source) { try { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { _photonView.RPC("ShowDeathLinkRPC", (RpcTarget)0, new object[2] { cause, source }); } else { ShowDeathLinkLocal(cause, source); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error broadcasting death link: " + ex.Message)); } } public void ReceiveDeathLinkRPC(string cause, string source) { ShowDeathLinkLocal(cause, source); } public void ShowGoalComplete() { ShowSimpleMessage("GOAL COMPLETE!"); } public void ShowTrapLinkNotification(string message) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ShowColoredMessage(message, new Color(1f, 0.5f, 0f)); } public void ShowDeathLinkSent(string message) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ShowColoredMessage(message, new Color(1f, 0.2f, 0.2f)); } public void ShowRingLinkNotification(string message) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ShowColoredMessage(message, new Color(1f, 0.84f, 0f)); } public void ShowConnected() { ShowSimpleMessage("Connected to Archipelago as " + _localSlotName); } public void ShowDisconnected() { ShowWarningMessage("Disconnected from Archipelago"); } } public enum TrapType { BananaPeelTrap, Coconut, Dynamite, SpawnBeeSwarm, DestroyHeldItem, SwapTrap, MinorPoisonTrap, PoisonTrap, DeadlyPoisonTrap, TornadoTrap, NapTimeTrap, BalloonTrap, HungryHungryCamperTrap, CactusBallTrap, FreezeTrap, SlipTrap, YeetTrap, TumbleweedTrapEffect, ZombieHordeTrap, GustTrap, MandrakeTrap, FungalInfectionTrap } public static class TrapTypeExtensions { private static readonly Dictionary<TrapType, string> _trapNames = new Dictionary<TrapType, string> { { TrapType.BananaPeelTrap, "Banana Peel Trap" }, { TrapType.Coconut, "Coconut" }, { TrapType.Dynamite, "Dynamite" }, { TrapType.SpawnBeeSwarm, "Spawn Bee Swarm" }, { TrapType.DestroyHeldItem, "Destroy Held Item" }, { TrapType.SwapTrap, "Swap Trap" }, { TrapType.MinorPoisonTrap, "Minor Poison Trap" }, { TrapType.PoisonTrap, "Poison Trap" }, { TrapType.DeadlyPoisonTrap, "Deadly Poison Trap" }, { TrapType.TornadoTrap, "Tornado Trap" }, { TrapType.NapTimeTrap, "Nap Time Trap" }, { TrapType.BalloonTrap, "Balloon Trap" }, { TrapType.HungryHungryCamperTrap, "Hungry Hungry Camper Trap" }, { TrapType.CactusBallTrap, "Cactus Ball Trap" }, { TrapType.FreezeTrap, "Freeze Trap" }, { TrapType.SlipTrap, "Slip Trap" }, { TrapType.YeetTrap, "Yeet Trap" }, { TrapType.TumbleweedTrapEffect, "Tumbleweed Trap" }, { TrapType.ZombieHordeTrap, "Zombie Horde Trap" }, { TrapType.GustTrap, "Gust Trap" }, { TrapType.MandrakeTrap, "Mandrake Trap" }, { TrapType.FungalInfectionTrap, "Fungal Infection Trap" } }; private static readonly Dictionary<string, TrapType> _nameToTrap = _trapNames.ToDictionary((KeyValuePair<TrapType, string> kvp) => kvp.Value, (KeyValuePair<TrapType, string> kvp) => kvp.Key); public static string ToTrapName(this TrapType trapType) { if (!_trapNames.TryGetValue(trapType, out var value)) { return trapType.ToString(); } return value; } public static bool TryParseTrapName(string trapName, out TrapType trapType) { return _nameToTrap.TryGetValue(trapName, out trapType); } public static bool IsTrapName(string itemName) { return _nameToTrap.ContainsKey(itemName); } public static HashSet<string> GetAllTrapNames() { HashSet<string> hashSet = new HashSet<string>(); foreach (string value in _trapNames.Values) { hashSet.Add(value); } return hashSet; } public static IEnumerable<TrapType> GetAllTraps() { return Enum.GetValues(typeof(TrapType)).Cast<TrapType>(); } } [BepInPlugin("com.mickemoose.peak.ap", "Peak Archipelago", "0.4.6")] public class PeakArchipelagoPlugin : BaseUnityPlugin, IInRoomCallbacks { [HarmonyPatch(typeof(MapHandler), "GoToSegment")] public static class MapHandlerGoToSegmentPatch { private static void Postfix(MapHandler __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_instance == (Object)null) { return; } int num = (int)__instance.GetCurrentSegment(); if (num < 0 || num >= __instance.segments.Length) { return; } MapSegment val = __instance.segments[num]; if ((Object)(object)val.reconnectSpawnPos != (Object)null) { foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter != (Object)null) { allCharacter.data.spawnPoint = val.reconnectSpawnPos; } } _instance._log.LogInfo((object)$"[PeakPelago] Updated spawn point for all players to segment {num}: {val.reconnectSpawnPos.position}"); } else { _instance._log.LogWarning((object)$"[PeakPelago] Segment {num} has no reconnect spawn position"); } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] GoToSegment patch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Luggage), "OpenLuggageRPC")] public static class LuggageOpenRPCPatch { private static void Postfix(Luggage __instance) { try { if (!((Object)(object)_instance == (Object)null) && PhotonNetwork.IsMasterClient) { _instance._log.LogInfo((object)("[PeakPelago] HOST: Luggage opened: " + __instance.GetName())); _instance.IncrementLuggageCount(); } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] OpenLuggageRPC patch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Item), "RequestPickup")] public static class ItemRequestPickupPatch { private static void Postfix(Item __instance, PhotonView characterView) { try { if (!((Object)(object)_instance == (Object)null) && PhotonNetwork.IsMasterClient) { Character component = ((Component)characterView).GetComponent<Character>(); if (!((Object)(object)component == (Object)null)) { string itemName = __instance.UIData.itemName; ushort itemID = __instance.itemID; _instance._log.LogDebug((object)$"[PeakPelago] HOST: Player {component.characterName} (Actor: {characterView.Owner.ActorNumber}) picked up item: {itemName} (ID: {itemID})"); _instance.TrackItemAcquisition(itemName, itemID); } } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] RequestPickup patch error: " + ex.Message)); _instance._log.LogError((object)("[PeakPelago] Stack trace: " + ex.StackTrace)); } } } } [HarmonyPatch(typeof(Character), "FinishZombifying")] public static class CharacterFinishZombifyingPatch { private static void Postfix(Character __instance) { try { if ((Object)(object)_instance == (Object)null || _instance._deathLinkService == null) { return; } if (_instance._isDyingFromDeathLink) { _instance._log.LogInfo((object)"[PeakPelago] Zombification was caused by DeathLink, not sending another DeathLink"); return; } _instance._log.LogInfo((object)("[PeakPelago] Character zombified: " + __instance.characterName)); if (_instance._deathLinkSendBehavior == 0) { _instance._log.LogInfo((object)"[PeakPelago] Sending Death Link (zombification - any player mode)"); _instance.SendDeathLink(_instance.cfgSlot.Value + " turned into a zombie"); } else { if (_instance._deathLinkSendBehavior != 1) { return; } bool flag = true; foreach (Character allCharacter in Character.AllCharacters) { if (!allCharacter.data.dead && !allCharacter.data.zombified) { flag = false; break; } } if (flag) { _instance._log.LogInfo((object)"[PeakPelago] Sending Death Link (all players dead/zombified mode)"); _instance.SendDeathLink("Everyone is dead or zombified"); } } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] FinishZombifying patch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(Character), "RPCA_Die")] public static class CharacterRPCADiePatch { private static void Postfix(Character __instance) { try { if ((Object)(object)_instance == (Object)null || _instance._deathLinkService == null) { return; } if (_instance._isDyingFromDeathLink) { _instance._log.LogInfo((object)"[PeakPelago] Death was caused by DeathLink, not sending another DeathLink"); return; } _instance._log.LogInfo((object)("[PeakPelago] Character died: " + __instance.characterName)); if (_instance._deathLinkSendBehavior == 0) { _instance._log.LogInfo((object)"[PeakPelago] Sending Death Link (any player dies mode)"); _instance.SendDeathLink(_instance.cfgSlot.Value + " died"); } else { if (_instance._deathLinkSendBehavior != 1) { return; } bool flag = true; foreach (Character allCharacter in Character.AllCharacters) { if (!allCharacter.data.dead) { flag = false; break; } } if (flag) { _instance._log.LogInfo((object)"[PeakPelago] Sending Death Link (all players dead mode)"); _instance.SendDeathLink("Everyone died"); } } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] RPCA_Die patch error: " + ex.Message)); } } } } [HarmonyPatch(typeof(AchievementManager), "ThrowAchievement")] public static class AchievementManagerThrowAchievementPatch { private static bool Prefix(ACHIEVEMENTTYPE type) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_instance == (Object)null) { Debug.Log((object)"[PeakPelago] ThrowAchievementPatch: _instance is null"); return true; } if (!_instance._badgesHidden) { Debug.Log((object)("[PeakPelago] ThrowAchievementPatch: badges not hidden, _badgesHidden = " + _instance._badgesHidden)); return true; } Debug.Log((object)("[PeakPelago] ThrowAchievementPatch: Processing badge " + ((object)(ACHIEVEMENTTYPE)(ref type)).ToString())); bool flag = _instance._originalUnlockedBadges.Contains(type); if (_instance.GetBadgeToLocationMapping().TryGetValue(type, out var value)) { _instance._log.LogInfo((object)("[PeakPelago] Badge condition met: " + value)); _instance.ReportCheckByName(value); if (flag) { _instance._log.LogInfo((object)("[PeakPelago] Re-awarding originally unlocked badge: " + value)); return true; } _instance._log.LogInfo((object)("[PeakPelago] New badge earned: " + value)); return true; } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] Badge patch error: " + ex.Message)); } } return true; } } [HarmonyPatch(typeof(AchievementManager), "IsAchievementUnlocked")] public static class AchievementManagerIsAchievementUnlockedPatch { private static bool Prefix(ACHIEVEMENTTYPE achievementType, ref bool __result) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_instance == (Object)null || !_instance._badgesHidden) { return true; } Dictionary<ACHIEVEMENTTYPE, string> badgeToLocationMapping = _instance.GetBadgeToLocationMapping(); if (badgeToLocationMapping.ContainsKey(achievementType)) { string text = badgeToLocationMapping[achievementType]; ArchipelagoSession session = _instance._session; long num = ((session != null) ? session.Locations.GetLocationIdFromName(_instance.cfgGameId.Value, text) : (-1)); if (num > 0 && _instance._reportedChecks.Contains(num)) { __result = true; return false; } __result = false; return false; } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] IsAchievementUnlocked patch error: " + ex.Message)); } } return true; } } [HarmonyPatch(typeof(AchievementManager), "GetMaxAscent")] public static class AchievementManagerGetMaxAscentPatch { private static bool Prefix(ref int __result) { try { if ((Object)(object)_instance == (Object)null || !_instance._badgesHidden) { return true; } if (_instance._unlockedAscents.Count > 0) { List<int> list = _instance._unlockedAscents.OrderBy((int x) => x).ToList(); int num = 0; for (int i = 1; i <= 7 && list.Contains(i); i++) { num = i; } __result = num; _instance._log.LogDebug((object)("[PeakPelago] GetMaxAscent returning: " + __result + " (AP unlocked: " + string.Join(", ", list) + ", consecutive up to: " + num + ")")); return false; } __result = 0; _instance._log.LogDebug((object)"[PeakPelago] GetMaxAscent returning: 0 (no AP ascents unlocked)"); return false; } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] GetMaxAscent patch error: " + ex.Message)); } } return true; } } [HarmonyPatch(typeof(MountainProgressHandler), "CheckAreaAchievement")] public static class MountainProgressHandlerCheckAreaAchievementPatch { private static void Postfix(ProgressPoint pointReached) { try { if ((Object)(object)_instance == (Object)null) { return; } string text = "Unknown"; if (pointReached != null) { FieldInfo field = ((object)pointReached).GetType().GetField("title"); if (field != null) { text = ((string)field.GetValue(pointReached)) ?? "Unknown"; } } _instance._log.LogInfo((object)("[PeakPelago] Player reached peak: " + text)); _instance.HandleAscentPeakReached(text); } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { _instance._log.LogError((object)("[PeakPelago] CheckAreaAchievement patch error: " + ex.Message)); } } } } [CompilerGenerated] private sealed class <ForceStaminaUIUpdate>d__132 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PeakArchipelagoPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ForceStaminaUIUpdate>d__132(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; PeakArchipelagoPlugin peakArchipelagoPlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; peakArchipelagoPlugin._log.LogInfo((object)"[PeakPelago] CLIENT: Forcing stamina UI update..."); if ((Object)(object)Character.localCharacter != (Object)null && peakArchipelagoPlugin._staminaManager != null) { float baseMaxStamina = peakArchipelagoPlugin._staminaManager.GetBaseMaxStamina(); float statusSum = Character.localCharacter.refs.afflictions.statusSum; float num2 = Mathf.Max(baseMaxStamina - statusSum, 0f); Character.localCharacter.data.currentStamina = Mathf.Min(Character.localCharacter.data.currentStamina, num2); peakArchipelagoPlugin._log.LogInfo((object)$"[PeakPelago] CLIENT: Set stamina to {Character.localCharacter.data.currentStamina} (max: {num2}, base: {baseMaxStamina})"); if ((Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.bar != (Object)null) { GUIManager.instance.bar.ChangeBar(); peakArchipelagoPlugin._log.LogInfo((object)"[PeakPelago] CLIENT: Stamina bar UI refreshed"); } else { peakArchipelagoPlugin._log.LogWarning((object)"[PeakPelago] CLIENT: GUIManager or bar is null, couldn't refresh UI"); } } else { peakArchipelagoPlugin._log.LogWarning((object)"[PeakPelago] CLIENT: Character or stamina manager is null, couldn't update"); } 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(); } } [CompilerGenerated] private sealed class <KillCharacterCoroutine>d__81 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PeakArchipelagoPlugin <>4__this; public string characterName; public Character targetCharacter; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <KillCharacterCoroutine>d__81(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown int num = <>1__state; PeakArchipelagoPlugin peakArchipelagoPlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { peakArchipelagoPlugin._log.LogInfo((object)("[PeakPelago] Executing death for " + characterName)); MethodInfo method = ((object)targetCharacter).GetType().GetMethod("DieInstantly", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(targetCharacter, null); peakArchipelagoPlugin._log.LogInfo((object)("[PeakPelago] DieInstantly succeeded for " + characterName)); } else { peakArchipelagoPlugin._log.LogError((object)"[PeakPelago] Could not find DieInstantly method"); } } catch (Exception ex) { peakArchipelagoPlugin._log.LogError((object)("[PeakPelago] Coroutine death failed: " + ex.Message)); if (ex.InnerException != null) { peakArchipelagoPlugin._log.LogError((object)("[PeakPelago] Inner: " + ex.InnerException.Message)); peakArchipelagoPlugin._log.LogError((object)("[PeakPelago] Inner stack: " + ex.InnerException.StackTrace)); } } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; case 2: <>1__state = -1; peakArchipelagoPlugin._isDyingFromDeathLink = false; 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(); } } [CompilerGenerated] private sealed class <RestoreSpeedAfterDelay>d__120 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delay; public Character character; public float originalModifier; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreSpeedAfterDelay>d__120(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)character != (Object)null && (Object)(object)character.refs.movement != (Object)null) { character.refs.movement.movementModifier = originalModifier; } 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 ManualLogSource _log; private Harmony _harmony; private ConfigEntry<string> cfgServer; private ConfigEntry<int> cfgPort; private ConfigEntry<string> cfgSlot; private ConfigEntry<string> cfgPassword; private ConfigEntry<string> cfgGameId; private ConfigEntry<bool> cfgAutoReconnect; private ConfigEntry<int> cfgGoalType; private ConfigEntry<int> cfgRequiredBadges; private ConfigEntry<int> cfgRequiredAscent; private ArchipelagoSession _session; private string _status = "Disconnected"; private bool _isConnecting; private bool _wantReconnect; private string _currentPort = ""; private int _lastProcessedItemIndex; private readonly HashSet<long> _reportedChecks = new HashSet<long>(); private int _itemsReceivedFromAP; private string _lastReceivedItemName = "None"; private DateTime _lastReceivedItemTime = DateTime.MinValue; private int _luggageOpenedCount; private int _luggageOpenedThisRun; private int _totalLuggageOpened; private bool _hasOpenedLuggageThisSession; private ProgressiveStaminaManager _staminaManager; private ArchipelagoNotificationManager _notifications; private PhotonView _photonView; private const string CHECK_RPC_NAME = "ReceiveCheckFromClient"; private HashSet<ACHIEVEMENTTYPE> _originalUnlockedBadges = new HashSet<ACHIEVEMENTTYPE>(); private bool _badgesHidden; private bool _hasHiddenBadges; private int _originalMaxAscent; private int _slotGoalType; private int _slotRequiredAscent; private int _slotRequiredBadges = 20; private HashSet<int> _unlockedAscents = new HashSet<int>(); private RingLinkService _ringLinkService; private HardRingLinkService _hardRingLinkService; private TrapLinkService _trapLinkService; private DeathLinkService _deathLinkService; private int _deathLinkBehavior; private bool _deathLinkReceivedThisSession; private int _deathLinkSendBehavior; private DateTime _lastDeathLinkSent = DateTime.MinValue; private DateTime _lastDeathLinkReceived = DateTime.MinValue; private string _lastDeathLinkSource = "None"; private string _lastDeathLinkCause = "None"; public bool _isDyingFromDeathLink; private ArchipelagoUI _ui; private LinkedList<(string itemName, bool isTrap, int itemIndex)> _itemQueue = new LinkedList<(string, bool, int)>(); private float _lastItemProcessed; private const float ITEM_PROCESSING_COOLDOWN = 1f; private string _lastAcquiredItemName = "None"; private ushort _lastAcquiredItemId; private float _lastAcquiredItemTime; private Dictionary<string, string> _itemToLocationMapping = new Dictionary<string, string>(); private HashSet<string> _awardedAscentBadges = new HashSet<string>(); private HashSet<ACHIEVEMENTTYPE> _collectedBadges = new HashSet<ACHIEVEMENTTYPE>(); private Dictionary<string, Action> _itemEffectHandlers = new Dictionary<string, Action>(); private string StateFilePath => Path.Combine(Paths.ConfigPath, "Peak.AP.state." + _currentPort.Replace(":", "_") + ".txt"); public PhotonView PhotonView => _photonView; public static PeakArchipelagoPlugin _instance { get; private set; } public string Status => _status; private void Awake() { //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Expected O, but got Unknown try { _log = ((BaseUnityPlugin)this).Logger; _instance = this; _log.LogInfo((object)"[PeakPelago] Plugin is initializing..."); cfgServer = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "Server", "archipelago.gg", "Host, or host:port"); cfgPort = ((BaseUnityPlugin)this).Config.Bind<int>("Connection", "Port", 38281, "Port (ignored if Server already contains :port)"); cfgSlot = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "Slot", "Player", "Your AP slot name"); cfgPassword = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "Password", "", "Room password (optional)"); cfgGameId = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "GameId", "PEAK", "Game ID (must match the room)"); cfgAutoReconnect = ((BaseUnityPlugin)this).Config.Bind<bool>("Connection", "AutoReconnect", true, "Try to reconnect when socket closes"); cfgGoalType = ((BaseUnityPlugin)this).Config.Bind<int>("Goal", "Type", 0, "Goal type: 0=Reach Peak, 1=All Badges, 2=24 Karat Badge"); cfgRequiredBadges = ((BaseUnityPlugin)this).Config.Bind<int>("Goal", "BadgeCount", 20, "Number of badges required for Complete All Badges goal"); cfgRequiredAscent = ((BaseUnityPlugin)this).Config.Bind<int>("Goal", "RequiredAscent", 4, "Ascent level required for Reach Peak goal (0-7)"); _notifications = new ArchipelagoNotificationManager(_log, cfgSlot.Value); _staminaManager = new ProgressiveStaminaManager(_log); CharacterGetMaxStaminaPatch.SetStaminaManager(_staminaManager); CharacterClampStaminaPatch.SetStaminaManager(_staminaManager); CharacterHandleLifePatch.SetStaminaManager(_staminaManager); StaminaBarUpdatePatch.SetStaminaManager(_staminaManager); CharacterHandlePassedOutPatch.SetStaminaManager(_staminaManager); BarAfflictionUpdateAfflictionPatch.SetStaminaManager(_staminaManager); BarAfflictionChangeAfflictionPatch.SetStaminaManager(_staminaManager); _ringLinkService = new RingLinkService(_log, _notifications); _hardRingLinkService = new HardRingLinkService(_log, _notifications); _trapLinkService = new TrapLinkService(_log, _notifications); SwapTrapEffect.Initialize(_log, this); AfflictionTrapEffect.Initialize(_log); CheckAndHandlePortChange(); _ui = ((Component)this).gameObject.AddComponent<ArchipelagoUI>(); _ui.Initialize(this); InitializeItemMapping(); InitializeItemEffectHandlers(); GlobalEvents.OnAchievementThrown = (Action<ACHIEVEMENTTYPE>)Delegate.Combine(GlobalEvents.OnAchievementThrown, new Action<ACHIEVEMENTTYPE>(OnAchievementThrown)); GlobalEvents.OnItemRequested = (Action<Item, Character>)Delegate.Combine(GlobalEvents.OnItemRequested, new Action<Item, Character>(OnItemRequested)); _log.LogInfo((object)"[PeakPelago] About to apply Harmony patches..."); _harmony = new Harmony("com.mickemoose.peak.ap"); _harmony.PatchAll(); _log.LogInfo((object)"[PeakPelago] Harmony patches applied successfully"); SetupPhotonView(); _notifications.SetPhotonView(_photonView); ((MonoBehaviour)this).Invoke("HideExistingBadges", 1f); ((MonoBehaviour)this).Invoke("StoreOriginalAscent", 1f); _status = "Ready"; PhotonNetwork.AddCallbackTarget((object)this); _log.LogInfo((object)"[PeakPelago] Plugin ready."); ((MonoBehaviour)this).Invoke("CountExistingBadges", 1.5f); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] CRITICAL ERROR during plugin initialization: " + ex.Message)); _log.LogError((object)("[PeakPelago] Stack trace: " + ex.StackTrace)); } } public void ApplyAfflictionViaRPC(int actorNumber, int statusType, float amount) { if ((Object)(object)_photonView != (Object)null && PhotonNetwork.IsConnected) { Player val = ((IEnumerable<Player>)PhotonNetwork.PlayerList).FirstOrDefault((Func<Player, bool>)((Player p) => p.ActorNumber == actorNumber)); if (val != null) { _photonView.RPC("ApplyAfflictionToPlayer", val, new object[3] { actorNumber, statusType, amount }); _log.LogInfo((object)$"[PeakPelago] Sent affliction RPC to actor {actorNumber}"); } else { _log.LogWarning((object)$"[PeakPelago] Could not find player with actor number {actorNumber}"); } } } public void IncrementLuggageCount() { _hasOpenedLuggageThisSession = true; _luggageOpenedCount++; _luggageOpenedThisRun++; _totalLuggageOpened++; _log.LogInfo((object)$"[PeakPelago] Luggage count - Total: {_totalLuggageOpened}, This run: {_luggageOpenedThisRun}"); CheckLuggageAchievements(); SaveState(); } private void OnDestroy() { GlobalEvents.OnAchievementThrown = (Action<ACHIEVEMENTTYPE>)Delegate.Remove(GlobalEvents.OnAchievementThrown, new Action<ACHIEVEMENTTYPE>(OnAchievementThrown)); GlobalEvents.OnItemRequested = (Action<Item, Character>)Delegate.Remove(GlobalEvents.OnItemRequested, new Action<Item, Character>(OnItemRequested)); _ringLinkService?.Cleanup(); _hardRingLinkService?.Cleanup(); _trapLinkService?.Cleanup(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } TryCloseSession(); SaveState(); } private void SetupPhotonView() { try { _photonView = ((Component)this).GetComponent<PhotonView>(); if ((Object)(object)_photonView == (Object)null) { _photonView = ((Component)this).gameObject.AddComponent<PhotonView>(); } if (_photonView.ViewID == 0) { _photonView.ViewID = 999001; } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to setup PhotonView: " + ex.Message)); _log.LogWarning((object)"[PeakPelago] Network synchronization may not work properly"); } } public void OnPlayerEnteredRoom(Player newPlayer) { try { _log.LogInfo((object)("[PeakPelago] Player " + newPlayer.NickName + " joined the room")); if (PhotonNetwork.IsMasterClient && (Object)(object)_photonView != (Object)null) { bool flag = _staminaManager?.IsProgressiveStaminaEnabled() ?? false; int num = _staminaManager?.GetStaminaUpgradesReceived() ?? 0; _log.LogInfo((object)$"[PeakPelago] Host syncing to {newPlayer.NickName}: progressive={flag}, upgrades={num}"); _photonView.RPC("SyncStaminaConfiguration", newPlayer, new object[2] { flag, num }); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error in OnPlayerEnteredRoom: " + ex.Message)); } } [PunRPC] private void SyncStaminaUpgrade(int totalUpgrades) { try { _log.LogInfo((object)$"[PeakPelago] RPC received: SyncStaminaUpgrade - total upgrades: {totalUpgrades}"); if (_staminaManager == null) { _log.LogError((object)"[PeakPelago] StaminaManager is null!"); return; } int num = _staminaManager.GetStaminaUpgradesReceived(); while (num < totalUpgrades) { _staminaManager.ApplyStaminaUpgrade(); num++; _log.LogInfo((object)$"[PeakPelago] Applied stamina upgrade {num}/{totalUpgrades}"); } ((MonoBehaviour)this).StartCoroutine(ForceStaminaUIUpdate()); _log.LogInfo((object)$"[PeakPelago] Stamina sync complete - now at {num} upgrades"); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error in SyncStaminaUpgrade: " + ex.Message)); _log.LogError((object)("[PeakPelago] Stack trace: " + ex.StackTrace)); } } [PunRPC] private void SyncStaminaConfiguration(bool progressiveEnabled, int totalUpgrades) { try { _log.LogInfo((object)$"[PeakPelago] CLIENT: Received stamina configuration: progressive={progressiveEnabled}, upgrades={totalUpgrades}"); if (_staminaManager == null) { _log.LogError((object)"[PeakPelago] CLIENT: StaminaManager is null!"); return; } _staminaManager.Initialize(progressiveEnabled, additionalBarsEnabled: true); _log.LogInfo((object)"[PeakPelago] CLIENT: Initialized stamina manager"); for (int i = 0; i < totalUpgrades; i++) { _staminaManager.ApplyStaminaUpgrade(); _log.LogInfo((object)$"[PeakPelago] CLIENT: Applied upgrade {i + 1}/{totalUpgrades}"); } _log.LogInfo((object)$"[PeakPelago] CLIENT: Final base max stamina: {_staminaManager.GetBaseMaxStamina()}"); ((MonoBehaviour)this).StartCoroutine(ForceStaminaUIUpdate()); _log.LogInfo((object)"[PeakPelago] CLIENT: Successfully configured stamina system"); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] CLIENT: Error in SyncStaminaConfiguration: " + ex.Message)); _log.LogError((object)("[PeakPelago] CLIENT: Stack trace: " + ex.StackTrace)); } } [PunRPC] private void ShowItemNotificationRPC(string fromName, string toName, string itemName, int classificationInt) { _notifications?.ReceiveItemNotificationRPC(fromName, toName, itemName, classificationInt); } [PunRPC] private void ShowSimpleMessageRPC(string message) { _notifications?.ReceiveSimpleMessageRPC(message); } [PunRPC] private void ShowWarningMessageRPC(string message) { _notifications?.ReceiveWarningMessageRPC(message); } [PunRPC] private void ShowColoredMessageRPC(string message, float r, float g, float b) { _notifications?.ReceiveColoredMessageRPC(message, r, g, b); } [PunRPC] private void ShowHeroTitleRPC(string message) { _notifications?.ReceiveHeroTitleRPC(message); } [PunRPC] private void ShowDeathLinkRPC(string cause, string source) { _notifications?.ReceiveDeathLinkRPC(cause, source); } [PunRPC] private void ReceiveCheckFromClient(string locationName, int senderId) { try { _log.LogInfo((object)$"[PeakPelago] Received check '{locationName}' from player {senderId}"); if (PhotonNetwork.IsMasterClient) { ReportCheckByName(locationName); } else { _log.LogWarning((object)"[PeakPelago] Non-host received RPC - this shouldn't happen"); } } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Error in ReceiveCheckFromClient RPC: " + ex.Message)); } } public void SendDeathLink(string cause = "Unknown") { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if (_deathLinkService == null) { _log.LogDebug((object)"[PeakPelago] Cannot send death link - not connected or disabled"); return; } try { if (DateTime.Now - _lastDeathLinkSent < TimeSpan.FromSeconds(5.0)) { _log.LogDebug((object)"[PeakPelago] Death link throttled - too recent"); return; } DeathLink val = new DeathLink(cfgSlot.Value, cause); _deathLinkService.SendDeathLink(val); _lastDeathLinkSent = DateTime.Now; _notifications.ShowDeathLinkSent("DeathLink Sent!"); _log.LogInfo((object)("[PeakPelago] *** DEATH LINK SENT ***: " + cause + " from " + cfgSlot.Value)); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to send death link: " + ex.Message)); } } private void HandleDeathLinkReceived(string cause, string source) { if (_deathLinkService == null) { _log.LogDebug((object)"[PeakPelago] Death link received but disabled"); return; } try { if (DateTime.Now - _lastDeathLinkReceived < TimeSpan.FromSeconds(5.0)) { _log.LogDebug((object)"[PeakPelago] Death link throttled - too recent"); return; } _lastDeathLinkReceived = DateTime.Now; _lastDeathLinkSource = source; _lastDeathLinkCause = cause; _deathLinkReceivedThisSession = true; _log.LogInfo((object)("[PeakPelago] *** DEATH LINK RECEIVED ***: " + cause + " from " + source)); KillLocalPlayerFromDeathLink(cause, source); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to handle death link: " + ex.Message)); } } private void KillLocalPlayerFromDeathLink(string cause, string source) { //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) try { if (Character.AllCharacters == null || Character.AllCharacters.Count == 0) { _log.LogWarning((object)"[PeakPelago] Cannot apply death link - no characters found"); return; } List<Character> list = Character.AllCharacters.Where((Character c) => (Object)(object)c != (Object)null && ((Component)c).gameObject.activeInHierarchy && !c.data.dead && !c.data.fullyPassedOut).ToList(); if (list.Count == 0) { _log.LogWarning((object)"[PeakPelago] Cannot apply death link - no valid characters found"); return; } Random random = new Random(); Character val = list[random.Next(list.Count)]; if ((Object)(object)val == (Object)null) { _log.LogWarning((object)"[PeakPelago] Cannot apply death link - target character not found"); return; } string text = ((!((Object)(object)val == (Object)(object)Character.localCharacter)) ? (val.characterName ?? "Player") : cfgSlot.Value); _log.LogInfo((object)("[PeakPelago] Applying death link to " + text + " due to death from " + source + " (" + cause + ")")); _notifications.ShowDeathLink(cause, source); _notifications.ShowHeroTitle("RIP " + text.ToUpper()); if (_deathLinkBehavior == 1) { _log.LogInfo((object)"[PeakPelago] Death link behavior: Reset to checkpoint"); Vector3 lastCheckpointPosition = GetLastCheckpointPosition(); foreach (Character item in list) { try { item.WarpPlayerRPC(lastCheckpointPosition, true); _log.LogInfo((object)string.Format("[PeakPelago] Warped {0} to checkpoint at {1}", item.characterName ?? "player", lastCheckpointPosition)); } catch (Exception ex) { _log.LogError((object)("[PeakPelago] Failed to warp " + (item.characterName ?? "player") + ": " + ex.Message)); } } } else { _isDyingFromDeathLink = true; ((MonoBehaviour)this).StartCoroutine(KillCharacterCoroutine(val, text)); } _log.LogInfo((object)("[PeakPelago] Death link applied to " + text)); } catch (Exception ex2) { _log.LogError((object)("[PeakPelago] Failed to apply death link: " + ex2.Message)); _log.LogError((object)("[PeakPelago] Stack trace: " + ex2.StackTrace)); } } [IteratorStateMachine(typeof(<KillCharacterCoroutine>d__81))] private IEnumerator KillCharacterCoroutine(Character targetCharacter, string characterName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <KillCharacterCoroutine>d__81(0) { <>4__this = this, targetCharacter = targetCharacter, characterName = characterName }; } private Vector3 GetLastCheckpointPosition() { //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030a: 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_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)Character.localCharacter == (Object)null) { return Vector3.zero; } Vector3 val; if ((Object)(object)Character.localCharacter.data.spawnPoint != (Object)null) { Vector3 position = Character.localCharacter.data.spawnPoint.position; ManualLogSource log = _log; val = position; log.LogDebug((object)("[PeakPelago] Using character spawn point: " + ((object)(Vector3)(ref val)).ToString())); return position; } object mapHandler = GetMapHandler(); if (mapHandler != null) { MethodInfo method = mapHandler.GetType().GetMethod("GetCurrentSegment"); if (method != null) { object obj = method.Invoke(mapHandler, null); object mapSegments = GetMapSegments(mapHandler); if (mapSegments != null && mapSegments is Array array && (int)obj < array.Length) { object value = array.GetValue((int)obj); if (value != null) { FieldInfo field = value.GetType().GetField("segmentCampfire"); if (field != null)