116 lines
4.0 KiB
C#
116 lines
4.0 KiB
C#
using NeonSprawl.Server.Game.Items;
|
|
using NeonSprawl.Server.Game.Mastery;
|
|
using NeonSprawl.Server.Game.PositionState;
|
|
using NeonSprawl.Server.Game.Quests;
|
|
using NeonSprawl.Server.Game.Rewards;
|
|
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, IQuestDefinitionRegistry questRegistry,
|
|
IPlayerQuestStateStore progressStore, IPlayerPerkStateStore perkStore,
|
|
IRewardDeliveryStore deliveryStore, TimeProvider timeProvider) =>
|
|
{
|
|
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,
|
|
questRegistry,
|
|
progressStore,
|
|
perkStore,
|
|
deliveryStore,
|
|
timeProvider);
|
|
|
|
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;
|
|
}
|
|
}
|