Skip to content

Commit

Permalink
Merge pull request #98 from BadMagic100/datastorage-custom-deser
Browse files Browse the repository at this point in the history
Add generic overload for GetSlotData in DataStorageWrapper
  • Loading branch information
Jarno458 authored Jul 31, 2024
2 parents 5ce1ee4 + 4cc1669 commit f0fe1fa
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,63 +22,35 @@
<Reference Include="Newtonsoft.Json">
<HintPath>..\DLLs\net35\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net471' AND '$(Configuration)' == 'Debug'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Debug\net35\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net471' AND '$(Configuration)' == 'Release'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Release\net35\Archipelago.MultiClient.Net.dll</HintPath>
<HintPath>..\Archipelago.MultiClient.Net\bin\$(Configuration)\net35\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<Reference Include="Newtonsoft.Json">
<HintPath>..\DLLs\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472' AND '$(Configuration)' == 'Debug'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Debug\net40\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472' AND '$(Configuration)' == 'Release'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Release\net40\Archipelago.MultiClient.Net.dll</HintPath>
<HintPath>..\Archipelago.MultiClient.Net\bin\$(Configuration)\net40\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net47'">
<Reference Include="Newtonsoft.Json">
<HintPath>..\DLLs\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net47' AND '$(Configuration)' == 'Debug'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Debug\net45\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net47' AND '$(Configuration)' == 'Release'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Release\net45\Archipelago.MultiClient.Net.dll</HintPath>
<HintPath>..\Archipelago.MultiClient.Net\bin\$(Configuration)\net45\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
<Reference Include="Newtonsoft.Json">
<HintPath>..\DLLs\netstandard2.0\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net48' AND '$(Configuration)' == 'Debug'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Debug\netstandard2.0\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net48' AND '$(Configuration)' == 'Release'">
<Reference Include="Archipelago.MultiClient.Net">
<HintPath>..\Archipelago.MultiClient.Net\bin\Release\netstandard2.0\Archipelago.MultiClient.Net.dll</HintPath>
<HintPath>..\Archipelago.MultiClient.Net\bin\$(Configuration)\netstandard2.0\Archipelago.MultiClient.Net.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
55 changes: 55 additions & 0 deletions Archipelago.MultiClient.Net.Tests/DataStorageWrapperFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<string> Strings { get; set; }
public Options SlotOptions { get; set; }
}
[Test]
public void GetSlotData_should_deserialize_custom_type_for_current_player_slot()
{
var socket = Substitute.For<IArchipelagoSocketHelper>();
var connectionInfo = Substitute.For<IConnectionInfoProvider>();
connectionInfo.Slot.Returns(4);

CustomSlotDataModel slotData = null;

var sut = new DataStorageHelper(socket, connectionInfo);

var serverSlotData = new Dictionary<string, object>
{
{ "One", 1 },
{ "Two", 2 },
{ "ListOfStuff", new string[] { "A", "B", "C" } },
{ "SlotOptions", new CustomSlotDataModel.Options
{
IsXRandomized = true,
IsYRandomized = false
} }
};

ExecuteAsyncWithDelay(
() => { slotData = sut.GetSlotData<CustomSlotDataModel>(); },
() => RaiseRetrieved(socket, "_read_slot_data_4", JObject.FromObject(serverSlotData)));

socket.Received().SendPacketAsync(Arg.Is<GetPacket>(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<string> { "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()
{
Expand Down
38 changes: 35 additions & 3 deletions Archipelago.MultiClient.Net/Helpers/DataStorageWrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ void TrackHints(Action<Hint[]> onHintsUpdated,
/// <param name="slot">the slot id of the player to request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>An Dictionary with string keys, and custom defined values, the keys and values differ per game</returns>
Dictionary<string, object> GetSlotData(int? slot = null);

/// <summary>
/// Retrieves the custom slot data for the specified slot
/// </summary>
/// <typeparam name="T">The type to convert the slot data to</typeparam>
/// <param name="slot">The slot ID of the player ot request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>The slot data, converted to a modeled object of the specified type</returns>
T GetSlotData<T>(int? slot = null) where T : class;

#if NET35
/// <summary>
Expand All @@ -67,13 +75,28 @@ void TrackHints(Action<Hint[]> onHintsUpdated,
/// <param name="slot">the slot id of the player to request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>An Dictionary with string keys, and custom defined values, the keys and values differ per game</returns>
void GetSlotDataAsync(Action<Dictionary<string, object>> onSlotDataRetrieved, int? slot = null);
/// <summary>
/// Retrieves the custom slot data for the specified slot
/// </summary>
/// <typeparam name="T">The type to convert the slot data to</typeparam>
/// <param name="onSlotDataRetrieved">the method to call with the retrieved slot data</param>
/// <param name="slot">the slot id of the player to request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>The slot data, converted to a modeled object of the specified type</returns>
void GetSlotDataAsync<T>(Action<T> onSlotDataRetrieved, int? slot = null) where T : class;
#else
/// <summary>
/// Retrieves the custom slot data for the specified slot
/// </summary>
/// <param name="slot">the slot id of the player to request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>An Dictionary with string keys, and custom defined values, the keys and values differ per game</returns>
Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null);
/// <summary>
/// Retrieves the custom slot data for the specified slot
/// </summary>
/// <typeparam name="T">The type to convert the slot data to</typeparam>
/// <param name="slot">the slot id of the player to request slot data for, defaults to the current player's slot if left empty</param>
/// <returns>The slot data, converted to a modeled object of the specified type</returns>
Task<T> GetSlotDataAsync<T>(int? slot = null) where T : class;
#endif

/// <summary>
Expand Down Expand Up @@ -203,16 +226,25 @@ public void TrackHints(Action<Hint[]> onHintsUpdated,
}

/// <inheritdoc />
public Dictionary<string, object> GetSlotData(int? slot = null) =>
GetSlotDataElement(slot).To<Dictionary<string, object>>();
public Dictionary<string, object> GetSlotData(int? slot = null) =>
GetSlotData<Dictionary<string, object>>(slot);
/// <inheritdoc/>
public T GetSlotData<T>(int? slot = null) where T : class =>
GetSlotDataElement(slot).To<T>();
#if NET35
/// <inheritdoc />
public void GetSlotDataAsync(Action<Dictionary<string, object>> onSlotDataRetrieved, int? slot = null) =>
GetSlotDataElement(slot).GetAsync(t => onSlotDataRetrieved(t?.ToObject<Dictionary<string, object>>()));
/// <inheritdoc/>
public void GetSlotDataAsync<T>(Action<T> onSlotDataRetrieved, int? slot = null) where T : class =>
GetSlotDataElement(slot).GetAsync(t => onSlotDataRetrieved(t?.ToObject<T>()));
#else
/// <inheritdoc />
public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null) =>
GetSlotDataElement(slot).GetAsync<Dictionary<string, object>>();
GetSlotDataAsync<Dictionary<string, object>>(slot);
/// <inheritdoc/>
public Task<T> GetSlotDataAsync<T>(int? slot = null) where T : class =>
GetSlotDataElement(slot).GetAsync<T>();
#endif

/// <inheritdoc />
Expand Down

0 comments on commit f0fe1fa

Please sign in to comment.