120 lines
4.3 KiB
C#
120 lines
4.3 KiB
C#
using NeonSprawl.Server.Game.Items;
|
|
using NeonSprawl.Server.Game.Mastery;
|
|
using NeonSprawl.Server.Game.PositionState;
|
|
using NeonSprawl.Server.Game.Rewards;
|
|
using NeonSprawl.Server.Game.Skills;
|
|
|
|
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, ISkillDefinitionRegistry skillRegistry,
|
|
IPlayerSkillProgressionStore skillProgressionStore, ISkillLevelCurve levelCurve,
|
|
PerkUnlockEngine perkUnlockEngine, IPlayerPerkStateStore perkStore,
|
|
IRewardDeliveryStore deliveryStore, 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,
|
|
skillRegistry,
|
|
skillProgressionStore,
|
|
levelCurve,
|
|
perkUnlockEngine,
|
|
perkStore,
|
|
deliveryStore,
|
|
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),
|
|
};
|
|
}
|