From 0cbb039a47f4c6e9d5bc8a463bf850975987f6c0 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sat, 26 Jul 2025 15:22:30 -0400 Subject: [PATCH 1/8] add create hints --- .../Archipelago.MultiClient.Net.csproj | 26 +++++ .../ArchipelagoSession.cs | 7 +- .../ArchipelagoSessionFactory.cs | 3 +- .../Converters/ArchipelagoPacketConverter.cs | 5 +- .../Enums/ArchipelagoPacketType.cs | 3 +- .../Helpers/CreateHintsHelper.cs | 107 ++++++++++++++++++ .../Helpers/LocationCheckHelper.cs | 2 +- .../Packets/CreateHintsPacket.cs | 19 ++++ .../Packets/LocationScoutsPacket.cs | 2 +- 9 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs create mode 100644 Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs diff --git a/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj b/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj index f13313d6..f236583c 100644 --- a/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj +++ b/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj @@ -61,6 +61,9 @@ + + 7.0.4 + ..\DLLs\net45\Newtonsoft.Json.dll @@ -76,6 +79,29 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + 7.0.4 + + + + + + 7.0.4 + + + diff --git a/Archipelago.MultiClient.Net/ArchipelagoSession.cs b/Archipelago.MultiClient.Net/ArchipelagoSession.cs index c2442a48..13fc7dc3 100644 --- a/Archipelago.MultiClient.Net/ArchipelagoSession.cs +++ b/Archipelago.MultiClient.Net/ArchipelagoSession.cs @@ -149,6 +149,9 @@ public partial class ArchipelagoSession : IArchipelagoSession /// public IMessageLogHelper MessageLog { get; } + /// + public ICreateHintsHelper CreateHints { get; } + #if NET35 volatile bool awaitingRoomInfo; volatile bool expectingLoginResult; @@ -165,7 +168,8 @@ internal ArchipelagoSession(IArchipelagoSocketHelper socket, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, - IMessageLogHelper messageLog) + IMessageLogHelper messageLog, + ICreateHintsHelper createHints) { Socket = socket; Items = items; @@ -175,6 +179,7 @@ internal ArchipelagoSession(IArchipelagoSocketHelper socket, connectionInfo = connectionInfoHelper; DataStorage = dataStorage; MessageLog = messageLog; + CreateHints = createHints; socket.PacketReceived += Socket_PacketReceived; } diff --git a/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs b/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs index 8c45701d..84c1ecf3 100644 --- a/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs +++ b/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs @@ -27,8 +27,9 @@ public static ArchipelagoSession CreateSession(Uri uri) var roomState = new RoomStateHelper(socket, locations); var dataStorage = new DataStorageHelper(socket, connectionInfo); var messageLog = new MessageLogHelper(socket, itemInfoResolver, players, connectionInfo); + var createHints = new CreateHintsHelper(socket, players, locations, roomState); - return new ArchipelagoSession(socket, items, locations, players, roomState, connectionInfo, dataStorage, messageLog); + return new ArchipelagoSession(socket, items, locations, players, roomState, connectionInfo, dataStorage, messageLog, createHints); } /// diff --git a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs index 7741aeae..04e9aacc 100644 --- a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs +++ b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs @@ -25,8 +25,9 @@ public class ArchipelagoPacketConverter : JsonConverter [ArchipelagoPacketType.Connect] = obj => obj.ToObject(), [ArchipelagoPacketType.ConnectUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationChecks] = obj => obj.ToObject(), - [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), - [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), + [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), + [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), + [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.Say] = obj => obj.ToObject(), [ArchipelagoPacketType.GetDataPackage] = obj => obj.ToObject(), [ArchipelagoPacketType.DataPackage] = obj => obj.ToObject(), diff --git a/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs b/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs index fe6c551e..24a45614 100644 --- a/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs +++ b/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs @@ -15,7 +15,8 @@ public enum ArchipelagoPacketType ConnectUpdate, LocationChecks, LocationScouts, - StatusUpdate, + CreateHints, + StatusUpdate, Say, GetDataPackage, DataPackage, diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs new file mode 100644 index 00000000..810f904f --- /dev/null +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -0,0 +1,107 @@ +using Archipelago.MultiClient.Net.Converters; +using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Packets; +using System; +using System.Collections.ObjectModel; +using System.Net.Sockets; + +namespace Archipelago.MultiClient.Net.Helpers +{ + /// + /// Provides information about the current state of the server + /// + public interface ICreateHintsHelper + { + /// + /// Tell the server to create hints for the specified locations. + /// When creating hints for another slot's locations, the packet will fail if any of those locations do not contain an item for the requesting slot. + /// When creating hints for your own slot's locations, non-existing locations will be silently skipped. + /// + /// + /// The ID of the player whose locations ar ebeing hinted for. + /// + /// + /// If included, sets the status of the created hints to this status. + /// Defaults to unspecified. + /// + /// + /// The location ids to create hints for. + /// + /// + /// The websocket connection is not alive. + /// + void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + + /// + /// Tell the server to create hints for the specified locations. + /// This version does not include the player id, and as such will only hint for locations in the active player's game. + /// When creating hints, non-existing locations will be silently skipped. + /// + /// + /// If included, sets the status of the created hints to this status. + /// Defaults to unspecified. + /// + /// + /// The location ids to create hints for. + /// + /// + /// The websocket connection is not alive. + /// + void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + } + + /// + public class CreateHintsHelper : ICreateHintsHelper + { + readonly IArchipelagoSocketHelper socket; + readonly ILocationCheckHelper locationCheckHelper; + readonly IRoomStateHelper roomStateHelper; + readonly IPlayerHelper players; + + /// + public Version Version { get; private set; } + + internal CreateHintsHelper(IArchipelagoSocketHelper socket, IPlayerHelper players, ILocationCheckHelper locationCheckHelper, IRoomStateHelper roomStateHelper) + { + this.socket = socket; + this.players = players; + this.locationCheckHelper = locationCheckHelper; + this.roomStateHelper = roomStateHelper; + } + /// + public void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + { + // The server supports CreateHints after version 0.6.2 + if (roomStateHelper.Version.CompareTo(new Version(0, 6, 2)) <= 0) + { + CreateHintsAsyncFallback(ids); + } + else + { + socket.SendPacketAsync(new CreateHintsPacket + { + Locations = ids, + Player = player, + Status = (int)hintStatus + }); + } + } + +#if NET35 + + /// + public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); +#else + /// + public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); +#endif + + /// + public void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + { + // When the player is not included, it defaults to the requesting slot. + var currentPlayer = players.ActivePlayer.Slot; + CreateHintsAsync(currentPlayer, hintStatus, ids); + } + } +} \ No newline at end of file diff --git a/Archipelago.MultiClient.Net/Helpers/LocationCheckHelper.cs b/Archipelago.MultiClient.Net/Helpers/LocationCheckHelper.cs index 9780417f..f7c56059 100644 --- a/Archipelago.MultiClient.Net/Helpers/LocationCheckHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/LocationCheckHelper.cs @@ -413,7 +413,7 @@ LocationChecksPacket GetLocationChecksPacket() => #if NET35 /// - public void ScoutLocationsAsync(Action> callback = null, + public void ScoutLocationsAsync(Action> callback = null, HintCreationPolicy hintCreationPolicy = HintCreationPolicy.None, params long[] ids) { var idsToScout = ids.Where(i => allLocations.Contains(i)).ToArray(); diff --git a/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs b/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs new file mode 100644 index 00000000..bcabc1d7 --- /dev/null +++ b/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs @@ -0,0 +1,19 @@ +using Archipelago.MultiClient.Net.Enums; +using Newtonsoft.Json; + +namespace Archipelago.MultiClient.Net.Packets +{ + 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 int Status { get; set; } + } +} diff --git a/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs b/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs index 62cb7e78..c92c632f 100644 --- a/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs +++ b/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs @@ -12,5 +12,5 @@ public class LocationScoutsPacket : ArchipelagoPacketBase [JsonProperty("create_as_hint")] public int CreateAsHint { get; set; } - } + } } From 65880a4ec77d850c37969b8408c8abf641af453d Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sat, 26 Jul 2025 15:29:15 -0400 Subject: [PATCH 2/8] Fix tabs vs spaces --- .../Archipelago.MultiClient.Net.csproj | 26 --- .../Converters/ArchipelagoPacketConverter.cs | 102 +++++------ .../Enums/ArchipelagoPacketType.cs | 4 +- .../Helpers/CreateHintsHelper.cs | 173 +++++++++--------- .../Packets/CreateHintsPacket.cs | 20 +- .../Packets/LocationScoutsPacket.cs | 2 +- 6 files changed, 149 insertions(+), 178 deletions(-) diff --git a/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj b/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj index f236583c..f13313d6 100644 --- a/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj +++ b/Archipelago.MultiClient.Net/Archipelago.MultiClient.Net.csproj @@ -61,9 +61,6 @@ - - 7.0.4 - ..\DLLs\net45\Newtonsoft.Json.dll @@ -79,29 +76,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - 7.0.4 - - - - - - 7.0.4 - - - diff --git a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs index 04e9aacc..bdf3d484 100644 --- a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs +++ b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs @@ -7,13 +7,13 @@ namespace Archipelago.MultiClient.Net.Converters { - /// - /// Json Converter for archipelago packets - /// + /// + /// Json Converter for archipelago packets + /// public class ArchipelagoPacketConverter : JsonConverter { static readonly Dictionary> PacketDeserializationMap = - new Dictionary>(23) + new Dictionary>(23) { [ArchipelagoPacketType.RoomInfo] = obj => obj.ToObject(), [ArchipelagoPacketType.ConnectionRefused] = obj => obj.ToObject(), @@ -26,8 +26,8 @@ public class ArchipelagoPacketConverter : JsonConverter [ArchipelagoPacketType.ConnectUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationChecks] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), - [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), - [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), + [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), + [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.Say] = obj => obj.ToObject(), [ArchipelagoPacketType.GetDataPackage] = obj => obj.ToObject(), [ArchipelagoPacketType.DataPackage] = obj => obj.ToObject(), @@ -42,28 +42,28 @@ public class ArchipelagoPacketConverter : JsonConverter }; /// - public override bool CanWrite => false; + public override bool CanWrite => false; /// - public override bool CanConvert(Type objectType) => objectType.IsAssignableFrom(typeof(ArchipelagoPacketBase)); + public override bool CanConvert(Type objectType) => objectType.IsAssignableFrom(typeof(ArchipelagoPacketBase)); /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JObject.Load(reader); var commandType = token["cmd"]?.ToString(); ArchipelagoPacketBase packet; - if (EnumTryParse(commandType, out ArchipelagoPacketType packetType) && PacketDeserializationMap.ContainsKey(packetType)) - packet = PacketDeserializationMap[packetType](token); - else - packet = new UnknownPacket(); + if (EnumTryParse(commandType, out ArchipelagoPacketType packetType) && PacketDeserializationMap.ContainsKey(packetType)) + packet = PacketDeserializationMap[packetType](token); + else + packet = new UnknownPacket(); - packet.jobject = token; + packet.jobject = token; - return packet; - } + return packet; + } static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) { @@ -73,37 +73,37 @@ static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) { switch (type) { - case JsonMessageType.ItemSend: - return obj.ToObject(); - case JsonMessageType.ItemCheat: - return obj.ToObject(); - case JsonMessageType.Hint: + case JsonMessageType.ItemSend: + return obj.ToObject(); + case JsonMessageType.ItemCheat: + return obj.ToObject(); + case JsonMessageType.Hint: return obj.ToObject(); - case JsonMessageType.Join: - return obj.ToObject(); - case JsonMessageType.Part: - return obj.ToObject(); - case JsonMessageType.Chat: - return obj.ToObject(); - case JsonMessageType.ServerChat: - return obj.ToObject(); - case JsonMessageType.Tutorial: - return obj.ToObject(); - case JsonMessageType.TagsChanged: - return obj.ToObject(); - case JsonMessageType.CommandResult: - return obj.ToObject(); - case JsonMessageType.AdminCommandResult: - return obj.ToObject(); - case JsonMessageType.Goal: - return obj.ToObject(); - case JsonMessageType.Release: - return obj.ToObject(); - case JsonMessageType.Collect: - return obj.ToObject(); - case JsonMessageType.Countdown: - return obj.ToObject(); - } + case JsonMessageType.Join: + return obj.ToObject(); + case JsonMessageType.Part: + return obj.ToObject(); + case JsonMessageType.Chat: + return obj.ToObject(); + case JsonMessageType.ServerChat: + return obj.ToObject(); + case JsonMessageType.Tutorial: + return obj.ToObject(); + case JsonMessageType.TagsChanged: + return obj.ToObject(); + case JsonMessageType.CommandResult: + return obj.ToObject(); + case JsonMessageType.AdminCommandResult: + return obj.ToObject(); + case JsonMessageType.Goal: + return obj.ToObject(); + case JsonMessageType.Release: + return obj.ToObject(); + case JsonMessageType.Collect: + return obj.ToObject(); + case JsonMessageType.Countdown: + return obj.ToObject(); + } } obj["type"] = null; @@ -116,7 +116,7 @@ static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) static bool EnumTryParse(string value, out TEnum result) where TEnum : struct, IConvertible { #if NET35 - if (value == null || !Enum.IsDefined(typeof(TEnum), value)) + if (value == null || !Enum.IsDefined(typeof(TEnum), value)) { result = default; return false; @@ -126,12 +126,12 @@ static bool EnumTryParse(string value, out TEnum result) where TEnum : st return true; #else #pragma warning disable IDE0022 // Use expression body for methods - return Enum.TryParse(value, out result); + return Enum.TryParse(value, out result); #pragma warning restore IDE0022 // Use expression body for methods #endif - } + } - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs b/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs index 24a45614..ba362164 100644 --- a/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs +++ b/Archipelago.MultiClient.Net/Enums/ArchipelagoPacketType.cs @@ -15,8 +15,8 @@ public enum ArchipelagoPacketType ConnectUpdate, LocationChecks, LocationScouts, - CreateHints, - StatusUpdate, + CreateHints, + StatusUpdate, Say, GetDataPackage, DataPackage, diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs index 810f904f..e2d7adcb 100644 --- a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -1,107 +1,104 @@ -using Archipelago.MultiClient.Net.Converters; -using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Packets; using System; -using System.Collections.ObjectModel; -using System.Net.Sockets; namespace Archipelago.MultiClient.Net.Helpers { - /// - /// Provides information about the current state of the server - /// - public interface ICreateHintsHelper - { - /// - /// Tell the server to create hints for the specified locations. - /// When creating hints for another slot's locations, the packet will fail if any of those locations do not contain an item for the requesting slot. - /// When creating hints for your own slot's locations, non-existing locations will be silently skipped. - /// - /// - /// The ID of the player whose locations ar ebeing hinted for. - /// - /// - /// If included, sets the status of the created hints to this status. - /// Defaults to unspecified. - /// - /// - /// The location ids to create hints for. - /// - /// - /// The websocket connection is not alive. - /// - void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + /// + /// Provides information about the current state of the server + /// + public interface ICreateHintsHelper + { + /// + /// Tell the server to create hints for the specified locations. + /// When creating hints for another slot's locations, the packet will fail if any of those locations do not contain an item for the requesting slot. + /// When creating hints for your own slot's locations, non-existing locations will be silently skipped. + /// + /// + /// The ID of the player whose locations ar ebeing hinted for. + /// + /// + /// If included, sets the status of the created hints to this status. + /// Defaults to unspecified. + /// + /// + /// The location ids to create hints for. + /// + /// + /// The websocket connection is not alive. + /// + void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); - /// - /// Tell the server to create hints for the specified locations. - /// This version does not include the player id, and as such will only hint for locations in the active player's game. - /// When creating hints, non-existing locations will be silently skipped. - /// - /// - /// If included, sets the status of the created hints to this status. - /// Defaults to unspecified. - /// - /// - /// The location ids to create hints for. - /// - /// - /// The websocket connection is not alive. - /// - void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); - } + /// + /// Tell the server to create hints for the specified locations. + /// This version does not include the player id, and as such will only hint for locations in the active player's game. + /// When creating hints, non-existing locations will be silently skipped. + /// + /// + /// If included, sets the status of the created hints to this status. + /// Defaults to unspecified. + /// + /// + /// The location ids to create hints for. + /// + /// + /// The websocket connection is not alive. + /// + void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + } - /// - public class CreateHintsHelper : ICreateHintsHelper - { - readonly IArchipelagoSocketHelper socket; - readonly ILocationCheckHelper locationCheckHelper; - readonly IRoomStateHelper roomStateHelper; - readonly IPlayerHelper players; + /// + public class CreateHintsHelper : ICreateHintsHelper + { + readonly IArchipelagoSocketHelper socket; + readonly ILocationCheckHelper locationCheckHelper; + readonly IRoomStateHelper roomStateHelper; + readonly IPlayerHelper players; - /// - public Version Version { get; private set; } + /// + public Version Version { get; private set; } internal CreateHintsHelper(IArchipelagoSocketHelper socket, IPlayerHelper players, ILocationCheckHelper locationCheckHelper, IRoomStateHelper roomStateHelper) { - this.socket = socket; - this.players = players; - this.locationCheckHelper = locationCheckHelper; - this.roomStateHelper = roomStateHelper; + this.socket = socket; + this.players = players; + this.locationCheckHelper = locationCheckHelper; + this.roomStateHelper = roomStateHelper; + } + /// + public void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + { + // The server supports CreateHints after version 0.6.2 + if (roomStateHelper.Version.CompareTo(new Version(0, 6, 2)) <= 0) + { + CreateHintsAsyncFallback(ids); + } + else + { + socket.SendPacketAsync(new CreateHintsPacket + { + Locations = ids, + Player = player, + Status = (int)hintStatus + }); + } } - /// - public void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) - { - // The server supports CreateHints after version 0.6.2 - if (roomStateHelper.Version.CompareTo(new Version(0, 6, 2)) <= 0) - { - CreateHintsAsyncFallback(ids); - } - else - { - socket.SendPacketAsync(new CreateHintsPacket - { - Locations = ids, - Player = player, - Status = (int)hintStatus - }); - } - } #if NET35 - /// - public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); + /// + public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); #else - /// - public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); + /// + public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); #endif - /// - public void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) - { - // When the player is not included, it defaults to the requesting slot. - var currentPlayer = players.ActivePlayer.Slot; - CreateHintsAsync(currentPlayer, hintStatus, ids); - } - } + /// + public void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + { + // When the player is not included, it defaults to the requesting slot. + var currentPlayer = players.ActivePlayer.Slot; + CreateHintsAsync(currentPlayer, hintStatus, ids); + } + } } \ No newline at end of file diff --git a/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs b/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs index bcabc1d7..c1ed4081 100644 --- a/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs +++ b/Archipelago.MultiClient.Net/Packets/CreateHintsPacket.cs @@ -3,17 +3,17 @@ namespace Archipelago.MultiClient.Net.Packets { - public class CreateHintsPacket : ArchipelagoPacketBase - { - public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.CreateHints; + public class CreateHintsPacket : ArchipelagoPacketBase + { + public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.CreateHints; - [JsonProperty("locations")] - public long[] Locations { get; set; } + [JsonProperty("locations")] + public long[] Locations { get; set; } - [JsonProperty("player")] - public int Player { get; set; } + [JsonProperty("player")] + public int Player { get; set; } - [JsonProperty("status")] - public int Status { get; set; } - } + [JsonProperty("status")] + public int Status { get; set; } + } } diff --git a/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs b/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs index c92c632f..62cb7e78 100644 --- a/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs +++ b/Archipelago.MultiClient.Net/Packets/LocationScoutsPacket.cs @@ -12,5 +12,5 @@ public class LocationScoutsPacket : ArchipelagoPacketBase [JsonProperty("create_as_hint")] public int CreateAsHint { get; set; } - } + } } From 6feaf8150c2a5811060aec969b24f09a0d9364aa Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sat, 26 Jul 2025 15:30:55 -0400 Subject: [PATCH 3/8] fix tabs vs spaces --- .../Converters/ArchipelagoPacketConverter.cs | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs index bdf3d484..1e0b3ff2 100644 --- a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs +++ b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs @@ -7,13 +7,13 @@ namespace Archipelago.MultiClient.Net.Converters { - /// - /// Json Converter for archipelago packets - /// + /// + /// Json Converter for archipelago packets + /// public class ArchipelagoPacketConverter : JsonConverter { static readonly Dictionary> PacketDeserializationMap = - new Dictionary>(23) + new Dictionary>(23) { [ArchipelagoPacketType.RoomInfo] = obj => obj.ToObject(), [ArchipelagoPacketType.ConnectionRefused] = obj => obj.ToObject(), @@ -26,8 +26,8 @@ public class ArchipelagoPacketConverter : JsonConverter [ArchipelagoPacketType.ConnectUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationChecks] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), - [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), - [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), + [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), + [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.Say] = obj => obj.ToObject(), [ArchipelagoPacketType.GetDataPackage] = obj => obj.ToObject(), [ArchipelagoPacketType.DataPackage] = obj => obj.ToObject(), @@ -42,28 +42,28 @@ public class ArchipelagoPacketConverter : JsonConverter }; /// - public override bool CanWrite => false; + public override bool CanWrite => false; /// - public override bool CanConvert(Type objectType) => objectType.IsAssignableFrom(typeof(ArchipelagoPacketBase)); + public override bool CanConvert(Type objectType) => objectType.IsAssignableFrom(typeof(ArchipelagoPacketBase)); /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JObject.Load(reader); var commandType = token["cmd"]?.ToString(); ArchipelagoPacketBase packet; - if (EnumTryParse(commandType, out ArchipelagoPacketType packetType) && PacketDeserializationMap.ContainsKey(packetType)) - packet = PacketDeserializationMap[packetType](token); - else - packet = new UnknownPacket(); + if (EnumTryParse(commandType, out ArchipelagoPacketType packetType) && PacketDeserializationMap.ContainsKey(packetType)) + packet = PacketDeserializationMap[packetType](token); + else + packet = new UnknownPacket(); - packet.jobject = token; + packet.jobject = token; - return packet; - } + return packet; + } static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) { @@ -73,37 +73,37 @@ static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) { switch (type) { - case JsonMessageType.ItemSend: - return obj.ToObject(); - case JsonMessageType.ItemCheat: - return obj.ToObject(); - case JsonMessageType.Hint: + case JsonMessageType.ItemSend: + return obj.ToObject(); + case JsonMessageType.ItemCheat: + return obj.ToObject(); + case JsonMessageType.Hint: return obj.ToObject(); - case JsonMessageType.Join: - return obj.ToObject(); - case JsonMessageType.Part: - return obj.ToObject(); - case JsonMessageType.Chat: - return obj.ToObject(); - case JsonMessageType.ServerChat: - return obj.ToObject(); - case JsonMessageType.Tutorial: - return obj.ToObject(); - case JsonMessageType.TagsChanged: - return obj.ToObject(); - case JsonMessageType.CommandResult: - return obj.ToObject(); - case JsonMessageType.AdminCommandResult: - return obj.ToObject(); - case JsonMessageType.Goal: - return obj.ToObject(); - case JsonMessageType.Release: - return obj.ToObject(); - case JsonMessageType.Collect: - return obj.ToObject(); - case JsonMessageType.Countdown: - return obj.ToObject(); - } + case JsonMessageType.Join: + return obj.ToObject(); + case JsonMessageType.Part: + return obj.ToObject(); + case JsonMessageType.Chat: + return obj.ToObject(); + case JsonMessageType.ServerChat: + return obj.ToObject(); + case JsonMessageType.Tutorial: + return obj.ToObject(); + case JsonMessageType.TagsChanged: + return obj.ToObject(); + case JsonMessageType.CommandResult: + return obj.ToObject(); + case JsonMessageType.AdminCommandResult: + return obj.ToObject(); + case JsonMessageType.Goal: + return obj.ToObject(); + case JsonMessageType.Release: + return obj.ToObject(); + case JsonMessageType.Collect: + return obj.ToObject(); + case JsonMessageType.Countdown: + return obj.ToObject(); + } } obj["type"] = null; @@ -116,7 +116,7 @@ static ArchipelagoPacketBase DeserializePrintJsonPacket(JObject obj) static bool EnumTryParse(string value, out TEnum result) where TEnum : struct, IConvertible { #if NET35 - if (value == null || !Enum.IsDefined(typeof(TEnum), value)) + if (value == null || !Enum.IsDefined(typeof(TEnum), value)) { result = default; return false; @@ -126,12 +126,12 @@ static bool EnumTryParse(string value, out TEnum result) where TEnum : st return true; #else #pragma warning disable IDE0022 // Use expression body for methods - return Enum.TryParse(value, out result); + return Enum.TryParse(value, out result); #pragma warning restore IDE0022 // Use expression body for methods #endif - } + } - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); } } \ No newline at end of file From e62d6bb00904d1f2c81c12191db19c91e0b77ec9 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sat, 26 Jul 2025 15:33:48 -0400 Subject: [PATCH 4/8] fix tabs vs spaces --- .../ArchipelagoSessionFactory.cs | 10 +++++----- .../Converters/ArchipelagoPacketConverter.cs | 4 ++-- .../Helpers/CreateHintsHelper.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs b/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs index 84c1ecf3..bb6df8d7 100644 --- a/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs +++ b/Archipelago.MultiClient.Net/ArchipelagoSessionFactory.cs @@ -21,13 +21,13 @@ public static ArchipelagoSession CreateSession(Uri uri) var dataPackageCache = new DataPackageCache(socket); var connectionInfo = new ConnectionInfoHelper(socket); var players = new PlayerHelper(socket, connectionInfo); - var itemInfoResolver = new ItemInfoResolver(dataPackageCache, connectionInfo); - var locations = new LocationCheckHelper(socket, itemInfoResolver, connectionInfo, players); + var itemInfoResolver = new ItemInfoResolver(dataPackageCache, connectionInfo); + var locations = new LocationCheckHelper(socket, itemInfoResolver, connectionInfo, players); var items = new ReceivedItemsHelper(socket, locations, itemInfoResolver, connectionInfo, players); - var roomState = new RoomStateHelper(socket, locations); - var dataStorage = new DataStorageHelper(socket, connectionInfo); + var roomState = new RoomStateHelper(socket, locations); + var dataStorage = new DataStorageHelper(socket, connectionInfo); var messageLog = new MessageLogHelper(socket, itemInfoResolver, players, connectionInfo); - var createHints = new CreateHintsHelper(socket, players, locations, roomState); + var createHints = new CreateHintsHelper(socket, players, locations, roomState); return new ArchipelagoSession(socket, items, locations, players, roomState, connectionInfo, dataStorage, messageLog, createHints); } diff --git a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs index 1e0b3ff2..f202751a 100644 --- a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs +++ b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs @@ -26,8 +26,8 @@ public class ArchipelagoPacketConverter : JsonConverter [ArchipelagoPacketType.ConnectUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationChecks] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), - [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), - [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), + [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), + [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.Say] = obj => obj.ToObject(), [ArchipelagoPacketType.GetDataPackage] = obj => obj.ToObject(), [ArchipelagoPacketType.DataPackage] = obj => obj.ToObject(), diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs index e2d7adcb..4a035c27 100644 --- a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -101,4 +101,4 @@ public void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, par CreateHintsAsync(currentPlayer, hintStatus, ids); } } -} \ No newline at end of file +} From d6ac69e5c72ba48e5b581856a4ab545f851df012 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sat, 26 Jul 2025 16:12:37 -0400 Subject: [PATCH 5/8] and just like that, it doesn't work --- .../ArchipelagoSession.cs | 4 ++-- .../Converters/ArchipelagoPacketConverter.cs | 2 +- .../Helpers/CreateHintsHelper.cs | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Archipelago.MultiClient.Net/ArchipelagoSession.cs b/Archipelago.MultiClient.Net/ArchipelagoSession.cs index 13fc7dc3..8339940a 100644 --- a/Archipelago.MultiClient.Net/ArchipelagoSession.cs +++ b/Archipelago.MultiClient.Net/ArchipelagoSession.cs @@ -169,7 +169,7 @@ internal ArchipelagoSession(IArchipelagoSocketHelper socket, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog, - ICreateHintsHelper createHints) + ICreateHintsHelper createHints) { Socket = socket; Items = items; @@ -179,7 +179,7 @@ internal ArchipelagoSession(IArchipelagoSocketHelper socket, connectionInfo = connectionInfoHelper; DataStorage = dataStorage; MessageLog = messageLog; - CreateHints = createHints; + CreateHints = createHints; socket.PacketReceived += Socket_PacketReceived; } diff --git a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs index f202751a..4839554c 100644 --- a/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs +++ b/Archipelago.MultiClient.Net/Converters/ArchipelagoPacketConverter.cs @@ -26,7 +26,7 @@ public class ArchipelagoPacketConverter : JsonConverter [ArchipelagoPacketType.ConnectUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationChecks] = obj => obj.ToObject(), [ArchipelagoPacketType.LocationScouts] = obj => obj.ToObject(), - [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), + [ArchipelagoPacketType.CreateHints] = obj => obj.ToObject(), [ArchipelagoPacketType.StatusUpdate] = obj => obj.ToObject(), [ArchipelagoPacketType.Say] = obj => obj.ToObject(), [ArchipelagoPacketType.GetDataPackage] = obj => obj.ToObject(), diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs index 4a035c27..e708acf0 100644 --- a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -27,7 +27,7 @@ public interface ICreateHintsHelper /// /// The websocket connection is not alive. /// - void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); /// /// Tell the server to create hints for the specified locations. @@ -44,7 +44,7 @@ public interface ICreateHintsHelper /// /// The websocket connection is not alive. /// - void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); + void CreateHints(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids); } /// @@ -66,16 +66,16 @@ internal CreateHintsHelper(IArchipelagoSocketHelper socket, IPlayerHelper player this.roomStateHelper = roomStateHelper; } /// - public void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + public void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) { // The server supports CreateHints after version 0.6.2 if (roomStateHelper.Version.CompareTo(new Version(0, 6, 2)) <= 0) { - CreateHintsAsyncFallback(ids); + CreateHintsFallback(ids); } else { - socket.SendPacketAsync(new CreateHintsPacket + socket.SendPacket(new CreateHintsPacket { Locations = ids, Player = player, @@ -87,18 +87,18 @@ public void CreateHintsAsync(int player, HintStatus hintStatus = HintStatus.Unsp #if NET35 /// - public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); + public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); #else /// - public void CreateHintsAsyncFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); + public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); #endif /// - public void CreateHintsAsync(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) + public void CreateHints(HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) { // When the player is not included, it defaults to the requesting slot. var currentPlayer = players.ActivePlayer.Slot; - CreateHintsAsync(currentPlayer, hintStatus, ids); + CreateHints(currentPlayer, hintStatus, ids); } } } From 35577996d5503ba5960f2587af60d31304c9f813 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sun, 10 Aug 2025 11:16:55 -0400 Subject: [PATCH 6/8] Attempt at fixing --- Archipelago.MultiClient.Net.Tests/ArchipelagoSessionFixture.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Archipelago.MultiClient.Net.Tests/ArchipelagoSessionFixture.cs b/Archipelago.MultiClient.Net.Tests/ArchipelagoSessionFixture.cs index 54edfdff..d6128257 100644 --- a/Archipelago.MultiClient.Net.Tests/ArchipelagoSessionFixture.cs +++ b/Archipelago.MultiClient.Net.Tests/ArchipelagoSessionFixture.cs @@ -193,8 +193,9 @@ static ArchipelagoSession CreateTestSession(IArchipelagoSocketHelper socket, var roomState = new RoomStateHelper(socket, locations); var dataStorage = new DataStorageHelper(socket, connectionInfo); var messageLog = new MessageLogHelper(socket, itemInfoResolver, players, connectionInfo); + var createHints = new CreateHintsHelper(socket, players, locations, roomState); - return new ArchipelagoSession(socket, items, locations, players, roomState, connectionInfo, dataStorage, messageLog); + return new ArchipelagoSession(socket, items, locations, players, roomState, connectionInfo, dataStorage, messageLog, createHints); } static void SetupLoginResultPacket(IArchipelagoSocketHelper socket, ArchipelagoPacketBase loginResultPacket) => From 0d24a2ff669d89eb535c9c803c61a8f335bdbd15 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sun, 10 Aug 2025 12:57:35 -0400 Subject: [PATCH 7/8] Add createAsHint to the functions to make it easier to read --- Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs index e708acf0..2bcaa87e 100644 --- a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -1,6 +1,8 @@ using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Packets; using System; +using System.Collections.Generic; +using System.Linq; namespace Archipelago.MultiClient.Net.Helpers { @@ -87,10 +89,10 @@ public void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecifi #if NET35 /// - public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, true, ids); + public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(null, createAsHint: true, ids); #else /// - public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(true, ids); + public void CreateHintsFallback(params long[] ids) => locationCheckHelper.ScoutLocationsAsync(createAsHint: true, ids); #endif /// From e201b8b07b4aa08de7a63852cb9c45a602ccaa1c Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sun, 10 Aug 2025 13:05:41 -0400 Subject: [PATCH 8/8] Add another linebreak to make it look a little nicer --- Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs index 2bcaa87e..00ec6772 100644 --- a/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs +++ b/Archipelago.MultiClient.Net/Helpers/CreateHintsHelper.cs @@ -67,6 +67,7 @@ internal CreateHintsHelper(IArchipelagoSocketHelper socket, IPlayerHelper player this.locationCheckHelper = locationCheckHelper; this.roomStateHelper = roomStateHelper; } + /// public void CreateHints(int player, HintStatus hintStatus = HintStatus.Unspecified, params long[] ids) {