Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Space station raw endpoint mapping #128

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/Helldivers-2-API/Controllers/ArrowHeadController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,17 @@ public static async Task<IResult> Assignments(HttpContext context, ArrowHeadStor

return Results.Bytes(assignments, contentType: "application/json");
}

/// <summary>
/// Fetches THE specific <see cref="SpaceStation" /> (749875195).
/// </summary>
[ProducesResponseType<List<Assignment>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
public static async Task<IResult> SpaceStation(HttpContext context, ArrowHeadStore store)
{
// TODO extract ID from route
var spaceStation = await store.GetSpaceStations(749875195, context.RequestAborted);

return Results.Bytes(spaceStation, contentType: "application/json");
}
}
1 change: 1 addition & 0 deletions src/Helldivers-2-API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
raw.MapGet("/api/Stats/war/801/summary", ArrowHeadController.Summary);
raw.MapGet("/api/NewsFeed/801", ArrowHeadController.NewsFeed);
raw.MapGet("/api/v2/Assignment/War/801", ArrowHeadController.Assignments);
raw.MapGet("/api/v2/SpaceStation/War/801/749875195", ArrowHeadController.SpaceStation);

#endregion

Expand Down
6 changes: 5 additions & 1 deletion src/Helldivers-2-Core/Mapping/MappingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public sealed class MappingContext
/// <summary>The <see cref="Assignment" />s currently being mapped.</summary>
public Dictionary<string, List<Assignment>> Assignments { get; private init; }

/// <summary>The <see cref="SpaceStation" />s currently being mapped.</summary>
public Dictionary<string, List<SpaceStation>> SpaceStations { get; private init; }

/// <summary>
/// A <see cref="DateTime" /> that represents the 'start' of the time in Helldivers 2.
/// This accounts for the <see cref="Models.ArrowHead.WarInfo.StartDate" /> and <see cref="GameTimeDeviation" />.
Expand All @@ -44,14 +47,15 @@ public sealed class MappingContext
public TimeSpan GameTimeDeviation { get; private init; }

/// <summary>Initializes a new <see cref="MappingContext" />.</summary>
internal MappingContext(WarId warId, WarInfo warInfo, Dictionary<string, WarStatus> warStatuses, WarSummary warSummary, Dictionary<string, List<NewsFeedItem>> newsFeeds, Dictionary<string, List<Assignment>> assignments)
internal MappingContext(WarId warId, WarInfo warInfo, Dictionary<string, WarStatus> warStatuses, WarSummary warSummary, Dictionary<string, List<NewsFeedItem>> newsFeeds, Dictionary<string, List<Assignment>> assignments, Dictionary<string, List<SpaceStation>> spaceStations)
{
WarId = warId;
WarInfo = warInfo;
WarStatuses = warStatuses;
WarSummary = warSummary;
NewsFeeds = newsFeeds;
Assignments = assignments;
SpaceStations = spaceStations;

InvariantWarStatus = warStatuses.FirstOrDefault().Value
?? throw new InvalidOperationException("No warstatus available");
Expand Down
2 changes: 1 addition & 1 deletion src/Helldivers-2-Core/Mapping/V1/SpaceStationMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public IEnumerable<SpaceStation> MapToV1(MappingContext context, List<Planet> pl
yield return Map(context, station, planets);
}

private SpaceStation Map(MappingContext context, Helldivers.Models.ArrowHead.Status.SpaceStation raw, List<Planet> planets)
private SpaceStation Map(MappingContext context, Helldivers.Models.ArrowHead.SpaceStation raw, List<Planet> planets)
{
var planet = planets.First(p => p.Index == raw.PlanetIndex);

Expand Down
16 changes: 15 additions & 1 deletion src/Helldivers-2-Core/Storage/ArrowHead/ArrowHeadStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public sealed class ArrowHeadStore
private CultureDictionary<Memory<byte>> _statuses = null!;
private CultureDictionary<Memory<byte>> _feeds = null!;
private CultureDictionary<Memory<byte>> _assignments = null!;
private CultureDictionary<Memory<byte>> _spaceStations = null!;
private readonly TaskCompletionSource _syncState = new();

/// <summary>
Expand All @@ -25,7 +26,8 @@ public void UpdateRawStore(
Memory<byte> warSummary,
IEnumerable<KeyValuePair<string, Memory<byte>>> statuses,
IEnumerable<KeyValuePair<string, Memory<byte>>> feeds,
IEnumerable<KeyValuePair<string, Memory<byte>>> assignments
IEnumerable<KeyValuePair<string, Memory<byte>>> assignments,
IEnumerable<KeyValuePair<string, Memory<byte>>> spaceStations
)
{
_warId = warId;
Expand All @@ -34,6 +36,7 @@ IEnumerable<KeyValuePair<string, Memory<byte>>> assignments
_statuses = new(statuses);
_feeds = new(feeds);
_assignments = new(assignments);
_spaceStations = new(spaceStations);

_syncState.TrySetResult();
}
Expand Down Expand Up @@ -97,4 +100,15 @@ public async Task<Memory<byte>> GetAssignments(CancellationToken cancellationTok

return _assignments.Get();
}

/// <summary>
/// returns the raw payload for <see cref="SpaceStation" />s.
/// </summary>
public async Task<Memory<byte>> GetSpaceStations(int id, CancellationToken cancellationToken)
{
await _syncState.Task.WaitAsync(cancellationToken);

// TODO use ID to get relevant space station
return _spaceStations.Get();
}
}
13 changes: 10 additions & 3 deletions src/Helldivers-2-Core/StorageFacade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ public ValueTask UpdateStores(SteamNewsFeed feed)
/// </summary>
public async ValueTask UpdateStores(Memory<byte> rawWarId, Memory<byte> rawWarInfo,
Dictionary<string, Memory<byte>> rawWarStatuses, Memory<byte> rawWarSummary,
Dictionary<string, Memory<byte>> rawNewsFeeds, Dictionary<string, Memory<byte>> rawAssignments)
Dictionary<string, Memory<byte>> rawNewsFeeds, Dictionary<string, Memory<byte>> rawAssignments,
Dictionary<string, Memory<byte>> rawStations)
{
arrowHead.UpdateRawStore(
rawWarId,
rawWarInfo,
rawWarSummary,
rawWarStatuses,
rawNewsFeeds,
rawAssignments
rawAssignments,
rawStations
);

var warId = DeserializeOrThrow(rawWarId, ArrowHeadSerializerContext.Default.WarId);
Expand All @@ -51,14 +53,19 @@ public async ValueTask UpdateStores(Memory<byte> rawWarId, Memory<byte> rawWarIn
pair => pair.Key,
pair => DeserializeOrThrow(pair.Value, ArrowHeadSerializerContext.Default.ListAssignment)
);
var spaceStations = rawAssignments.ToDictionary(
pair => pair.Key,
pair => DeserializeOrThrow(pair.Value, ArrowHeadSerializerContext.Default.ListSpaceStation)
);

var context = new MappingContext(
warId,
warInfo,
warStatuses,
warSummary,
newsFeeds,
assignments
assignments,
spaceStations
);

await v1.UpdateStores(context);
Expand Down
25 changes: 25 additions & 0 deletions src/Helldivers-2-Models/ArrowHead/SpaceStation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Helldivers.Models.ArrowHead.SpaceStations;

namespace Helldivers.Models.ArrowHead;

/// <summary>
/// Represents an assignment given from Super Earth to the Helldivers.
/// </summary>
/// <param name="Id32">The unique identifier of the station.</param>
/// <param name="PlanetIndex">The id of the planet it's currently orbiting</param>
/// <param name="LastElectionId">The id of the previous planet election.</param>
/// <param name="CurrentElectionId">The id of the current planet election.</param>
/// <param name="NextElectionId">The id of the next planet election.</param>
/// <param name="CurrentElectionEndWarTime">When the election for the next planet will end (in seconds relative to game start).</param>
/// <param name="Flags">A set of flags, purpose currently unknown.</param>
/// <param name="TacticalActions">The list of actions the space station crew can perform.</param>
public sealed record SpaceStation(
long Id32,
int PlanetIndex,
string LastElectionId,
string CurrentElectionId,
string NextElectionId,
ulong CurrentElectionEndWarTime,
int Flags,
List<TacticalAction> TacticalActions
);
21 changes: 21 additions & 0 deletions src/Helldivers-2-Models/ArrowHead/SpaceStations/Cost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Helldivers.Models.ArrowHead.SpaceStations;

/// <summary>
/// Represents the "Cost" of a tactical action
/// </summary>
/// <param name="Id"></param>
/// <param name="ItemMixId"></param>
/// <param name="TargetValue"></param>
/// <param name="CurrentValue"></param>
/// <param name="DeltaPerSecond"></param>
/// <param name="MaxDonationAmmount"></param>
/// <param name="MaxDonationPeriodSeconds"></param>
public sealed record Cost(
string Id,
long ItemMixId,
int TargetValue,
int CurrentValue,
int DeltaPerSecond,
int MaxDonationAmmount,
int MaxDonationPeriodSeconds
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Helldivers.Models.ArrowHead.SpaceStations;

/// <summary>
/// Represents information of a space station from the 'SpaceStation' endpoint returned by ArrowHead's API.
/// </summary>
/// <param name="Id32"></param>
/// <param name="MediaId32"></param>
/// <param name="Name"></param>
/// <param name="Description"></param>
/// <param name="StrategicDescription"></param>
/// <param name="Status"></param>
/// <param name="StatusExpireAtWarTimeSeconds"></param>
/// <param name="Cost"></param>
/// <param name="EffectIds"></param>
/// <param name="ActiveEffectIds"></param>
public sealed record TacticalAction(
long Id32,
long MediaId32,
string Name,
string Description,
string StrategicDescription,
int Status,
int StatusExpireAtWarTimeSeconds,
List<Cost> Cost,
List<int> EffectIds,
List<int> ActiveEffectIds
);
1 change: 1 addition & 0 deletions src/Helldivers-2-Models/ArrowHeadSerializerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Helldivers.Models;
[JsonSerializable(typeof(NewsFeedItem))]
[JsonSerializable(typeof(WarSummary))]
[JsonSerializable(typeof(List<Assignment>))]
[JsonSerializable(typeof(List<SpaceStation>))]
[JsonSerializable(typeof(List<NewsFeedItem>))]
[JsonSourceGenerationOptions(PropertyNameCaseInsensitive = true)]
public sealed partial class ArrowHeadSerializerContext : JsonSerializerContext
Expand Down
10 changes: 9 additions & 1 deletion src/Helldivers-2-Sync/Hosted/ArrowHeadSyncService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ private async Task SynchronizeAsync(IServiceProvider services, CancellationToken
cancellationToken
);

// For each language, load space stations
var spaceStations = await DownloadTranslations<SpaceStation>(
// TODO extract station id's from war status
async language => await api.LoadSpaceStations(season, "749875195", language, cancellationToken),
cancellationToken
);

await storage.UpdateStores(
rawWarId,
warInfo,
statuses,
warSummary,
feeds,
assignments
assignments,
spaceStations
);
}

Expand Down
13 changes: 13 additions & 0 deletions src/Helldivers-2-Sync/Services/ArrowHeadApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ public async Task<Memory<byte>> LoadAssignments(string season, string language,
return await CollectStream(stream, cancellationToken);
}

/// <summary>
/// Loads space station of a given <paramref name="season" /> and <paramref name="id"/> in <paramref name="language" />.
/// </summary>
public async Task<Memory<byte>> LoadSpaceStations(string season, string id, string language,
CancellationToken cancellationToken)
{
var request = BuildRequest($"/api/SpaceStation/{season}/{id}", language);
using var response = await http.SendAsync(request, cancellationToken);
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);

return await CollectStream(stream, cancellationToken);
}

/// <summary>
/// Fetch <see cref="WarSummary" /> from ArrowHead's API.
/// </summary>
Expand Down