using MessagePack; namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses; /// /// Wire-shape mirrors production's /check/game_start response. Several fields here are /// NOT read by Cute/GameStartCheckTask.Parse (now_viewer_id, now_name, /// now_rank — those are consumed by sibling tasks); they're included because prod sends /// them and the boot worked when we matched prod exactly. Removing them is a regression risk /// even though the parse-time decompile says they're unused. /// [MessagePackObject] public class GameStartResponse { /// The signed-in viewer's internal id. Prod always sends. [Key("now_viewer_id")] public long NowViewerId { get; set; } /// /// Whether the user has set a data-transfer password. Prod sends a non-null bool; /// GameStartCheckTask.Parse gates the read with Keys.Contains. /// [Key("is_set_transition_password")] public bool IsSetTransitionPassword { get; set; } /// Viewer display name. Not read by GameStartCheckTask but sent by prod. [Key("now_name")] public string NowName { get; set; } = string.Empty; /// /// Per-format rank-name map keyed by deck-format id ("1", "2", "4" observed in prod). /// Stub for now until rank state is persisted; pinned to RankName_010 / RankName_017 /// (matches prod's shape). /// [Key("now_rank")] public Dictionary NowRank { get; set; } = new(); /// /// Tutorial progress — **sent as a string on the wire** ("100" = tutorial complete). /// GameStartCheckTask.Parse calls .ToInt() so LitJson coerces. /// [Key("now_tutorial_step")] public string NowTutorialStep { get; set; } = "100"; /// /// Linked social accounts. Per-entry shape in . /// [Key("transition_account_data")] public List TransitionAccountData { get; set; } = new(); // INTENTIONALLY OMITTED: `rewrite_viewer_id` and `account_delete_reservation_status`. // Both are presence-checked by the client via `Keys.Contains(...)` + `.ToInt()` with no // null guard. MessagePack-CSharp writes [Key] properties unconditionally (null → Nil), // and the System.Text.Json `WhenWritingNull` ignore only affects the plain-JSON path. // So including these as nullable properties is a guaranteed NRE on the encrypted client // path. We don't need them — the client tolerates their absence — so don't declare them. // Re-add only if we have a real value to send. // --- Agreement / consent state (all required) --- /// PlayerStaticData.AgreementState enum. [Key("tos_state")] public int TosState { get; set; } /// PlayerStaticData.AgreementState enum. [Key("policy_state")] public int PolicyState { get; set; } /// PlayerStaticData.AgreementState enum. [Key("kor_authority_state")] public int KorAuthorityState { get; set; } /// Current Terms of Service document id. [Key("tos_id")] public int TosId { get; set; } /// Current Privacy Policy document id. [Key("policy_id")] public int PolicyId { get; set; } /// Current Korean authority consent document id. [Key("kor_authority_id")] public int KorAuthorityId { get; set; } }