DTOs for index mostly done, doing DB models

This commit is contained in:
gamer147
2024-09-12 00:35:31 -04:00
parent ac3b002d74
commit 79505e0c1a
69 changed files with 1523 additions and 21 deletions

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Interfaces; using DCGEngine.Database.Interfaces;
namespace DCGEngine.Database.Models; namespace DCGEngine.Database.Models;
@@ -6,6 +7,7 @@ namespace DCGEngine.Database.Models;
public class BaseEntity<TKey> : ITimeTrackedEntity, IDbTrackedEntity public class BaseEntity<TKey> : ITimeTrackedEntity, IDbTrackedEntity
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public virtual TKey Id { get; set; } public virtual TKey Id { get; set; }
public DateTime? DateCreated { get; set; } public DateTime? DateCreated { get; set; }

View File

@@ -1,3 +1,5 @@
using System.ComponentModel.DataAnnotations;
namespace DCGEngine.Database.Models; namespace DCGEngine.Database.Models;
/// <summary> /// <summary>
@@ -8,7 +10,8 @@ public abstract class CardEntry : BaseEntity<long>
/// <summary> /// <summary>
/// The name of this card used internally, to separate it from any localization key stored. /// The name of this card used internally, to separate it from any localization key stored.
/// </summary> /// </summary>
public virtual string InternalName { get; set; } [Required(AllowEmptyStrings = false)]
public virtual string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
/// The offensive power of this card. /// The offensive power of this card.

View File

@@ -0,0 +1,17 @@
namespace DCGEngine.Database.Models;
/// <summary>
/// A set containing 0 or more <see cref="CardEntry"/>s. All cards must belong to a set.
/// </summary>
public abstract class CardSetEntry : BaseEntity<int>
{
/// <summary>
/// The internal name of the set.
/// </summary>
public virtual string Name { get; set; } = string.Empty;
/// <summary>
/// The cards in the set.
/// </summary>
public virtual List<CardEntry> Cards { get; set; } = new List<CardEntry>();
}

View File

@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
namespace DCGEngine.Database.Models;
/// <summary>
/// A <see cref="CardEntry"/> that is in a <see cref="DeckEntry"/> X times.
/// </summary>
[Owned]
public class DeckCard
{
/// <summary>
/// The card in the deck.
/// </summary>
public virtual CardEntry Card { get; set; }
/// <summary>
/// The number of the card that is in the deck.
/// </summary>
public virtual int Count { get; set; }
/// <summary>
/// The deck this belongs to.
/// </summary>
public virtual DeckEntry Deck { get; set; }
}

View File

@@ -1,3 +1,5 @@
using System.ComponentModel.DataAnnotations;
namespace DCGEngine.Database.Models; namespace DCGEngine.Database.Models;
/// <summary> /// <summary>
@@ -8,10 +10,11 @@ public abstract class DeckEntry : BaseEntity<long>
/// <summary> /// <summary>
/// How this deck is referred to internally. /// How this deck is referred to internally.
/// </summary> /// </summary>
public virtual string InternalName { get; set; } [Required(AllowEmptyStrings = false)]
public virtual string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
/// The cards present in this deck. /// The cards present in this deck.
/// </summary> /// </summary>
public virtual List<CardEntry> Cards { get; set; } public virtual List<DeckCard> Cards { get; set; } = new List<DeckCard>();
} }

View File

@@ -0,0 +1,101 @@
namespace SVSim.Database.Enums;
public enum FeatureMaintenance
{
ProfileMaintenance = 2001,
MypageMaintenance,
GiftMaintenance,
SignupMaintenance,
PaymentMaintenanceIOs,
PaymentMaintenanceAndroid,
PaymentMaintenanceDmm = 2025,
PaymentMaintenanceSteam,
ShopCardpackMaintenance = 2007,
ShopBuilddeckMaintenance = 2032,
ShopSleeveMaintenance = 2008,
ShopSkinMaintenance = 2024,
ShopItemMaintenance = 2037,
AchievementMaintenance = 2009,
MissionMaintenance,
BpPointMaintenance,
FreebattleMaintenance,
RankbattleMaintenance,
RoomBattleMaintenance,
StoryMaintenance,
PracticeMaintenance,
ArenaTwopickMaintenance,
CardMaintenance,
DeckMaintenance,
TutorialMaintenance,
AccountMaintenance,
FriendMaintenance,
ArenaTwopickBattleMaintenance,
RoomTwopickMaintenance = 2029,
RoomAllMaintenance,
RoomWatchingMaintenance,
RoomRuleBo1 = 2038,
RoomRuleTwoPick,
RoomRuleTwoPickBackdraft,
RoomRuleBo3,
RoomRuleBo5,
RoomRuleBo3Ban1 = 2071,
RoomRuleBo5Ban1,
ArenaConvention = 2043,
FreebattleUnlimited,
FreebattleRotation,
RankbattleUnlimited,
RankbattleRotation,
RoomUnlimited,
RoomRotation,
Colosseum,
ColosseumBattle,
ColosseumRankMatchUser,
RoomRuleTwoPickQube,
GuildMaintenance,
ArenaSealedMaintenance,
ArenaSealedBattleMaintenance,
RoomFormatHof,
SealedDeckCode = 2059,
SpotcardExchange,
RoomPreRotation,
RoomRuleTwoPickBo3,
RoomRuleTwoPickBo5,
FreebattlePrerotation = 2065,
GatheringAll,
GatheringCreate,
BattlePass = 2070,
RoomRuleTwoPickChaos = 2073,
Quest = 2077,
RoomFormatWindfall,
DeckQrCode,
AutoDeckCreate,
CompetitionAll,
CompetitionBattle,
CompetitionRankMatchUser,
FreebattleCrossover,
RankbattleCrossover,
RoomFormatCrossover,
GatheringCrossover,
PracticePuzzle,
FreebattleMyrotation = 2093,
RoomFormatMyrotation,
GatheringMyrotation,
BossRush,
SecretBossBattle = 2100,
ReplayAll = 2034,
NewreplayAll = 2097,
NewreplayExcludeRotation,
NewreplayRecord,
ChatGuild = 2101,
ChatGathering,
FreebattleAvatar,
RoomFormatAvatar,
GatheringAvatar,
RoomRuleTwoPickCubeBackdraft,
RoomRuleTwoPickCubeBo3,
RoomRuleTwoPickCubeBo5,
RoomRuleTwoPickChaosBackdraft,
RoomRuleTwoPickChaosBo3,
RoomRuleTwoPickChaosBo5,
InvalidValue = 0
}

View File

@@ -0,0 +1,12 @@
namespace SVSim.Database.Enums;
public enum PickTwoFormat
{
None,
Normal,
Backdraft,
Cube,
Chaos,
BackdraftCube,
BackdraftChaos
}

View File

@@ -0,0 +1,10 @@
namespace SVSim.Database.Enums;
public enum Rarity
{
Unknown = 0,
Bronze = 1,
Silver = 2,
Gold = 3,
Legendary = 4
}

View File

@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class ClassEntry : BaseEntity<int>
{
/// <summary>
/// The name of the class.
/// </summary>
public string Name { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,10 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class CollectionInfo
{
public int CraftCost { get; set; }
public int DustReward { get; set; }
}

View File

@@ -0,0 +1,8 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class DegreeEntry : BaseEntity<int>
{
}

View File

@@ -0,0 +1,8 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class EmblemEntry : BaseEntity<long>
{
}

View File

@@ -0,0 +1,8 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class FormatEntry : BaseEntity<int>
{
public string Name { get; set; } = string.Empty;
}

View File

@@ -1,12 +1,37 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models; using DCGEngine.Database.Models;
using SVSim.Database.Enums;
namespace SVSim.Database.Models; namespace SVSim.Database.Models;
public class ShadowverseCardEntry : CardEntry public class ShadowverseCardEntry : CardEntry
{ {
[Key] /// <summary>
[DatabaseGenerated(DatabaseGeneratedOption.None)] /// The rarity of this card.
public override long Id { get; set; } /// </summary>
public Rarity Rarity { get; set; }
#region Owned
/// <summary>
/// Info about this card in the collection, if it can be collected.
/// </summary>
public CollectionInfo? CollectionInfo { get; set; }
#endregion
#region Navigation Properties
/// <summary>
/// The class this card belongs to, or optionally none for neutral cards.
/// </summary>
public ClassEntry? Class { get; set; }
/// <summary>
/// The set this card belongs to.
/// </summary>
public CardSetEntry CardSet { get; set; } = new ShadowverseCardSetEntry();
#endregion
} }

View File

@@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class ShadowverseCardSetEntry : CardSetEntry
{
}

View File

@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models; using DCGEngine.Database.Models;
using SVSim.Database.Enums; using SVSim.Database.Enums;
@@ -8,6 +9,9 @@ namespace SVSim.Database.Models;
/// </summary> /// </summary>
public class SocialAccountConnection : BaseEntity<Guid> public class SocialAccountConnection : BaseEntity<Guid>
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override Guid Id { get; set; }
/// <summary> /// <summary>
/// The type of the social account. /// The type of the social account.
/// </summary> /// </summary>

View File

@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models; using DCGEngine.Database.Models;
namespace SVSim.Database.Models; namespace SVSim.Database.Models;
@@ -7,6 +8,9 @@ namespace SVSim.Database.Models;
/// </summary> /// </summary>
public class Viewer : BaseEntity<ulong> public class Viewer : BaseEntity<ulong>
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override ulong Id { get; set; }
/// <summary> /// <summary>
/// This user's name displayed in game. /// This user's name displayed in game.
/// </summary> /// </summary>
@@ -16,6 +20,18 @@ public class Viewer : BaseEntity<ulong>
/// This user's short identifier. /// This user's short identifier.
/// </summary> /// </summary>
public ulong ShortUdid { get; set; } public ulong ShortUdid { get; set; }
public DateTime LastLogin { get; set; }
#region Owned
public ViewerInfo Info { get; set; } = new ViewerInfo();
public ViewerMissionData MissionData { get; set; } = new ViewerMissionData();
public ViewerCurrency Currency { get; set; } = new ViewerCurrency();
#endregion
#region Navigation Properties #region Navigation Properties

View File

@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class ViewerCurrency
{
public ulong Crystals { get; set; }
public ulong AndroidCrystals { get; set; }
public ulong IosCrystals { get; set; }
public ulong SteamCrystals { get; set; }
public ulong DmmCrystals { get; set; }
public ulong FreeCrystals { get; set; }
public ulong TotalCrystals { get; set; }
public ulong LifeTotalCrystals { get; set; }
public ulong RedEther { get; set; }
public ulong Rupees { get; set; }
}

View File

@@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class ViewerInfo
{
public DateTime BirthDate { get; set; }
public string CountryCode { get; set; } = string.Empty;
public int MaxFriends { get; set; }
public bool IsOfficial { get; set; }
public bool IsOfficialMarkDisplayed { get; set; }
#region Navigation Properties
public EmblemEntry SelectedEmblem { get; set; } = new EmblemEntry();
public DegreeEntry SelectedDegree { get; set; } = new DegreeEntry();
#endregion
}

View File

@@ -0,0 +1,12 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class ViewerMissionData
{
public bool HasReceivedPickTwoMission { get; set; }
public int MissionReceiveType { get; set; }
public DateTime MissionChangeTime { get; set; }
public int TutorialState { get; set; }
}

View File

@@ -6,4 +6,5 @@ public interface IViewerRepository
{ {
Task<Models.Viewer?> GetViewerBySocialConnection(SocialAccountType accountType, ulong socialId); Task<Models.Viewer?> GetViewerBySocialConnection(SocialAccountType accountType, ulong socialId);
Task<Models.Viewer?> GetViewerWithSocials(ulong id); Task<Models.Viewer?> GetViewerWithSocials(ulong id);
Task<Models.Viewer?> GetViewerByShortUdid(ulong shortUdid);
} }

View File

@@ -27,4 +27,10 @@ public class ViewerRepository : IViewerRepository
return await _dbContext.Set<Models.Viewer>().AsNoTracking().Include(viewer => viewer.SocialAccountConnections) return await _dbContext.Set<Models.Viewer>().AsNoTracking().Include(viewer => viewer.SocialAccountConnections)
.FirstOrDefaultAsync(viewer => viewer.Id == id); .FirstOrDefaultAsync(viewer => viewer.Id == id);
} }
public async Task<Models.Viewer?> GetViewerByShortUdid(ulong shortUdid)
{
return await _dbContext.Set<Models.Viewer>().AsNoTracking().Include(viewer => viewer.MissionData)
.Include(viewer => viewer.Info).FirstOrDefaultAsync(viewer => viewer.ShortUdid == shortUdid);
}
} }

View File

@@ -0,0 +1,42 @@
using Microsoft.AspNetCore.Mvc;
using SVSim.Database.Models;
using SVSim.Database.Repositories.Viewer;
using SVSim.EmulatedEntrypoint.Constants;
using SVSim.EmulatedEntrypoint.Models.Dtos;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
using SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
namespace SVSim.EmulatedEntrypoint.Controllers;
public class LoadController : SVSimController
{
private readonly IViewerRepository _viewerRepository;
public LoadController(IViewerRepository viewerRepository)
{
_viewerRepository = viewerRepository;
}
[HttpPost("index")]
public async Task<ActionResult<IndexResponse>> Index(IndexRequest request)
{
Viewer? viewer = await _viewerRepository.GetViewerByShortUdid(ulong.Parse(User.Claims
.FirstOrDefault(claim => claim.Type == ShadowverseClaimTypes.ShortUdidClaim).Value));
if (viewer == null)
{
return NotFound();
}
return new IndexResponse
{
UserTutorial = new UserTutorial()
{
TutorialStep = viewer.MissionData.TutorialState
},
UserInfo = new UserInfo(int.Parse(Request.Headers["DEVICE"].FirstOrDefault()), viewer),
UserCurrency = new UserCurrency(),
};
}
}

View File

@@ -1,5 +1,6 @@
using System.Text; using System.Text;
using MessagePack; using MessagePack;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
@@ -8,6 +9,7 @@ using SVSim.Database.Models;
using SVSim.EmulatedEntrypoint.Constants; using SVSim.EmulatedEntrypoint.Constants;
using SVSim.EmulatedEntrypoint.Extensions; using SVSim.EmulatedEntrypoint.Extensions;
using SVSim.EmulatedEntrypoint.Models.Dtos; using SVSim.EmulatedEntrypoint.Models.Dtos;
using SVSim.EmulatedEntrypoint.Models.Dtos.Internal;
using SVSim.EmulatedEntrypoint.Security; using SVSim.EmulatedEntrypoint.Security;
using SVSim.EmulatedEntrypoint.Services; using SVSim.EmulatedEntrypoint.Services;
@@ -31,7 +33,7 @@ public class ShadowverseTranslationMiddleware : IMiddleware
{ {
bool isUnity = context.Request.Headers.UserAgent.Any(agent => agent?.Contains("UnityPlayer") ?? false); bool isUnity = context.Request.Headers.UserAgent.Any(agent => agent?.Contains("UnityPlayer") ?? false);
string path = context.Request.Path; string path = context.Request.Path;
var endpointDescriptor = ActionDescriptor? endpointDescriptor =
_actionDescriptorCollectionProvider.ActionDescriptors.Items.FirstOrDefault(ad => _actionDescriptorCollectionProvider.ActionDescriptors.Items.FirstOrDefault(ad =>
$"/{ad.AttributeRouteInfo.Template}".Equals(path, StringComparison.InvariantCultureIgnoreCase)); $"/{ad.AttributeRouteInfo.Template}".Equals(path, StringComparison.InvariantCultureIgnoreCase));
if (!isUnity || endpointDescriptor == null) if (!isUnity || endpointDescriptor == null)
@@ -41,12 +43,12 @@ public class ShadowverseTranslationMiddleware : IMiddleware
} }
// Replace response body stream to re-access it. // Replace response body stream to re-access it.
using var tempResponseBody = new MemoryStream(); using MemoryStream tempResponseBody = new MemoryStream();
var originalResponsebody = context.Response.Body; Stream originalResponsebody = context.Response.Body;
context.Response.Body = tempResponseBody; context.Response.Body = tempResponseBody;
// Pull out the request bytes into a stream // Pull out the request bytes into a stream
using var requestBytesStream = new MemoryStream(); using MemoryStream requestBytesStream = new MemoryStream();
await context.Request.Body.CopyToAsync(requestBytesStream); await context.Request.Body.CopyToAsync(requestBytesStream);
byte[] requestBytes = requestBytesStream.ToArray(); byte[] requestBytes = requestBytesStream.ToArray();
@@ -58,8 +60,8 @@ public class ShadowverseTranslationMiddleware : IMiddleware
requestBytes = Encryption.Decrypt(requestBytes, udid); requestBytes = Encryption.Decrypt(requestBytes, udid);
object? data = MessagePackSerializer.Deserialize(endpointDescriptor.Parameters.FirstOrDefault().ParameterType, object? data = MessagePackSerializer.Deserialize(endpointDescriptor.Parameters.FirstOrDefault().ParameterType,
requestBytes); requestBytes);
var json = JsonConvert.SerializeObject(data); string json = JsonConvert.SerializeObject(data);
var newStream = new StringContent(json, Encoding.UTF8, "application/json"); StringContent newStream = new StringContent(json, Encoding.UTF8, "application/json");
context.Request.Body = newStream.ReadAsStream(); context.Request.Body = newStream.ReadAsStream();
context.Request.Headers.ContentType = new StringValues("application/json"); context.Request.Headers.ContentType = new StringValues("application/json");
@@ -68,16 +70,16 @@ public class ShadowverseTranslationMiddleware : IMiddleware
Viewer? viewer = context.GetViewer(); Viewer? viewer = context.GetViewer();
// Grab the response object // Grab the response object
var responseType = ((ControllerActionDescriptor)endpointDescriptor).MethodInfo.ReturnType; Type responseType = ((ControllerActionDescriptor)endpointDescriptor).MethodInfo.ReturnType;
if (responseType.IsGenericType && responseType.GetGenericTypeDefinition() == typeof(Task<>)) if (responseType.IsGenericType && responseType.GetGenericTypeDefinition() == typeof(Task<>))
{ {
responseType = responseType.GetGenericArguments()[0]; responseType = responseType.GetGenericArguments()[0];
} }
using var responseBytesStream = new MemoryStream(); using MemoryStream responseBytesStream = new MemoryStream();
context.Response.Body.Seek(0, SeekOrigin.Begin); context.Response.Body.Seek(0, SeekOrigin.Begin);
await context.Response.Body.CopyToAsync(responseBytesStream); await context.Response.Body.CopyToAsync(responseBytesStream);
var responseBytes = responseBytesStream.ToArray(); byte[] responseBytes = responseBytesStream.ToArray();
var responseData = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(responseBytes), responseType); object? responseData = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(responseBytes), responseType);
// Wrap the response in a datawrapper // Wrap the response in a datawrapper
DataWrapper wrappedResponseData = new DataWrapper DataWrapper wrappedResponseData = new DataWrapper
@@ -96,7 +98,7 @@ public class ShadowverseTranslationMiddleware : IMiddleware
}; };
// Convert the response into a messagepack, encrypt it // Convert the response into a messagepack, encrypt it
var packedData = MessagePackSerializer.Serialize<DataWrapper>(wrappedResponseData); byte[] packedData = MessagePackSerializer.Serialize<DataWrapper>(wrappedResponseData);
packedData = Encryption.Encrypt(packedData, udid); packedData = Encryption.Encrypt(packedData, udid);
await originalResponsebody.WriteAsync(Encoding.UTF8.GetBytes(Convert.ToBase64String(packedData))); await originalResponsebody.WriteAsync(Encoding.UTF8.GetBytes(Convert.ToBase64String(packedData)));
context.Response.Body = originalResponsebody; context.Response.Body = originalResponsebody;

View File

@@ -0,0 +1,12 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class ArenaConfig
{
[Key("use_challenge_two_pick_premium_card")]
public int UseChallengePickTwoPremiumCard { get; set; }
[Key("challenge_two_pick_sleeve_id")]
public int ChallengePickTwoCardSleeve { get; set; }
}

View File

@@ -0,0 +1,21 @@
using MessagePack;
using SVSim.Database.Enums;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class ArenaFormatInfo
{
[Key("two_pick_type")]
public PickTwoFormat PickTwoFormat { get; set; }
[Key("card_pool_name")]
public string CardPoolName { get; set; } = string.Empty;
[Key("announce_id")]
public string AnnounceId { get; set; } = "0";
[Key("card_pool_url")]
public string CardPoolUrl { get; set; } = string.Empty;
[Key("start_time")]
public DateTime StartTime { get; set; }
[Key("end_time")]
public DateTime EndTime { get; set; }
}

View File

@@ -0,0 +1,24 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class ArenaInfo
{
[Key("mode")]
public int Mode { get; set; }
[Key("enable")]
public int Enable { get; set; }
[Key("cost")]
public ulong Cost { get; set; }
[Key("rupy_cost")]
public ulong RupeeCost { get; set; }
[Key("ticket_cost")]
public int TicketCost { get; set; }
[Key("is_join")]
public bool IsJoin { get; set; }
[Key("sales_period_info")]
public ShopExpiryInfo? SalesPeriodInfo { get; set; }
[Key("format_info")]
public ArenaFormatInfo? FormatInfo { get; set; }
}

View File

@@ -0,0 +1,17 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class AvatarAbility
{
public int LeaderSkinId { get; set; }
public int BattleStartFirstPlayerBp { get; set; }
public int BattleStartSecondPlayerBp { get; set; }
public int BattleStartMaxLife { get; set; }
public string AbilityCost { get; set; }
public string Ability { get; set; }
public string PassiveAbility { get; set; }
public string AbilityDesc { get; set; }
public string PassiveAbilityDesc { get; set; }
}

View File

@@ -0,0 +1,10 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class AvatarInfo
{
public Dictionary<string, AvatarAbility> Abilities { get; set; } = new Dictionary<string, AvatarAbility>();
public SpecialRotationSchedule Schedules { get; set; } = new SpecialRotationSchedule();
}

View File

@@ -0,0 +1,12 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class BattlePassLevel
{
[Key("level")]
public int Level { get; set; }
[Key("required_point")]
public int RequiredPoints { get; set; }
}

View File

@@ -0,0 +1,16 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// Identifies a card in the game system.
/// </summary>
[MessagePackObject]
public class CardIdentifier
{
/// <summary>
/// The identifier of the card.
/// </summary>
[Key("card_id")]
public long CardId { get; set; }
}

View File

@@ -0,0 +1,10 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class CardSetIdentifier
{
[Key("card_set_id")]
public int SetId { get; set; }
}

View File

@@ -0,0 +1,16 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class ClassExp
{
[Key("level")]
public int Level { get; set; }
[Key("necessary_exp")]
public int NecessaryExp { get; set; }
[Key("diff_exp")]
public int DiffExp { get; set; }
[Key("accumulate_exp")]
public int AccumulateExp { get; set; }
}

View File

@@ -0,0 +1,14 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class DailyLoginBonus
{
[Key("total")]
public LoginBonusCampaign? Total { get; set; }
[Key("normal")]
public LoginBonusCampaign? Normal { get; set; }
[Key("campaign")]
public LoginBonusCampaign? Campaign { get; set; }
}

View File

@@ -0,0 +1,12 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class DateRange
{
[Key("begin_time")]
public DateTime BeginTime { get; set; }
[Key("end_time")]
public DateTime EndTime { get; set; }
}

View File

@@ -0,0 +1,14 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class DefaultSettings
{
[Key("default_emblem_id")]
public ulong DefaultEmblemId { get; set; }
[Key("default_degree_id")]
public int DefaultDegreeId { get; set; }
[Key("default_mypage_id")]
public ulong DefaultMyPageBackground { get; set; }
}

View File

@@ -0,0 +1,10 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class DegreeIdentifier
{
[Key("degree_id")]
public int DegreeId { get; set; }
}

View File

@@ -0,0 +1,10 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class EmblemIdentifier
{
[Key("emblem_id")]
public int EmblemId { get; set; }
}

View File

@@ -0,0 +1,10 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class GatheringInfo
{
[Key("has_invite")]
public int HasInvite { get; set; }
}

View File

@@ -1,6 +1,6 @@
using MessagePack; using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos; namespace SVSim.EmulatedEntrypoint.Models.Dtos.Internal;
[MessagePackObject] [MessagePackObject]
public class DataHeaders public class DataHeaders

View File

@@ -1,6 +1,6 @@
using MessagePack; using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos; namespace SVSim.EmulatedEntrypoint.Models.Dtos.Internal;
/// <summary> /// <summary>
/// Wraps responses in the format the official game client expects, with a header section for additional data. Not for manual endpoint use, this wrapping is done automatically in a middleware. /// Wraps responses in the format the official game client expects, with a header section for additional data. Not for manual endpoint use, this wrapping is done automatically in a middleware.

View File

@@ -0,0 +1,20 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class LoginBonusCampaign
{
[Key("name")]
public string Name { get; set; } = string.Empty;
[Key("campaign_id")]
public int CampaignId { get; set; }
[Key("img")]
public int Image { get; set; }
[Key("now_count")]
public int NowCount { get; set; }
[Key("is_next_reward")]
public bool IsNextReward { get; set; }
[Key("reward")]
public List<LoginBonusReward> Rewards { get; set; } = new List<LoginBonusReward>();
}

View File

@@ -0,0 +1,31 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class LoginBonusReward
{
/// <summary>
/// The effect shown ingame.
/// </summary>
[Key("effect_id")]
public int EffectId { get; set; }
/// <summary>
/// The type of reward.
/// </summary>
[Key("reward_type")]
public int RewardType { get; set; }
/// <summary>
/// A more specified reward type (ie if a pack, which pack).
/// </summary>
[Key("reward_detail_id")]
public int RewardDetailId { get; set; }
/// <summary>
/// The count of the reward.
/// </summary>
[Key("reward_number")]
public int RewardNumber { get; set; }
}

View File

@@ -0,0 +1,23 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// What features are restricted by a user's country's loot box regulations. 1 indicates restricted, 0 indicates
/// </summary>
[MessagePackObject]
public class LootBoxRegulations
{
[Key("pack")]
public int Pack { get; set; }
[Key("arena_2pick")]
public int ArenaPickTwo { get; set; }
[Key("arena_sealed")]
public int ArenaSealed { get; set; }
[Key("arena_colosseum")]
public int ArenaColosseum { get; set; }
[Key("arena_competition")]
public int ArenaCompetition { get; set; }
[Key("special_shop")]
public int SpecialShop { get; set; }
}

View File

@@ -0,0 +1,15 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject()]
public class MyRotationAbility
{
public int AbilityId { get; set; }
public int AddStartPp { get; set; }
public int AddStartLife { get; set; }
public int IncreaseAddPpTotalAmount { get; set; }
public int IncreaseAddPpTotalTurn { get; set; }
public string Ability { get; set; } = string.Empty;
public string AbilityDesc { get; set; } = String.Empty;
}

View File

@@ -0,0 +1,29 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class MyRotationInfo
{
[Key("abilities")]
public Dictionary<string, MyRotationAbility> Abilities { get; set; } = new Dictionary<string, MyRotationAbility>();
[Key("schedules")]
public SpecialRotationSchedule Schedules { get; set; } = new SpecialRotationSchedule();
[Key("setting")]
public Dictionary<string, SpecialRotationSetting>? Settings { get; set; }
[Key("disabled_card_set_ids")]
public List<int>? DisabledCardSets { get; set; }
/// <summary>
/// Set to card to card reprinted list.
/// </summary>
[Key("reprinted_base_card_ids")]
public Dictionary<string, Dictionary<string, int>>? ReprintedCards { get; set; }
/// <summary>
/// Set to card to count banlist.
/// </summary>
[Key("restricted_base_card_id_list")]
public Dictionary<string, Dictionary<string, int>>? Banlist { get; set; }
}

View File

@@ -0,0 +1,36 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class PreReleaseInfo
{
[Key("id")]
public int Id { get; set; }
[Key("start_time")]
public DateTime StartTime { get; set; }
[Key("end_time")]
public DateTime EndTime { get; set; }
[Key("display_end_time")]
public DateTime DisplayEndTime { get; set; }
[Key("next_card_set_id")]
public int NextCardSetId { get; set; }
[Key("default_card_master_id")]
public int DefaultCardMasterId { get; set; }
[Key("pre_release_card_master_id")]
public int PreReleaseCardMasterId { get; set; }
[Key("free_match_start_time")]
public DateTime FreeMatchStartTime { get; set; }
[Key("card_master_id")]
public int CardMasterId { get; set; }
[Key("rotation_card_set_id_list")]
public List<int> RotationCardSets { get; set; } = new List<int>();
[Key("reprinted_base_card_ids")]
public Dictionary<string, long> ReprintedCardIds { get; set; } = new Dictionary<string, long>();
[Key("latest_reprinted_base_card_ids")]
public List<int> LatestReprintedCardIds { get; set; } = new List<int>();
[Key("pre_release_status")]
public int PreReleaseStatus { get; set; }
[Key("is_pre_rotation_free_match_term")]
public int IsPreRotationFreeMatchTerm { get; set; }
}

View File

@@ -0,0 +1,42 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class RankInfo
{
[Key("rank_id")]
public int RankId { get; set; }
[Key("rank_name")]
public string RankName { get; set; } = string.Empty;
[Key("necessary_point")]
public int NecessaryPoints { get; set; }
[Key("accumulate_point")]
public int AccumulatePoints { get; set; }
[Key("lower_limit_point")]
public int LowerLimitPoints { get; set; }
[Key("base_add_bp")]
public int BaseAddBp { get; set; }
[Key("base_drop_bp")]
public int BaseDropBp { get; set; }
[Key("streak_bonus_pt")]
public int StreakBonusPoints { get; set; }
[Key("win_bonus")]
public double WinBonus { get; set; }
[Key("lose_bonus")]
public double LoseBonus { get; set; }
[Key("max_win_bonus")]
public int MaxWinBonus { get; set; }
[Key("max_lose_bonus")]
public int MaxLoseBonus { get; set; }
[Key("is_promotion_war")]
public int IsPromotionWar { get; set; }
[Key("match_count")]
public int MatchCount { get; set; }
[Key("necessary_win")]
public int NecessaryWins { get; set; }
[Key("reset_lose")]
public int ResetLose { get; set; }
[Key("accumulate_master_point")]
public int AccumulateMasterPoints { get; set; }
}

View File

@@ -0,0 +1,22 @@
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// An indication that a specific card has had it's red ether amounts overriden from the normal amounts.
/// </summary>
public class RedEtherOverride
{
/// <summary>
/// The id of the affected card.
/// </summary>
public ulong CardId { get; set; }
/// <summary>
/// How much red ether is now provided from dusting the card.
/// </summary>
public int GetRedEther { get; set; }
/// <summary>
/// How much red ether is now required to craft the card.
/// </summary>
public int UseRedEther { get; set; }
}

View File

@@ -1,6 +1,286 @@
using MessagePack;
using SVSim.Database.Enums;
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses; namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
[MessagePackObject]
public class IndexResponse public class IndexResponse
{ {
#region Primitive Returns
[Key("ts_card_rotation")]
public string TsCardRotation { get; set; } = string.Empty;
[Key("is_beginner_mission")]
public int IsBeginnerMission { get; set; }
[Key("spot_point")]
public int SpotPoint { get; set; }
[Key("is_available_colosseum_free_entry")]
public bool IsAvailableColosseumFreeEntry { get; set; }
[Key("friend_battle_invite_count")]
public int FriendBattleInviteCount { get; set; }
[Key("battle_recovery_status")]
public int BattleRecoveryStatus { get; set; }
[Key("room_recovery_status")]
public int RoomRecoveryStatus { get; set; }
[Key("is_battle_pass_period")]
public bool IsBattlePassPeriod { get; set; }
[Key("card_set_id_for_resource_dl_view")]
public int CardSetIdForResourceDlView { get; set; }
#endregion
#region Basic User Data
/// <summary>
/// The user's tutorial progress state.
/// </summary>
[Key("user_tutorial")]
public UserTutorial UserTutorial { get; set; } = new UserTutorial();
/// <summary>
/// Basic information about the user.
/// </summary>
[Key("user_info")]
public UserInfo UserInfo { get; set; } = new UserInfo();
/// <summary>
/// The in-game currency information for this user.
/// </summary>
[Key("user_crystal_count")]
public UserCurrency UserCurrency { get; set; } = new UserCurrency();
#endregion
#region Inventory Data
/// <summary>
/// Items that the user has and how many of each.
/// </summary>
[Key("user_item_list")]
public List<UserItem> UserItems { get; set; } = new List<UserItem>();
/// <summary>
/// Decks for the rotation format.
/// </summary>
[Key("user_deck_rotation")]
public UserFormatDeckInfo UserRotationDecks { get; set; } = new UserFormatDeckInfo();
/// <summary>
/// Decks for the unlimited format.
/// </summary>
[Key("user_deck_unlimited")]
public UserFormatDeckInfo UserUnlimitedDecks { get; set; } = new UserFormatDeckInfo();
/// <summary>
/// Decks for the unlimited format.
/// </summary>
[Key("user_deck_my_rotation")]
public UserFormatDeckInfo UserMyRotationDecks { get; set; } = new UserFormatDeckInfo();
/// <summary>
/// The list of cards and how many of each this user has.
/// </summary>
[Key("user_card_list")]
public List<UserCard> UserCards { get; set; } = new List<UserCard>();
/// <summary>
/// The classes a user has and their stats.
/// </summary>
[Key("user_class_list")]
public List<UserClass> UserClasses { get; set; } = new List<UserClass>();
/// <summary>
/// Mapping of SleeveId to a <see cref="SleeveIdentifier"/> object.
/// </summary>
[Key("user_sleeve_list")]
public Dictionary<string, SleeveIdentifier> Sleeves { get; set; } = new Dictionary<string, SleeveIdentifier>();
/// <summary>
/// The emblems available to this user.
/// </summary>
[Key("user_emblem_list")]
public List<EmblemIdentifier> UserEmblems { get; set; } = new List<EmblemIdentifier>();
/// <summary>
/// The degrees available to this user.
/// </summary>
[Key("degree_id")]
public List<DegreeIdentifier> UserDegrees { get; set; } = new List<DegreeIdentifier>();
/// <summary>
/// Leader skins available to the leader.
/// </summary>
[Key("user_leader_skin_list")]
public Dictionary<string, UserLeaderSkin> LeaderSkins { get; set; } = new Dictionary<string, UserLeaderSkin>();
/// <summary>
/// Backgrounds for 'My Page' the user has collected.
/// </summary>
[Key("user_mypage_list")]
public List<ulong> MyPageBackgrounds { get; set; } = new List<ulong>();
#endregion
#region Advanced Player Data
/// <summary>
/// Maps a deck format (as a string) to info about ranked for that format.
/// </summary>
[Key("user_rank")]
public Dictionary<string, UserRankInfo> UserRankInfo { get; set; } = new Dictionary<string, UserRankInfo>();
/// <summary>
/// The number of ranked matches for each class the user has played.
/// </summary>
[Key("user_rank_match_list")]
public List<UserRankedMatches> UserRankedMatches { get; set; } = new List<UserRankedMatches>();
/// <summary>
/// The daily login bonuses currently going on, including if the player should receive the next reward for any.
/// </summary>
[Key("daily_login_bonus")]
public DailyLoginBonus DailyLoginBonus { get; set; } = new DailyLoginBonus();
/// <summary>
/// User configuration for the arena.
/// </summary>
[Key("challenge_config")]
public ArenaConfig ArenaConfig { get; set; } = new ArenaConfig();
#endregion
#region Global Data
/// <summary>
/// Cards that have had their red ether values overriden.
/// </summary>
[Key("red_ether_overwrite_list")]
public List<RedEtherOverride> RedEtherOverrides { get; set; } = new List<RedEtherOverride>();
/// <summary>
/// Cards that are currently undergoing maintenance.
/// </summary>
[Key("maintenance_card_list")]
public List<CardIdentifier> MaintenanceCards { get; set; } = new List<CardIdentifier>();
/// <summary>
/// The arena formats currently available.
/// </summary>
[Key("arena_info")]
public List<ArenaInfo> ArenaInfos { get; set; } = new List<ArenaInfo>();
/// <summary>
/// Dictionary of rank id to information about that rank.
/// </summary>
[Key("rank_info")]
public Dictionary<string, RankInfo> RankInfo { get; set; } = new Dictionary<string, RankInfo>();
/// <summary>
/// Dictionary mapping a class level to information about that level.
/// </summary>
[Key("class_exp")]
public Dictionary<string, ClassExp> ClassExp { get; set; } = new Dictionary<string, ClassExp>();
/// <summary>
/// Card ids that should not show up on loading screen tips.
/// </summary>
[Key("loading_exclusion_card_list")]
public List<long> LoadingTipCardExclusions { get; set; } = new List<long>();
/// <summary>
/// The default settings for every user.
/// </summary>
[Key("default_setting")]
public DefaultSettings DefaultSettings { get; set; } = new DefaultSettings();
/// <summary>
/// Any cards that are restricted in unlimited, and the maximum count that can be run of the card.
/// </summary>
[Key("unlimited_restricted_base_card_id_list")]
public Dictionary<string, int> UnlimitedBanList { get; set; } = new Dictionary<string, int>();
/// <summary>
/// Sets currently available in rotation.
/// </summary>
[Key("rotation_card_set_id_list")]
public List<CardSetIdentifier> RotationSets { get; set; } = new List<CardSetIdentifier>();
/// <summary>
/// Allows cards out of your 'My Rotation' to still be used. TODO investigate
/// </summary>
[Key("reprinted_base_card_ids")]
public Dictionary<string, long> ReprintedCards { get; set; } = new Dictionary<string, long>();
/// <summary>
/// Something to do with destroying cards. TODO investigate
/// </summary>
[Key("spot_cards")]
public Dictionary<string, int> SpotCards { get; set; } = new Dictionary<string, int>();
/// <summary>
/// Info about the next set to be released? TODO investigate
/// </summary>
[Key("pre_release_info")]
public PreReleaseInfo? PreReleaseInfo { get; set; }
/// <summary>
/// Information for the 'My Rotation' mode.
/// </summary>
[Key("my_rotation_info")]
public MyRotationInfo? MyRotationInfo { get; set; }
/// <summary>
/// Information about some avatar mode? TODO investigate
/// </summary>
[Key("avatar_info")]
public MyRotationInfo? AvatarRotationInfo { get; set; }
/// <summary>
/// List of features that are undergoing maintenance.
/// </summary>
[Key("feature_maintenance_list")]
public List<FeatureMaintenance> FeatureMaintenances { get; set; } = new List<FeatureMaintenance>();
/// <summary>
/// Special deals on crystal purchases.
/// </summary>
[Key("special_crystal_info")]
public List<SpecialCrystalInfo> SpecialCrystalInfos { get; set; } = new List<SpecialCrystalInfo>();
/// <summary>
/// Current battle pass levels and required points for each.
/// </summary>
[Key("battle_pass_level_info")]
public Dictionary<string, BattlePassLevel>? BattlePassLevelInfo { get; set; }
/// <summary>
/// Battlefields that can currently be picked.
/// </summary>
[Key("open_battle_field_id_list")]
public Dictionary<string, int> OpenBattlefieldIds { get; set; } = new Dictionary<string, int>();
#endregion
#region Misc Data
/// <summary>
/// What loot box features are disabled for this user.
/// </summary>
[Key("loot_box_regulation")]
public LootBoxRegulations LootBoxRegulations { get; set; } = new LootBoxRegulations();
/// <summary>
/// Something about whether the user has an invite notification.
/// </summary>
[Key("gathering_info")]
public GatheringInfo GatheringInfo { get; set; } = new GatheringInfo();
/// <summary>
/// User configuration.
/// </summary>
[Key("user_config")]
public UserConfig UserConfig { get; set; } = new UserConfig();
#endregion
} }

View File

@@ -0,0 +1,12 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class ShopExpiryInfo
{
[Key("sales_period_time")]
public DateTime? SalesPeriodTime { get; set; }
[Key("sales_period_series")]
public int? SalesPeriodSeries { get; set; }
}

View File

@@ -0,0 +1,16 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// Identifies a card sleeve.
/// </summary>
[MessagePackObject]
public class SleeveIdentifier
{
/// <summary>
/// The id of the sleeve.
/// </summary>
[Key("sleeve_id")]
public int SleeveId { get; set; }
}

View File

@@ -0,0 +1,9 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class SpecialCrystalInfo
{
}

View File

@@ -0,0 +1,12 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class SpecialRotationSchedule
{
[Key("gathering")]
public DateRange Gathering { get; set; } = new DateRange();
[Key("free_battle")]
public DateRange FreeBattle { get; set; } = new DateRange();
}

View File

@@ -0,0 +1,22 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class SpecialRotationSetting
{
[Key("rotation_id")]
public int RotationId { get; set; }
/// <summary>
/// Formatted as 'setid|setid|setid...'.
/// </summary>
[Key("card_set_ids")]
public string CardSetIds { get; set; }
/// <summary>
/// Formatted as 'abilityid|abilityid|abilityid...'.
/// </summary>
[Key("abilities")]
public string Abilities { get; set; }
}

View File

@@ -0,0 +1,22 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// A card in a user's collection and the number possessed.
/// </summary>
[MessagePackObject]
public class UserCard : CardIdentifier
{
/// <summary>
/// The number of the specified card the user has.
/// </summary>
[Key("number")]
public int Count { get; set; }
/// <summary>
/// Whether the card is protected from dusting.
/// </summary>
[Key("is_protected")]
public int IsProtected { get; set; }
}

View File

@@ -0,0 +1,31 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserClass
{
[Key("class_id")]
public int ClassId { get; set; }
[Key("is_available")]
public int IsAvailable { get; set; }
[Key("level")]
public int Level { get; set; }
[Key("exp")]
public int Exp { get; set; }
[Key("is_random_leader_skin")]
public int IsRandomLeaderSkin { get; set; }
[Key("leader_skin_id")]
public int LeaderSkinId { get; set; }
[Key("leader_skin_id_list")]
public List<int> LeaderSkinIds { get; set; } = new List<int>();
[Key("default_leader_skin_id")]
public int DefaultLeaderSkinId { get; set; }
}

View File

@@ -0,0 +1,22 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserConfig
{
[Key("receive_invitation")]
public int ReceiveInvitation { get; set; }
[Key("receive_invitation_in_battle")]
public int ReceiveInvitationInBattle { get; set; }
[Key("receive_invitation_in_offline")]
public int ReceiveInvitationInOffline { get; set; }
[Key("receive_friend_apply")]
public int ReceiveFriendApply { get; set; }
[Key("is_allow_send_adjust")]
public int IsAllowSendAdjust { get; set; }
[Key("is_foil_preferred")]
public int IsFoilPreferred { get; set; }
[Key("is_prize_preferred")]
public int IsPrizePreferred { get; set; }
}

View File

@@ -0,0 +1,52 @@
using MessagePack;
using SVSim.Database.Models;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserCurrency
{
[Key("viewer_id")]
public ulong ViewerId { get; set; }
[Key("crystal")]
public ulong Crystals { get; set; }
[Key("crystal_android")]
public ulong AndroidCrystals { get; set; }
[Key("crystal_ios")]
public ulong IosCrystals { get; set; }
[Key("crystal_steam")]
public ulong SteamCrystals { get; set; }
[Key("crystal_dmm")]
public ulong DmmCrystals { get; set; }
[Key("free_crystal")]
public ulong FreeCrystals { get; set; }
[Key("total_crystal")]
public ulong TotalCrystals { get; set; }
[Key("life_total_crystal")]
public ulong LifeTotalCrystals { get; set; }
[Key("red_ether")]
public ulong RedEther { get; set; }
[Key("rupy")]
public ulong Rupees { get; set; }
public UserCurrency()
{
}
public UserCurrency(Viewer viewer)
{
ViewerCurrency currency = viewer.Currency;
this.Crystals = currency.Crystals;
this.RedEther = currency.RedEther;
this.LifeTotalCrystals = currency.LifeTotalCrystals;
this.TotalCrystals = currency.LifeTotalCrystals;
this.Rupees = currency.Rupees;
this.FreeCrystals = currency.FreeCrystals;
this.AndroidCrystals = currency.AndroidCrystals;
this.DmmCrystals = currency.DmmCrystals;
this.SteamCrystals = currency.SteamCrystals;
this.IosCrystals = currency.IosCrystals;
this.ViewerId = viewer.Id;
}
}

View File

@@ -0,0 +1,41 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// A deck belonging to a user.
/// </summary>
[MessagePackObject]
public class UserDeck
{
[Key("deck_no")]
public int DeckNumber { get; set; }
[Key("class_id")]
public int ClassId { get; set; }
[Key("sleeve_id")]
public int SleeveId { get; set; }
[Key("leader_skin_id")]
public int LeaderSkinId { get; set; }
[Key("deck_name")]
public string DeckName { get; set; } = string.Empty;
[Key("card_id_array")]
public List<int> Cards { get; set; } = new List<int>();
[Key("is_complete_deck")]
public int IsCompleteDeck { get; set; }
[Key("restricted_card_exists")]
public bool RestrictedCardExists { get; set; }
[Key("is_available_deck")]
public int IsAvailable { get; set; }
[Key("maintenance_card_ids")]
public List<int> MaintenanceCards { get; set; } = new List<int>();
[Key("is_include_un_possession_card")]
public bool IncludesNonCollectibleCards { get; set; }
[Key("is_random_leader_skin")]
public int IsRandomLeaderSkin { get; set; }
[Key("leader_skin_id_list")]
public List<int> LeaderSkinIds { get; set; } = new List<int> { 0 };
[Key("order_num")]
public int Order { get; set; }
[Key("create_deck_time")]
public DateTime DeckCreateTime { get; set; }
}

View File

@@ -0,0 +1,13 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserFormatDeckInfo
{
[Key("format")]
public string Format { get; set; } = string.Empty;
[Key("user_deck_list")]
public List<UserDeck> UserDecks { get; set; } = new List<UserDeck>();
}

View File

@@ -0,0 +1,56 @@
using MessagePack;
using SVSim.Database.Models;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserInfo
{
[Key("device_type")]
public int DeviceType { get; set; }
[Key("name")]
public string Name { get; set; } = string.Empty;
[Key("country_code")]
public string CountryCode { get; set; } = string.Empty;
[Key("max_friend")]
public int MaxFriend { get; set; }
[Key("last_play_time")]
public DateTime LastPlayTime { get; set; }
[Key("is_received_two_pick_mission")]
public int HasReceivedPickTwoMission { get; set; }
[Key("birth")]
public long Birthday { get; set; }
[Key("selected_emblem_id")]
public long SelectedEmblemId { get; set; }
[Key("selected_degree_id")]
public int SelectedDegreeId { get; set; }
[Key("mission_change_time")]
public DateTime MissionChangeTime { get; set; }
[Key("mission_receive_type")]
public int MissionReceiveType { get; set; }
[Key("is_official")]
public int IsOfficial { get; set; }
[Key("is_official_mark_displayed")]
public int IsOfficialMarkDisplayed { get; set; }
public UserInfo()
{
}
public UserInfo(int deviceType, Viewer viewer)
{
this.DeviceType = deviceType;
this.Name = viewer.DisplayName;
this.CountryCode = viewer.Info.CountryCode;
this.MaxFriend = viewer.Info.MaxFriends;
this.LastPlayTime = viewer.LastLogin;
this.HasReceivedPickTwoMission = viewer.MissionData.HasReceivedPickTwoMission ? 1 : 0;
this.Birthday = viewer.Info.BirthDate.Ticks;
this.SelectedEmblemId = viewer.Info.SelectedEmblem.Id;
this.SelectedDegreeId = viewer.Info.SelectedDegree.Id;
this.MissionChangeTime = viewer.MissionData.MissionChangeTime;
this.MissionReceiveType = viewer.MissionData.MissionReceiveType;
this.IsOfficial = viewer.Info.IsOfficial ? 1 : 0;
this.IsOfficialMarkDisplayed = viewer.Info.IsOfficialMarkDisplayed ? 1 : 0;
}
}

View File

@@ -0,0 +1,13 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserItem
{
[Key("item_id")]
public int ItemId { get; set; }
[Key("number")]
public int Number { get; set; }
}

View File

@@ -0,0 +1,18 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserLeaderSkin
{
[Key("leader_skin_id")]
public int Id { get; set; }
[Key("leader_skin_name")]
public string Name { get; set; } = string.Empty;
[Key("class_id")]
public int ClassId { get; set; }
[Key("emote_id")]
public int EmoteId { get; set; }
[Key("is_owned")]
public bool IsOwned { get; set; }
}

View File

@@ -0,0 +1,16 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserPromotionMatch
{
[Key("match_count")]
public int MatchCount { get; set; }
[Key("battle_result")]
public int BattleResult { get; set; }
[Key("win")]
public int Wins { get; set; }
[Key("lose")]
public int Losses { get; set; }
}

View File

@@ -0,0 +1,34 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserRankInfo
{
[Key("deck_format")]
public int DeckFormat { get; set; }
[Key("rank")]
public int Rank { get; set; }
[Key("battle_point")]
public int BattlePoints { get; set; }
[Key("successive_win_number")]
public int WinStreak { get; set; }
[Key("successive_losses_number")]
public int LossStreak { get; set; }
[Key("is_promotion")]
public int IsPromotion { get; set; }
[Key("is_master_rank")]
public int IsMasterRank { get; set; }
[Key("is_grand_master_rank")]
public bool IsGrandMasterRank { get; set; }
[Key("master_point")]
public int MasterPoints { get; set; }
[Key("period_grand_master_point")]
public int PeriodGrandMasterPoints { get; set; }
[Key("target_grand_master_point")]
public int TargetGrandMasterPoints { get; set; }
[Key("current_grand_master_point")]
public int CurrentGrandMasterPoints { get; set; }
[Key("user_promotion_match")]
public UserPromotionMatch? UserPromotionMatch { get; set; }
}

View File

@@ -0,0 +1,18 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
[MessagePackObject]
public class UserRankedMatches
{
[Key("class_id")]
public int ClassId { get; set; }
[Key("match_count")]
public int MatchCount { get; set; }
[Key("win")]
public int Wins { get; set; }
[Key("lose")]
public int Losses { get; set; }
[Key("viewer_id")]
public ulong ViewerId { get; set; }
}

View File

@@ -0,0 +1,16 @@
using MessagePack;
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
/// <summary>
/// The state of a user's tutorial progress.
/// </summary>
[MessagePackObject]
public class UserTutorial
{
/// <summary>
/// The current tutorial step they are on.
/// </summary>
[Key("tutorial_step")]
public int TutorialStep { get; set; }
}

View File

@@ -24,7 +24,6 @@
<ItemGroup> <ItemGroup>
<Folder Include="Configuration\" /> <Folder Include="Configuration\" />
<Folder Include="Controllers\" />
<Folder Include="Utility\" /> <Folder Include="Utility\" />
</ItemGroup> </ItemGroup>