feat(practice): serve default/trial/leader-skin lists on practice/deck_list

practice/deck_list returns the same wire shape as /deck/info (the client parses
both via DeckGroupListData), but only ever sent user decks — so a fresh account
saw no default decks and couldn't start a practice match.

Extract the /deck/info hydration into a shared IDeckListBuilder used by
/deck/info, /deck/my_list, and /practice/deck_list. Practice passes
padEmptySlots:false (deck *select*, not builder) — matches the prod practice
capture, which returns real decks unpadded plus the 8 per-class default decks
and per-class leader-skin settings. Retire the near-duplicate
PracticeDeckListResponse DTO in favor of the shared DeckListResponse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-29 12:01:36 -04:00
parent 1e53748ae3
commit 2d675aa35d
6 changed files with 203 additions and 158 deletions

View File

@@ -1,25 +0,0 @@
using MessagePack;
using System.Text.Json.Serialization;
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.Practice;
/// <summary>
/// Same shape consumed by DeckGroupListData(jsonData, Format.All). Per-format keys are
/// conditional 窶・omit (don't send empty arrays) for formats the server doesn't enable.
/// </summary>
[MessagePackObject]
public class PracticeDeckListResponse
{
/// <summary>Card ids currently disabled for maintenance (client unions with global list).</summary>
[JsonPropertyName("maintenance_card_list")]
[Key("maintenance_card_list")] public List<long> MaintenanceCardList { get; set; } = new();
[JsonPropertyName("user_deck_rotation")]
[Key("user_deck_rotation")] public List<UserDeck>? UserDeckRotation { get; set; }
[JsonPropertyName("user_deck_unlimited")]
[Key("user_deck_unlimited")] public List<UserDeck>? UserDeckUnlimited { get; set; }
// The remaining format keys (pre_rotation, crossover, my_rotation, avatar, default_deck_list,
// trial_deck_list, crossover_trial_deck_list, build_deck_list, user_leader_skin_setting_list)
// are all conditional 窶・added when those formats are enabled.
}