neon-sprawl/server/NeonSprawl.Server/Game/Quests/QuestProgressApi.cs

108 lines
3.8 KiB
C#

using NeonSprawl.Server.Game.Items;
using NeonSprawl.Server.Game.PositionState;
namespace NeonSprawl.Server.Game.Quests;
/// <summary>Maps <c>GET /game/players/{{id}}/quest-progress</c> (NEO-119).</summary>
public static class QuestProgressApi
{
public const string StatusNotStarted = "not_started";
public const string StatusActive = "active";
public const string StatusCompleted = "completed";
public static WebApplication MapQuestProgressApi(this WebApplication app)
{
app.MapGet(
"/game/players/{id}/quest-progress",
(string id, IPositionStateStore positions, IQuestDefinitionRegistry questRegistry,
IPlayerQuestStateStore progressStore, IPlayerInventoryStore inventoryStore,
IItemDefinitionRegistry itemRegistry, TimeProvider timeProvider, ILogger<Program>? logger) =>
{
var trimmedId = id.Trim();
if (trimmedId.Length == 0 || !positions.TryGetPosition(trimmedId, out _))
{
return Results.NotFound();
}
QuestObjectiveWiring.TryRefreshInventoryProgressForPlayer(
trimmedId,
questRegistry,
progressStore,
inventoryStore,
itemRegistry,
timeProvider,
logger);
return Results.Json(BuildSnapshot(trimmedId, questRegistry, progressStore));
});
return app;
}
internal static QuestProgressListResponse BuildSnapshot(
string playerId,
IQuestDefinitionRegistry questRegistry,
IPlayerQuestStateStore progressStore)
{
var defs = questRegistry.GetDefinitionsInIdOrder();
var rows = new List<QuestProgressRowJson>(defs.Count);
foreach (var def in defs)
{
rows.Add(MapQuestProgressRow(playerId, def.Id, progressStore));
}
return new QuestProgressListResponse
{
PlayerId = playerId,
Quests = rows,
SchemaVersion = QuestProgressListResponse.CurrentSchemaVersion,
};
}
internal static QuestProgressRowJson MapQuestProgressRow(
string playerId,
string questId,
IPlayerQuestStateStore progressStore)
{
if (!progressStore.TryGetProgress(playerId, questId, out var snapshot))
{
return NotStartedRow(questId);
}
return MapQuestProgressRow(snapshot);
}
internal static QuestProgressRowJson MapQuestProgressRow(QuestStepState snapshot)
{
var counters = new Dictionary<string, int>(snapshot.ObjectiveCounters, StringComparer.Ordinal);
return snapshot.Status switch
{
QuestProgressStatus.Active => new QuestProgressRowJson
{
QuestId = snapshot.QuestId,
Status = StatusActive,
CurrentStepIndex = snapshot.CurrentStepIndex,
ObjectiveCounters = counters,
},
QuestProgressStatus.Completed => new QuestProgressRowJson
{
QuestId = snapshot.QuestId,
Status = StatusCompleted,
CurrentStepIndex = snapshot.CurrentStepIndex,
ObjectiveCounters = counters,
CompletedAt = snapshot.CompletedAt,
},
_ => throw new InvalidOperationException($"Unknown quest progress status '{snapshot.Status}'."),
};
}
private static QuestProgressRowJson NotStartedRow(string questId) =>
new()
{
QuestId = questId,
Status = StatusNotStarted,
CurrentStepIndex = 0,
ObjectiveCounters = new Dictionary<string, int>(StringComparer.Ordinal),
};
}