130 lines
5.0 KiB
C#
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;
|
|
}
|
|
}
|