neon-sprawl/server/NeonSprawl.Server/Game/Crafting/PlayerCraftApi.cs

107 lines
3.5 KiB
C#

using NeonSprawl.Server.Game.Items;
using NeonSprawl.Server.Game.Mastery;
using NeonSprawl.Server.Game.PositionState;
using NeonSprawl.Server.Game.Skills;
namespace NeonSprawl.Server.Game.Crafting;
/// <summary>Maps <c>POST /game/players/{{id}}/craft</c> — craft execution (NEO-70).</summary>
public static class PlayerCraftApi
{
public static WebApplication MapPlayerCraftApi(this WebApplication app)
{
app.MapPost(
"/game/players/{id}/craft",
(string id, PlayerCraftRequest? body, IPositionStateStore positions,
IRecipeDefinitionRegistry recipeRegistry, IItemDefinitionRegistry itemRegistry,
IPlayerInventoryStore inventoryStore, ISkillDefinitionRegistry skillRegistry,
IPlayerSkillProgressionStore xpStore, ISkillLevelCurve levelCurve,
PerkUnlockEngine perkUnlockEngine) =>
{
if (body is null || body.SchemaVersion != PlayerCraftRequest.CurrentSchemaVersion)
{
return Results.BadRequest();
}
if (body.RecipeId is null || body.RecipeId.Trim().Length == 0)
{
return Results.BadRequest();
}
var trimmedId = id.Trim();
if (trimmedId.Length == 0 || !positions.TryGetPosition(trimmedId, out _))
{
return Results.NotFound();
}
var quantity = body.Quantity ?? 1;
var result = CraftOperations.TryCraft(
trimmedId,
body.RecipeId,
quantity,
recipeRegistry,
itemRegistry,
inventoryStore,
skillRegistry,
xpStore,
levelCurve,
perkUnlockEngine);
if (!result.Success &&
(string.Equals(result.ReasonCode, CraftReasonCodes.InventoryStoreMissing, StringComparison.Ordinal) ||
string.Equals(result.ReasonCode, CraftReasonCodes.ProgressionStoreMissing, StringComparison.Ordinal)))
{
return Results.NotFound();
}
return Results.Json(MapResponse(result));
});
return app;
}
internal static CraftResponse MapResponse(CraftResult result)
{
CraftXpGrantSummaryJson? xp = null;
if (result.XpGrantSummary is { } summary)
{
xp = new CraftXpGrantSummaryJson
{
SkillId = summary.SkillId,
Amount = summary.Amount,
SourceKind = summary.SourceKind,
};
}
return new CraftResponse
{
Success = result.Success,
ReasonCode = result.ReasonCode,
InputsConsumed = MapIoRows(result.InputsConsumed),
OutputsGranted = MapIoRows(result.OutputsGranted),
XpGrantSummary = xp,
};
}
private static IReadOnlyList<CraftIoAppliedJson> MapIoRows(IReadOnlyList<CraftIoApplied> rows)
{
if (rows.Count == 0)
{
return Array.Empty<CraftIoAppliedJson>();
}
var mapped = new CraftIoAppliedJson[rows.Count];
for (var i = 0; i < rows.Count; i++)
{
var row = rows[i];
mapped[i] = new CraftIoAppliedJson
{
ItemId = row.ItemId,
Quantity = row.Quantity,
};
}
return mapped;
}
}