Puzzles
This commit is contained in:
@@ -6,9 +6,13 @@ namespace SVSim.EmulatedEntrypoint.Models.Dtos;
|
||||
/// <summary>
|
||||
/// basic_puzzle.is_display_badge — drives the "practice puzzle" badge on the
|
||||
/// footer. Read by MyPageTask.cs:177.
|
||||
///
|
||||
/// Named with the "Badge" suffix to avoid colliding with the
|
||||
/// <c>Models.Dtos.{Common,Requests,Responses}.BasicPuzzle</c> sub-namespaces
|
||||
/// that hold the /basic_puzzle/* endpoint DTOs.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class BasicPuzzle
|
||||
public class BasicPuzzleBadge
|
||||
{
|
||||
[JsonPropertyName("is_display_badge")]
|
||||
[Key("is_display_badge")]
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleEntryResponse
|
||||
{
|
||||
[JsonPropertyName("puzzle_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("puzzle_id")]
|
||||
public int PuzzleId { get; set; }
|
||||
|
||||
[JsonPropertyName("puzzle_difficulty")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("puzzle_difficulty")]
|
||||
public int PuzzleDifficulty { get; set; }
|
||||
|
||||
[JsonPropertyName("is_cleared")] [Key("is_cleared")]
|
||||
public bool IsCleared { get; set; }
|
||||
|
||||
[JsonPropertyName("is_additional")] [Key("is_additional")]
|
||||
public bool IsAdditional { get; set; }
|
||||
|
||||
[JsonPropertyName("is_playable")] [Key("is_playable")]
|
||||
public bool IsPlayable { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("release_condition_text_id")] [Key("release_condition_text_id")]
|
||||
public string ReleaseConditionTextId { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleGroupResponse
|
||||
{
|
||||
[JsonPropertyName("puzzle_master_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("puzzle_master_id")]
|
||||
public int PuzzleMasterId { get; set; }
|
||||
|
||||
[JsonPropertyName("puzzle_data")] [Key("puzzle_data")]
|
||||
public List<PuzzleEntryResponse> PuzzleData { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("puzzle_chara_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("puzzle_chara_id")]
|
||||
public int PuzzleCharaId { get; set; }
|
||||
|
||||
[JsonPropertyName("puzzle_difficulty_name_list")] [Key("puzzle_difficulty_name_list")]
|
||||
public Dictionary<string, string> PuzzleDifficultyNameList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("is_all_cleared")] [Key("is_all_cleared")]
|
||||
public bool IsAllCleared { get; set; }
|
||||
|
||||
[JsonPropertyName("chara_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("chara_id")]
|
||||
public int CharaId { get; set; }
|
||||
|
||||
[JsonPropertyName("sort_type")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("sort_type")]
|
||||
public int SortType { get; set; }
|
||||
|
||||
[JsonPropertyName("basic_title_text_id")] [Key("basic_title_text_id")]
|
||||
public string BasicTitleTextId { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("is_mission_target")] [Key("is_mission_target")]
|
||||
public bool IsMissionTarget { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
|
||||
/// <summary>Serializes int as a JSON string ("123"), deserializes from either form. Several
|
||||
/// /basic_puzzle/* fields use this on the wire (puzzle_master_id, total_count, reward_type, etc.).</summary>
|
||||
public sealed class StringifiedIntConverter : JsonConverter<int>
|
||||
{
|
||||
public override int Read(ref Utf8JsonReader r, Type _, JsonSerializerOptions __) =>
|
||||
r.TokenType switch
|
||||
{
|
||||
JsonTokenType.String when int.TryParse(r.GetString(), out var v) => v,
|
||||
JsonTokenType.Number => r.GetInt32(),
|
||||
_ => 0
|
||||
};
|
||||
public override void Write(Utf8JsonWriter w, int v, JsonSerializerOptions _) =>
|
||||
w.WriteStringValue(v.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Same for long. Reward ids fit in int but the client uses long internally.</summary>
|
||||
public sealed class StringifiedLongConverter : JsonConverter<long>
|
||||
{
|
||||
public override long Read(ref Utf8JsonReader r, Type _, JsonSerializerOptions __) =>
|
||||
r.TokenType switch
|
||||
{
|
||||
JsonTokenType.String when long.TryParse(r.GetString(), out var v) => v,
|
||||
JsonTokenType.Number => r.GetInt64(),
|
||||
_ => 0
|
||||
};
|
||||
public override void Write(Utf8JsonWriter w, long v, JsonSerializerOptions _) =>
|
||||
w.WriteStringValue(v.ToString());
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class FinishRequest : BaseRequest
|
||||
{
|
||||
[JsonPropertyName("puzzle_id")]
|
||||
[Key("puzzle_id")]
|
||||
public int PuzzleId { get; set; }
|
||||
|
||||
[JsonPropertyName("retry_count")]
|
||||
[Key("retry_count")]
|
||||
public int RetryCount { get; set; }
|
||||
|
||||
[JsonPropertyName("is_win")]
|
||||
[Key("is_win")]
|
||||
public bool IsWin { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class OpenPuzzleDialogRequest : BaseRequest
|
||||
{
|
||||
[JsonPropertyName("puzzle_master_id")]
|
||||
[Key("puzzle_master_id")]
|
||||
public int PuzzleMasterId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class StartRequest : BaseRequest
|
||||
{
|
||||
[JsonPropertyName("puzzle_id")]
|
||||
[Key("puzzle_id")]
|
||||
public int PuzzleId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common.BasicPuzzle;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class FinishResponse
|
||||
{
|
||||
[JsonPropertyName("add_point")] [Key("add_point")]
|
||||
public int? AddPoint { get; set; } = null;
|
||||
|
||||
/// <summary>STRING "1" on wins, NUMBER 0 on losses — both observed in prod. Per-call wire type
|
||||
/// quirk; controller writes the right one based on is_win.</summary>
|
||||
[JsonPropertyName("win_count")] [Key("win_count")]
|
||||
public object WinCount { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("class_experience")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("class_experience")]
|
||||
public int ClassExperience { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("class_level")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("class_level")]
|
||||
public int ClassLevel { get; set; } = 1;
|
||||
|
||||
[JsonPropertyName("achieved_info")] [Key("achieved_info")]
|
||||
public AchievedInfoResponse AchievedInfo { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("reward_list")] [Key("reward_list")]
|
||||
public List<TreasureRewardResponse> RewardList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("class_bonus_point")] [Key("class_bonus_point")]
|
||||
public int ClassBonusPoint { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("format_bonus_point")] [Key("format_bonus_point")]
|
||||
public int FormatBonusPoint { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("required_win_count_for_win_bonus_point")] [Key("required_win_count_for_win_bonus_point")]
|
||||
public int RequiredWinCountForWinBonusPoint { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("win_bonus_point")] [Key("win_bonus_point")]
|
||||
public int WinBonusPoint { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("win_bonus_point_status")] [Key("win_bonus_point_status")]
|
||||
public int WinBonusPointStatus { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("get_class_experience")] [Key("get_class_experience")]
|
||||
public int GetClassExperience { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("clear_mission_list")] [Key("clear_mission_list")]
|
||||
public ClearMissionListResponse ClearMissionList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("spot_point_data")] [Key("spot_point_data")]
|
||||
public SpotPointDataResponse SpotPointData { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("puzzle_list")] [Key("puzzle_list")]
|
||||
public List<PuzzleGroupResponse> PuzzleList { get; set; } = new();
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class AchievedInfoResponse
|
||||
{
|
||||
[JsonPropertyName("achieved_mission_list")] [Key("achieved_mission_list")]
|
||||
public List<PuzzleAchievedMissionEntry> AchievedMissionList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("achieved_mission_reward_list")] [Key("achieved_mission_reward_list")]
|
||||
public List<PuzzleAchievedMissionReward> AchievedMissionRewardList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("mission_start_data")] [Key("mission_start_data")]
|
||||
public List<MissionStartEntry> MissionStartData { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("battle_pass_reward_list")] [Key("battle_pass_reward_list")]
|
||||
public List<object> BattlePassRewardList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("battle_pass_message_list")] [Key("battle_pass_message_list")]
|
||||
public List<object> BattlePassMessageList { get; set; } = new();
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleAchievedMissionEntry
|
||||
{
|
||||
[JsonPropertyName("achieved_message")] [Key("achieved_message")]
|
||||
public string AchievedMessage { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleAchievedMissionReward
|
||||
{
|
||||
[JsonPropertyName("mission_reward_type")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("mission_reward_type")]
|
||||
public int MissionRewardType { get; set; }
|
||||
|
||||
[JsonPropertyName("mission_reward_detail_id")] [JsonConverter(typeof(StringifiedLongConverter))] [Key("mission_reward_detail_id")]
|
||||
public long MissionRewardDetailId { get; set; }
|
||||
|
||||
[JsonPropertyName("mission_reward_number")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("mission_reward_number")]
|
||||
public int MissionRewardNumber { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class MissionStartEntry
|
||||
{
|
||||
[JsonPropertyName("mission_name")] [Key("mission_name")]
|
||||
public string MissionName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("start_time")] [Key("start_time")]
|
||||
public long StartTime { get; set; }
|
||||
|
||||
[JsonPropertyName("lot_type")] [Key("lot_type")]
|
||||
public string LotType { get; set; } = "3"; // Phase 1 only emits puzzle-mission lot_type
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class TreasureRewardResponse
|
||||
{
|
||||
[JsonPropertyName("reward_type")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("reward_type")]
|
||||
public int RewardType { get; set; }
|
||||
|
||||
[JsonPropertyName("reward_id")] [JsonConverter(typeof(StringifiedLongConverter))] [Key("reward_id")]
|
||||
public long RewardId { get; set; }
|
||||
|
||||
[JsonPropertyName("reward_num")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("reward_num")]
|
||||
public int RewardNum { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class ClearMissionListResponse
|
||||
{
|
||||
[JsonPropertyName("common_mission")] [Key("common_mission")]
|
||||
public List<object> CommonMission { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("character_mission")] [Key("character_mission")]
|
||||
public List<object> CharacterMission { get; set; } = new();
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class SpotPointDataResponse
|
||||
{
|
||||
[JsonPropertyName("before_spot_point")] [Key("before_spot_point")] public int BeforeSpotPoint { get; set; }
|
||||
[JsonPropertyName("add_spot_point")] [Key("add_spot_point")] public int AddSpotPoint { get; set; }
|
||||
[JsonPropertyName("after_spot_point")] [Key("after_spot_point")] public int AfterSpotPoint { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common.BasicPuzzle;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class OpenPuzzleDialogResponse
|
||||
{
|
||||
[JsonPropertyName("puzzle_quest")] [Key("puzzle_quest")]
|
||||
public List<PuzzleEntryResponse> PuzzleQuest { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("puzzle_quest_chara_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("puzzle_quest_chara_id")]
|
||||
public int PuzzleQuestCharaId { get; set; }
|
||||
|
||||
[JsonPropertyName("puzzle_difficulty_name_list")] [Key("puzzle_difficulty_name_list")]
|
||||
public Dictionary<string, string> PuzzleDifficultyNameList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("is_display_badge")] [Key("is_display_badge")]
|
||||
public bool IsDisplayBadge { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("is_display_puzzle_new")] [Key("is_display_puzzle_new")]
|
||||
public bool IsDisplayPuzzleNew { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.BasicPuzzle;
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleMissionResponse
|
||||
{
|
||||
[JsonPropertyName("mission_name")] [Key("mission_name")]
|
||||
public string MissionName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("require_number")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("require_number")]
|
||||
public int RequireNumber { get; set; }
|
||||
|
||||
[JsonPropertyName("campaign_commence_time")] [Key("campaign_commence_time")]
|
||||
public long CampaignCommenceTime { get; set; }
|
||||
|
||||
[JsonPropertyName("reward_list")] [Key("reward_list")]
|
||||
public List<PuzzleMissionRewardResponse> RewardList { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("order_id")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("order_id")]
|
||||
public int OrderId { get; set; }
|
||||
|
||||
[JsonPropertyName("total_count")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("total_count")]
|
||||
public int TotalCount { get; set; }
|
||||
|
||||
[JsonPropertyName("is_achieved")] [Key("is_achieved")]
|
||||
public bool IsAchieved { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class PuzzleMissionRewardResponse
|
||||
{
|
||||
[JsonPropertyName("reward_type")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("reward_type")]
|
||||
public int RewardType { get; set; }
|
||||
|
||||
[JsonPropertyName("reward_detail_id")] [JsonConverter(typeof(StringifiedLongConverter))] [Key("reward_detail_id")]
|
||||
public long RewardDetailId { get; set; }
|
||||
|
||||
[JsonPropertyName("reward_number")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("reward_number")]
|
||||
public int RewardNumber { get; set; }
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public class MyPageIndexResponse
|
||||
|
||||
[JsonPropertyName("basic_puzzle")]
|
||||
[Key("basic_puzzle")]
|
||||
public BasicPuzzle BasicPuzzle { get; set; } = new();
|
||||
public BasicPuzzleBadge BasicPuzzle { get; set; } = new();
|
||||
|
||||
// ── Battle Pass period flag ────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -56,6 +56,16 @@ public class UserDeck
|
||||
[Key("create_deck_time")]
|
||||
public DateTime? DeckCreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MyRotation period id. Emitted only for Format.MyRotation decks; the client's
|
||||
/// DeckData.Initialize reads it via GetValueOrDefault("rotation_id", null) and resolves
|
||||
/// against Data.MyRotationAllInfo. A MyRotation deck without this field crashes the
|
||||
/// deck-detail dialog inside DeckData.CreateMyRotationClassName (info.LastPackText on null).
|
||||
/// </summary>
|
||||
[JsonPropertyName("rotation_id")]
|
||||
[Key("rotation_id")]
|
||||
public string? RotationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Empty placeholder matching the wire shape prod uses to pad deck-list responses up to the
|
||||
/// per-format cap. The client's <c>DeckUI.DeckViewData.CreateDeckViewList</c> converts the
|
||||
@@ -93,6 +103,7 @@ public class UserDeck
|
||||
this.IsRandomLeaderSkin = deck.RandomLeaderSkin ? 1 : 0;
|
||||
this.Order = deck.Number;
|
||||
this.DeckCreateTime = deck.DateCreated;
|
||||
this.RotationId = deck.MyRotationId;
|
||||
|
||||
//TODO probably want to calc some of these on demand
|
||||
this.IsCompleteDeck = 1;
|
||||
|
||||
Reference in New Issue
Block a user