using System.Text.Json.Serialization; namespace NeonSprawl.Server.Game.Skills; /// POST body for applying one skill XP grant (NEO-38). public sealed class SkillProgressionGrantRequest { public const int CurrentSchemaVersion = 1; [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; init; } [JsonPropertyName("skillId")] public required string SkillId { get; init; } [JsonPropertyName("amount")] public int Amount { get; init; } /// Validated against target skill's allowedXpSourceKinds (ordinal ignore-case). [JsonPropertyName("sourceKind")] public required string SourceKind { get; init; } } /// POST responses for progression grants — success () or structured deny (). public sealed class SkillProgressionGrantResponse { public const int CurrentSchemaVersion = 1; [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; init; } = CurrentSchemaVersion; [JsonPropertyName("granted")] public bool Granted { get; init; } /// Set when is false; stable snake_case values (see README). [JsonPropertyName("reasonCode")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? ReasonCode { get; init; } [JsonPropertyName("progression")] public required SkillProgressionSnapshotResponse Progression { get; init; } /// Present on success only; empty array when XP changed but level did not. [JsonPropertyName("levelUps")] public required IReadOnlyList LevelUps { get; init; } } /// One skill crossed a level boundary on this grant (previousLevel < newLevel). public sealed class SkillLevelUpJson { [JsonPropertyName("skillId")] public required string SkillId { get; init; } [JsonPropertyName("previousLevel")] public int PreviousLevel { get; init; } [JsonPropertyName("newLevel")] public int NewLevel { get; init; } }