81 lines
2.7 KiB
C#
81 lines
2.7 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace NeonSprawl.Server.Game.AbilityInput;
|
|
|
|
/// <summary>Canonical hotbar loadout payload returned by loadout APIs (NEO-29).</summary>
|
|
public sealed class HotbarLoadoutResponse
|
|
{
|
|
public const int CurrentSchemaVersion = 1;
|
|
public const int SlotCountV1 = 8;
|
|
|
|
[JsonPropertyName("schemaVersion")]
|
|
public int SchemaVersion { get; init; } = CurrentSchemaVersion;
|
|
|
|
[JsonPropertyName("playerId")]
|
|
public required string PlayerId { get; init; }
|
|
|
|
[JsonPropertyName("slotCount")]
|
|
public int SlotCount { get; init; } = SlotCountV1;
|
|
|
|
/// <summary>Always includes v1 slots 0..7 in ascending order.</summary>
|
|
[JsonPropertyName("slots")]
|
|
public required IReadOnlyList<HotbarSlotStateJson> Slots { get; init; }
|
|
}
|
|
|
|
/// <summary>POST body for hotbar loadout updates.</summary>
|
|
public sealed class HotbarLoadoutUpdateRequest
|
|
{
|
|
public const int CurrentSchemaVersion = 1;
|
|
|
|
[JsonPropertyName("schemaVersion")]
|
|
public int SchemaVersion { get; init; }
|
|
|
|
/// <summary>
|
|
/// Requested slot bindings to apply. Slot entries are upserts; unspecified slots keep previous values.
|
|
/// </summary>
|
|
[JsonPropertyName("slots")]
|
|
public IReadOnlyList<HotbarSlotBindingJson>? Slots { get; init; }
|
|
}
|
|
|
|
/// <summary>POST response for hotbar updates (applied or denied).</summary>
|
|
public sealed class HotbarLoadoutUpdateResponse
|
|
{
|
|
public const int CurrentSchemaVersion = 1;
|
|
|
|
[JsonPropertyName("schemaVersion")]
|
|
public int SchemaVersion { get; init; } = CurrentSchemaVersion;
|
|
|
|
[JsonPropertyName("updated")]
|
|
public bool Updated { get; init; }
|
|
|
|
[JsonPropertyName("loadout")]
|
|
public required HotbarLoadoutResponse Loadout { get; init; }
|
|
|
|
/// <summary>Required on deny responses; omitted when <see cref="Updated"/> is true.</summary>
|
|
[JsonPropertyName("reasonCode")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? ReasonCode { get; init; }
|
|
}
|
|
|
|
/// <summary>Wire shape for an individual slot state in GET/POST responses.</summary>
|
|
public sealed class HotbarSlotStateJson
|
|
{
|
|
[JsonPropertyName("slotIndex")]
|
|
public required int SlotIndex { get; init; }
|
|
|
|
/// <summary>Canonical lowercase ability id or null when the slot is unbound.</summary>
|
|
[JsonPropertyName("abilityId")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
public string? AbilityId { get; init; }
|
|
}
|
|
|
|
/// <summary>Wire shape for an individual slot update in POST requests.</summary>
|
|
public sealed class HotbarSlotBindingJson
|
|
{
|
|
[JsonPropertyName("slotIndex")]
|
|
public int SlotIndex { get; init; }
|
|
|
|
[JsonPropertyName("abilityId")]
|
|
public string? AbilityId { get; init; }
|
|
}
|