neon-sprawl/server/NeonSprawl.Server/Game/Interaction/InteractionApi.cs

130 lines
5.0 KiB
C#

using NeonSprawl.Server.Game.Gathering;
using NeonSprawl.Server.Game.Items;
using NeonSprawl.Server.Game.Mastery;
using NeonSprawl.Server.Game.PositionState;
using NeonSprawl.Server.Game.Quests;
using NeonSprawl.Server.Game.Skills;
using NeonSprawl.Server.Game.World;
namespace NeonSprawl.Server.Game.Interaction;
/// <summary>Maps <c>POST /game/players/{{id}}/interact</c> (NS-18).</summary>
public static class InteractionApi
{
public const string ReasonOutOfRange = "out_of_range";
public const string ReasonUnknownInteractable = "unknown_interactable";
public static WebApplication MapInteractionApi(this WebApplication app)
{
app.MapPost(
"/game/players/{id}/interact",
(string id, InteractionRequest? body, IPositionStateStore store,
IResourceNodeDefinitionRegistry nodeRegistry, IItemDefinitionRegistry itemRegistry,
IPlayerInventoryStore inventoryStore, ISkillDefinitionRegistry skillRegistry,
IPlayerSkillProgressionStore xpStore, ISkillLevelCurve levelCurve, PerkUnlockEngine perkUnlockEngine,
IResourceNodeInstanceStore nodeInstanceStore, IQuestDefinitionRegistry questRegistry,
IPlayerQuestStateStore progressStore, TimeProvider timeProvider) =>
{
if (body is null || body.SchemaVersion != InteractionRequest.CurrentSchemaVersion)
{
return Results.BadRequest();
}
var rawId = body.InteractableId;
if (rawId is null)
{
return Results.BadRequest();
}
var interactableKey = rawId.Trim();
if (interactableKey.Length == 0)
{
return Results.BadRequest();
}
var lookupKey = interactableKey.ToLowerInvariant();
var playerKey = id.Trim();
if (!store.TryGetPosition(playerKey, out var snap))
{
return Results.NotFound();
}
if (!PrototypeInteractableRegistry.TryGet(lookupKey, out var entry))
{
return Results.Json(
new InteractionResponse
{
SchemaVersion = InteractionResponse.CurrentSchemaVersion,
Allowed = false,
ReasonCode = ReasonUnknownInteractable,
});
}
if (!HorizontalReach.IsWithinHorizontalRadius(
snap.X,
snap.Z,
entry.X,
entry.Z,
entry.InteractionRadius))
{
return Results.Json(
new InteractionResponse
{
SchemaVersion = InteractionResponse.CurrentSchemaVersion,
Allowed = false,
ReasonCode = ReasonOutOfRange,
});
}
if (string.Equals(entry.Kind, PrototypeInteractableRegistry.ResourceNodeKind, StringComparison.Ordinal))
{
var gather = GatherOperations.TryGather(
playerKey,
lookupKey,
nodeRegistry,
itemRegistry,
inventoryStore,
skillRegistry,
xpStore,
levelCurve,
perkUnlockEngine,
nodeInstanceStore,
questRegistry,
progressStore,
timeProvider);
if (!gather.Success)
{
return Results.Json(
new InteractionResponse
{
SchemaVersion = InteractionResponse.CurrentSchemaVersion,
Allowed = false,
ReasonCode = gather.ReasonCode,
});
}
return Results.Json(
new InteractionResponse
{
SchemaVersion = InteractionResponse.CurrentSchemaVersion,
Allowed = true,
InteractableId = lookupKey,
Payload = new InteractionPlaceholderPayload(),
});
}
return Results.Json(
new InteractionResponse
{
SchemaVersion = InteractionResponse.CurrentSchemaVersion,
Allowed = true,
InteractableId = lookupKey,
Payload = new InteractionPlaceholderPayload(),
});
});
return app;
}
}