diff --git a/Archipelago.MultiClient.Net.Tests/Archipelago.MultiClient.Net.Tests.csproj b/Archipelago.MultiClient.Net.Tests/Archipelago.MultiClient.Net.Tests.csproj
index 1f1f85a..abc6286 100644
--- a/Archipelago.MultiClient.Net.Tests/Archipelago.MultiClient.Net.Tests.csproj
+++ b/Archipelago.MultiClient.Net.Tests/Archipelago.MultiClient.Net.Tests.csproj
@@ -22,15 +22,8 @@
..\DLLs\net35\Newtonsoft.Json.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Debug\net35\Archipelago.MultiClient.Net.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Release\net35\Archipelago.MultiClient.Net.dll
+ ..\Archipelago.MultiClient.Net\bin\$(Configuration)\net35\Archipelago.MultiClient.Net.dll
@@ -38,15 +31,8 @@
..\DLLs\net40\Newtonsoft.Json.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Debug\net40\Archipelago.MultiClient.Net.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Release\net40\Archipelago.MultiClient.Net.dll
+ ..\Archipelago.MultiClient.Net\bin\$(Configuration)\net40\Archipelago.MultiClient.Net.dll
@@ -54,15 +40,8 @@
..\DLLs\net45\Newtonsoft.Json.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Debug\net45\Archipelago.MultiClient.Net.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Release\net45\Archipelago.MultiClient.Net.dll
+ ..\Archipelago.MultiClient.Net\bin\$(Configuration)\net45\Archipelago.MultiClient.Net.dll
@@ -70,15 +49,8 @@
..\DLLs\netstandard2.0\Newtonsoft.Json.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Debug\netstandard2.0\Archipelago.MultiClient.Net.dll
-
-
-
- ..\Archipelago.MultiClient.Net\bin\Release\netstandard2.0\Archipelago.MultiClient.Net.dll
+ ..\Archipelago.MultiClient.Net\bin\$(Configuration)\netstandard2.0\Archipelago.MultiClient.Net.dll
diff --git a/Archipelago.MultiClient.Net.Tests/DataStorageWrapperFixture.cs b/Archipelago.MultiClient.Net.Tests/DataStorageWrapperFixture.cs
index e8b743d..da50d06 100644
--- a/Archipelago.MultiClient.Net.Tests/DataStorageWrapperFixture.cs
+++ b/Archipelago.MultiClient.Net.Tests/DataStorageWrapperFixture.cs
@@ -2,6 +2,7 @@
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NSubstitute;
using NUnit.Framework;
@@ -321,6 +322,60 @@ public void GetSlotData_should_return_slot_data_for_current_player_slot()
Assert.That(slotData["Two"], Is.EqualTo(2));
}
+ private class CustomSlotDataModel
+ {
+ public class Options
+ {
+ public bool IsXRandomized { get; set; }
+ public bool IsYRandomized { get; set; }
+ }
+ public int One { get; set; }
+ public long Two { get; set; }
+ public uint? Three { get; set; }
+ [JsonProperty("ListOfStuff")]
+ public List Strings { get; set; }
+ public Options SlotOptions { get; set; }
+ }
+ [Test]
+ public void GetSlotData_should_deserialize_custom_type_for_current_player_slot()
+ {
+ var socket = Substitute.For();
+ var connectionInfo = Substitute.For();
+ connectionInfo.Slot.Returns(4);
+
+ CustomSlotDataModel slotData = null;
+
+ var sut = new DataStorageHelper(socket, connectionInfo);
+
+ var serverSlotData = new Dictionary
+ {
+ { "One", 1 },
+ { "Two", 2 },
+ { "ListOfStuff", new string[] { "A", "B", "C" } },
+ { "SlotOptions", new CustomSlotDataModel.Options
+ {
+ IsXRandomized = true,
+ IsYRandomized = false
+ } }
+ };
+
+ ExecuteAsyncWithDelay(
+ () => { slotData = sut.GetSlotData(); },
+ () => RaiseRetrieved(socket, "_read_slot_data_4", JObject.FromObject(serverSlotData)));
+
+ socket.Received().SendPacketAsync(Arg.Is(p => p.Keys.FirstOrDefault() == "_read_slot_data_4"));
+
+ Assert.IsNotNull(slotData);
+
+ Assert.That(slotData.One, Is.EqualTo(1));
+ Assert.That(slotData.Two, Is.EqualTo(2));
+ Assert.That(slotData.Three, Is.Null);
+ Assert.That(slotData.Strings, Is.EquivalentTo(new List { "A", "B", "C" }));
+ Assert.That(slotData.SlotOptions.IsXRandomized, Is.True);
+ Assert.That(slotData.SlotOptions.IsYRandomized, Is.False);
+
+ }
+
[Test]
public void GetSlotData_should_return_null_for_non_existing_player_slot()
{
diff --git a/Archipelago.MultiClient.Net/Helpers/DataStorageWrappers.cs b/Archipelago.MultiClient.Net/Helpers/DataStorageWrappers.cs
index edff89c..42547d8 100644
--- a/Archipelago.MultiClient.Net/Helpers/DataStorageWrappers.cs
+++ b/Archipelago.MultiClient.Net/Helpers/DataStorageWrappers.cs
@@ -58,6 +58,14 @@ void TrackHints(Action onHintsUpdated,
/// the slot id of the player to request slot data for, defaults to the current player's slot if left empty
/// An Dictionary with string keys, and custom defined values, the keys and values differ per game
Dictionary GetSlotData(int? slot = null);
+
+ ///
+ /// Retrieves the custom slot data for the specified slot
+ ///
+ /// The type to convert the slot data to
+ /// The slot ID of the player ot request slot data for, defaults to the current player's slot if left empty
+ /// The slot data, converted to a modeled object of the specified type
+ T GetSlotData(int? slot = null) where T : class;
#if NET35
///
@@ -67,6 +75,14 @@ void TrackHints(Action onHintsUpdated,
/// the slot id of the player to request slot data for, defaults to the current player's slot if left empty
/// An Dictionary with string keys, and custom defined values, the keys and values differ per game
void GetSlotDataAsync(Action> onSlotDataRetrieved, int? slot = null);
+ ///
+ /// Retrieves the custom slot data for the specified slot
+ ///
+ /// The type to convert the slot data to
+ /// the method to call with the retrieved slot data
+ /// the slot id of the player to request slot data for, defaults to the current player's slot if left empty
+ /// The slot data, converted to a modeled object of the specified type
+ void GetSlotDataAsync(Action onSlotDataRetrieved, int? slot = null) where T : class;
#else
///
/// Retrieves the custom slot data for the specified slot
@@ -74,6 +90,13 @@ void TrackHints(Action onHintsUpdated,
/// the slot id of the player to request slot data for, defaults to the current player's slot if left empty
/// An Dictionary with string keys, and custom defined values, the keys and values differ per game
Task> GetSlotDataAsync(int? slot = null);
+ ///
+ /// Retrieves the custom slot data for the specified slot
+ ///
+ /// The type to convert the slot data to
+ /// the slot id of the player to request slot data for, defaults to the current player's slot if left empty
+ /// The slot data, converted to a modeled object of the specified type
+ Task GetSlotDataAsync(int? slot = null) where T : class;
#endif
///
@@ -203,16 +226,25 @@ public void TrackHints(Action onHintsUpdated,
}
///
- public Dictionary GetSlotData(int? slot = null) =>
- GetSlotDataElement(slot).To>();
+ public Dictionary GetSlotData(int? slot = null) =>
+ GetSlotData>(slot);
+ ///
+ public T GetSlotData(int? slot = null) where T : class =>
+ GetSlotDataElement(slot).To();
#if NET35
///
public void GetSlotDataAsync(Action> onSlotDataRetrieved, int? slot = null) =>
GetSlotDataElement(slot).GetAsync(t => onSlotDataRetrieved(t?.ToObject>()));
+ ///
+ public void GetSlotDataAsync(Action onSlotDataRetrieved, int? slot = null) where T : class =>
+ GetSlotDataElement(slot).GetAsync(t => onSlotDataRetrieved(t?.ToObject()));
#else
///
public Task> GetSlotDataAsync(int? slot = null) =>
- GetSlotDataElement(slot).GetAsync>();
+ GetSlotDataAsync>(slot);
+ ///
+ public Task GetSlotDataAsync(int? slot = null) where T : class =>
+ GetSlotDataElement(slot).GetAsync();
#endif
///