From 735db02c5078539f166394fcb4606aaad289206c Mon Sep 17 00:00:00 2001 From: raphaeIl Date: Sat, 11 May 2024 00:30:17 -0400 Subject: [PATCH] basic character, equipment and weapon management --- .../ModelExtensions/AccountExtensions.cs | 39 ++ SCHALE.Common/Database/SCHALEContext.cs | 18 + SCHALE.Common/Database/dbs.cs | 175 ++++++- .../20240510003553_Equipment.Designer.cs | 420 ++++++++++++++++ .../Migrations/20240510003553_Equipment.cs | 52 ++ .../20240510093842_Weapons.Designer.cs | 469 ++++++++++++++++++ .../Migrations/20240510093842_Weapons.cs | 51 ++ .../Migrations/SCHALEContextModelSnapshot.cs | 101 ++++ SCHALE.Common/NetworkProtocol/protos.cs | 16 +- .../Api/ProtocolHandlers/Account.cs | 136 ++++- .../Api/ProtocolHandlers/Character.cs | 68 +++ .../Controllers/Api/ProtocolHandlers/Clan.cs | 23 +- .../Api/ProtocolHandlers/Echelon.cs | 15 +- .../Api/ProtocolHandlers/Equipment.cs | 103 ++++ .../Controllers/Api/ProtocolHandlers/Item.cs | 8 + .../Controllers/Api/ProtocolHandlers/Raid.cs | 65 +++ .../Api/ProtocolHandlers/Scenario.cs | 10 +- .../Controllers/Api/ProtocolHandlers/Shop.cs | 59 ++- 18 files changed, 1795 insertions(+), 33 deletions(-) create mode 100644 SCHALE.Common/Migrations/20240510003553_Equipment.Designer.cs create mode 100644 SCHALE.Common/Migrations/20240510003553_Equipment.cs create mode 100644 SCHALE.Common/Migrations/20240510093842_Weapons.Designer.cs create mode 100644 SCHALE.Common/Migrations/20240510093842_Weapons.cs create mode 100644 SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Character.cs create mode 100644 SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Equipment.cs create mode 100644 SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Raid.cs diff --git a/SCHALE.Common/Database/ModelExtensions/AccountExtensions.cs b/SCHALE.Common/Database/ModelExtensions/AccountExtensions.cs index 3175845..0775d2e 100644 --- a/SCHALE.Common/Database/ModelExtensions/AccountExtensions.cs +++ b/SCHALE.Common/Database/ModelExtensions/AccountExtensions.cs @@ -12,5 +12,44 @@ return [.. characters]; } + + public static List AddEquipment(this AccountDB account, SCHALEContext context, params EquipmentDB[] equipmentDB) + { + foreach (var equipment in equipmentDB) + { + equipment.AccountServerId = account.ServerId; + + var existingEquipment = account.Equipment.FirstOrDefault(x => x.UniqueId == equipment.UniqueId); + + if (existingEquipment != null && equipment.BoundCharacterServerId == default) + existingEquipment.StackCount += equipment.StackCount; + else + context.Equipment.Add(equipment); + } + + return [.. equipmentDB]; + } + + public static List AddWeapons(this AccountDB account, SCHALEContext context, params WeaponDB[] weapons) + { + foreach (var weapon in weapons) + { + weapon.AccountServerId = account.ServerId; + context.Weapons.Add(weapon); + } + + return [.. weapons]; + } + + public static List AddItems(this AccountDB account, SCHALEContext context, params ItemDB[] items) + { + foreach (var item in items) + { + item.AccountServerId = account.ServerId; + context.Items.Add(item); + } + + return [.. items]; + } } } diff --git a/SCHALE.Common/Database/SCHALEContext.cs b/SCHALE.Common/Database/SCHALEContext.cs index bd039f8..7fc2516 100644 --- a/SCHALE.Common/Database/SCHALEContext.cs +++ b/SCHALE.Common/Database/SCHALEContext.cs @@ -11,10 +11,15 @@ namespace SCHALE.Common.Database public DbSet GuestAccounts { get; set; } public DbSet Accounts { get; set; } public DbSet MissionProgresses { get; set; } + public DbSet Items { get; set; } public DbSet Characters { get; set; } + public DbSet Equipment { get; set; } + public DbSet Weapons { get; set; } + public DbSet Echelons { get; set; } public DbSet AccountTutorials { get; set; } + public static SCHALEContext Create(string connectionString) => new(new DbContextOptionsBuilder() @@ -47,8 +52,21 @@ namespace SCHALE.Common.Database .WithOne(x => x.Account) .HasForeignKey(x => x.AccountServerId) .IsRequired(); + modelBuilder.Entity() + .HasMany(x => x.Equipment) + .WithOne(x => x.Account) + .HasForeignKey(x => x.AccountServerId) + .IsRequired(); + modelBuilder.Entity() + .HasMany(x => x.Weapons) + .WithOne(x => x.Account) + .HasForeignKey(x => x.AccountServerId) + .IsRequired(); modelBuilder.Entity().Property(x => x.ServerId).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(x => x.ServerId).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(x => x.ServerId).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(x => x.ServerId).ValueGeneratedOnAdd(); modelBuilder.Entity().Property(x => x.ServerId).ValueGeneratedOnAdd(); diff --git a/SCHALE.Common/Database/dbs.cs b/SCHALE.Common/Database/dbs.cs index 8589950..4e3d006 100644 --- a/SCHALE.Common/Database/dbs.cs +++ b/SCHALE.Common/Database/dbs.cs @@ -1,12 +1,18 @@ using SCHALE.Common.FlatData; using SCHALE.Common.NetworkProtocol; using SCHALE.Common.Parcel; +using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; namespace SCHALE.Common.Database { + public class SingleRaidLobbyInfoDB : RaidLobbyInfoDB + { + + } + // Battle? probably need to implement these our selves public class BattleSummary { @@ -197,6 +203,12 @@ namespace SCHALE.Common.Database [JsonIgnore] public virtual ICollection Echelons { get; } + [JsonIgnore] + public virtual ICollection Equipment { get; } + + [JsonIgnore] + public virtual ICollection Weapons { get; } + public AccountDB() { } public AccountDB(long publisherAccountId) @@ -358,7 +370,7 @@ namespace SCHALE.Common.Database Cheat = 4 } - public class AssistCharacterDB + public class AssistCharacterDB : CharacterDB { public EchelonType EchelonType { get; set; } public int SlotNumber { get; set; } @@ -1108,8 +1120,10 @@ namespace SCHALE.Common.Database public class EquipmentDB : ConsumableItemBaseDB { + [NotMapped] public override ParcelType Type { get => ParcelType.Equipment; } + [NotMapped] [JsonIgnore] public override IEnumerable ParcelInfos { get; } @@ -1738,6 +1752,16 @@ namespace SCHALE.Common.Database public long PurchaseOrderId { get; set; } } + public class RaidMemberCollection : KeyedCollection + { + public long TotalDamage { get; set; } + + protected override long GetKeyForItem(RaidMemberDescription item) + { + return -1; + } + //public IEnumerable RaidDamages { get; set; } + } public class RaidBattleDB { @@ -1749,7 +1773,7 @@ namespace SCHALE.Common.Database public long CurrentBossAIPhase { get; set; } public string BIEchelon { get; set; } public bool IsClear { get; set; } - //public RaidMemberCollection RaidMembers { get; set; } + public RaidMemberCollection RaidMembers { get; set; } public List SubPartsHPs { get; set; } } @@ -1777,10 +1801,23 @@ namespace SCHALE.Common.Database public long CostumeId { get; set; } } - - public class RaidDB + public class RaidMemberDescription : IEquatable { - //public RaidMemberDescription Owner { get; set; } + public long AccountId { get; set; } + + public string AccountName { get; set; } + + public long CharacterId { get; set; } + + public bool Equals(RaidMemberDescription? other) + { + return this.AccountId == other.AccountId; + } + } + + public class RaidDB + { + public RaidMemberDescription Owner { get; set; } public ContentType ContentType { get; set; } public long ServerId { get; set; } public long UniqueId { get; set; } @@ -1832,7 +1869,7 @@ namespace SCHALE.Common.Database } - public class RaidLobbyInfoDB + public abstract class RaidLobbyInfoDB { public long SeasonId { get; set; } public int Tier { get; set; } @@ -2113,10 +2150,123 @@ namespace SCHALE.Common.Database public RaidTeamSettingDB RaidTeamSettingDB { get; set; } } + public enum SkillSlot + { + None, + NormalAttack01, + NormalAttack02, + NormalAttack03, + NormalAttack04, + NormalAttack05, + NormalAttack06, + NormalAttack07, + NormalAttack08, + NormalAttack09, + NormalAttack10, + ExSkill01, + ExSkill02, + ExSkill03, + ExSkill04, + ExSkill05, + ExSkill06, + ExSkill07, + ExSkill08, + ExSkill09, + ExSkill10, + Passive01, + Passive02, + Passive03, + Passive04, + Passive05, + Passive06, + Passive07, + Passive08, + Passive09, + Passive10, + ExtraPassive01, + ExtraPassive02, + ExtraPassive03, + ExtraPassive04, + ExtraPassive05, + ExtraPassive06, + ExtraPassive07, + ExtraPassive08, + ExtraPassive09, + ExtraPassive10, + Support01, + Support02, + Support03, + Support04, + Support05, + Support06, + Support07, + Support08, + Support09, + Support10, + EnterBattleGround, + LeaderSkill01, + LeaderSkill02, + LeaderSkill03, + LeaderSkill04, + LeaderSkill05, + LeaderSkill06, + LeaderSkill07, + LeaderSkill08, + LeaderSkill09, + LeaderSkill10, + Equipment01, + Equipment02, + Equipment03, + Equipment04, + Equipment05, + Equipment06, + Equipment07, + Equipment08, + Equipment09, + Equipment10, + PublicSkill01, + PublicSkill02, + PublicSkill03, + PublicSkill04, + PublicSkill05, + PublicSkill06, + PublicSkill07, + PublicSkill08, + PublicSkill09, + PublicSkill10, + GroupBuff01, + HexaBuff01, + EventBuff01, + EventBuff02, + EventBuff03, + MoveAttack01, + MetamorphNormalAttack, + GroundPassive01, + GroundPassive02, + GroundPassive03, + GroundPassive04, + GroundPassive05, + GroundPassive06, + GroundPassive07, + GroundPassive08, + GroundPassive09, + GroundPassive10, + HiddenPassive01, + HiddenPassive02, + HiddenPassive03, + HiddenPassive04, + HiddenPassive05, + HiddenPassive06, + HiddenPassive07, + HiddenPassive08, + HiddenPassive09, + HiddenPassive10, + Count + } public class SkillLevelBatchGrowthRequestDB { - //public SkillSlot SkillSlot { get; set; } + public SkillSlot SkillSlot { get; set; } public int Level { get; set; } public List ReplaceInfos { get; set; } } @@ -2241,11 +2391,22 @@ namespace SCHALE.Common.Database public class WeaponDB : ParcelBase { + [NotMapped] public override ParcelType Type { get => ParcelType.CharacterWeapon; } + [NotMapped] [JsonIgnore] public override IEnumerable ParcelInfos { get; } + [JsonIgnore] + public virtual AccountDB Account { get; set; } + + [JsonIgnore] + public long AccountServerId { get; set; } + + [Key] + public long ServerId { get; set; } + public long UniqueId { get; set; } public int Level { get; set; } public long Exp { get; set; } diff --git a/SCHALE.Common/Migrations/20240510003553_Equipment.Designer.cs b/SCHALE.Common/Migrations/20240510003553_Equipment.Designer.cs new file mode 100644 index 0000000..83fbeb0 --- /dev/null +++ b/SCHALE.Common/Migrations/20240510003553_Equipment.Designer.cs @@ -0,0 +1,420 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SCHALE.Common.Database; + +#nullable disable + +namespace SCHALE.Common.Migrations +{ + [DbContext(typeof(SCHALEContext))] + [Migration("20240510003553_Equipment")] + partial class Equipment + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("BirthDay") + .HasColumnType("datetime2"); + + b.Property("CallName") + .HasColumnType("nvarchar(max)"); + + b.Property("CallNameUpdateTime") + .HasColumnType("datetime2"); + + b.Property("Comment") + .HasColumnType("nvarchar(max)"); + + b.Property("CreateDate") + .HasColumnType("datetime2"); + + b.Property("DevId") + .HasColumnType("nvarchar(max)"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("LastConnectTime") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("LinkRewardDate") + .HasColumnType("datetime2"); + + b.Property("LobbyMode") + .HasColumnType("int"); + + b.Property("MemoryLobbyUniqueId") + .HasColumnType("bigint"); + + b.Property("Nickname") + .HasColumnType("nvarchar(max)"); + + b.Property("PublisherAccountId") + .HasColumnType("bigint"); + + b.Property("RepresentCharacterServerId") + .HasColumnType("int"); + + b.Property("RetentionDays") + .HasColumnType("int"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("UnReadMailCount") + .HasColumnType("int"); + + b.Property("VIPLevel") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("EquipmentServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EquipmentSlotAndDBIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ExSkillLevel") + .HasColumnType("int"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("ExtraPassiveSkillLevel") + .HasColumnType("int"); + + b.Property("FavorExp") + .HasColumnType("bigint"); + + b.Property("FavorRank") + .HasColumnType("int"); + + b.Property("IsFavorite") + .HasColumnType("bit"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("LeaderSkillLevel") + .HasColumnType("int"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("PassiveSkillLevel") + .HasColumnType("int"); + + b.Property("PotentialStats") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PublicSkillLevel") + .HasColumnType("int"); + + b.Property("StarGrade") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Characters"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("EchelonNumber") + .HasColumnType("bigint"); + + b.Property("EchelonType") + .HasColumnType("int"); + + b.Property("ExtensionType") + .HasColumnType("int"); + + b.Property("LeaderServerId") + .HasColumnType("bigint"); + + b.Property("MainSlotServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SkillCardMulliganCharacterIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SupportSlotServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TSSInteractionServerId") + .HasColumnType("bigint"); + + b.Property("UsingFlag") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Echelons"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("BoundCharacterServerId") + .HasColumnType("bigint"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("StackCount") + .HasColumnType("bigint"); + + b.Property("Tier") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Equipment"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("StackCount") + .HasColumnType("bigint"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Items"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("Complete") + .HasColumnType("bit"); + + b.Property("MissionUniqueId") + .HasColumnType("bigint"); + + b.Property("ProgressParameters") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("MissionProgresses"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b => + { + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("TutorialIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("AccountServerId"); + + b.ToTable("AccountTutorials"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Uid")); + + b.Property("DeviceId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Uid"); + + b.ToTable("GuestAccounts"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Characters") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Echelons") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Equipment") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Items") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("MissionProgresses") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b => + { + b.Navigation("Characters"); + + b.Navigation("Echelons"); + + b.Navigation("Equipment"); + + b.Navigation("Items"); + + b.Navigation("MissionProgresses"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SCHALE.Common/Migrations/20240510003553_Equipment.cs b/SCHALE.Common/Migrations/20240510003553_Equipment.cs new file mode 100644 index 0000000..00a5861 --- /dev/null +++ b/SCHALE.Common/Migrations/20240510003553_Equipment.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SCHALE.Common.Migrations +{ + /// + public partial class Equipment : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Equipment", + columns: table => new + { + ServerId = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Level = table.Column(type: "int", nullable: false), + Exp = table.Column(type: "bigint", nullable: false), + Tier = table.Column(type: "int", nullable: false), + BoundCharacterServerId = table.Column(type: "bigint", nullable: false), + IsLocked = table.Column(type: "bit", nullable: false), + AccountServerId = table.Column(type: "bigint", nullable: false), + UniqueId = table.Column(type: "bigint", nullable: false), + StackCount = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Equipment", x => x.ServerId); + table.ForeignKey( + name: "FK_Equipment_Accounts_AccountServerId", + column: x => x.AccountServerId, + principalTable: "Accounts", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Equipment_AccountServerId", + table: "Equipment", + column: "AccountServerId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Equipment"); + } + } +} diff --git a/SCHALE.Common/Migrations/20240510093842_Weapons.Designer.cs b/SCHALE.Common/Migrations/20240510093842_Weapons.Designer.cs new file mode 100644 index 0000000..9b5a4be --- /dev/null +++ b/SCHALE.Common/Migrations/20240510093842_Weapons.Designer.cs @@ -0,0 +1,469 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SCHALE.Common.Database; + +#nullable disable + +namespace SCHALE.Common.Migrations +{ + [DbContext(typeof(SCHALEContext))] + [Migration("20240510093842_Weapons")] + partial class Weapons + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("BirthDay") + .HasColumnType("datetime2"); + + b.Property("CallName") + .HasColumnType("nvarchar(max)"); + + b.Property("CallNameUpdateTime") + .HasColumnType("datetime2"); + + b.Property("Comment") + .HasColumnType("nvarchar(max)"); + + b.Property("CreateDate") + .HasColumnType("datetime2"); + + b.Property("DevId") + .HasColumnType("nvarchar(max)"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("LastConnectTime") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("LinkRewardDate") + .HasColumnType("datetime2"); + + b.Property("LobbyMode") + .HasColumnType("int"); + + b.Property("MemoryLobbyUniqueId") + .HasColumnType("bigint"); + + b.Property("Nickname") + .HasColumnType("nvarchar(max)"); + + b.Property("PublisherAccountId") + .HasColumnType("bigint"); + + b.Property("RepresentCharacterServerId") + .HasColumnType("int"); + + b.Property("RetentionDays") + .HasColumnType("int"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("UnReadMailCount") + .HasColumnType("int"); + + b.Property("VIPLevel") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("EquipmentServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EquipmentSlotAndDBIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ExSkillLevel") + .HasColumnType("int"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("ExtraPassiveSkillLevel") + .HasColumnType("int"); + + b.Property("FavorExp") + .HasColumnType("bigint"); + + b.Property("FavorRank") + .HasColumnType("int"); + + b.Property("IsFavorite") + .HasColumnType("bit"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("LeaderSkillLevel") + .HasColumnType("int"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("PassiveSkillLevel") + .HasColumnType("int"); + + b.Property("PotentialStats") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PublicSkillLevel") + .HasColumnType("int"); + + b.Property("StarGrade") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Characters"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("EchelonNumber") + .HasColumnType("bigint"); + + b.Property("EchelonType") + .HasColumnType("int"); + + b.Property("ExtensionType") + .HasColumnType("int"); + + b.Property("LeaderServerId") + .HasColumnType("bigint"); + + b.Property("MainSlotServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SkillCardMulliganCharacterIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SupportSlotServerIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TSSInteractionServerId") + .HasColumnType("bigint"); + + b.Property("UsingFlag") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Echelons"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("BoundCharacterServerId") + .HasColumnType("bigint"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("StackCount") + .HasColumnType("bigint"); + + b.Property("Tier") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Equipment"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("StackCount") + .HasColumnType("bigint"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Items"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("Complete") + .HasColumnType("bit"); + + b.Property("MissionUniqueId") + .HasColumnType("bigint"); + + b.Property("ProgressParameters") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("MissionProgresses"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b => + { + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("TutorialIds") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("AccountServerId"); + + b.ToTable("AccountTutorials"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Uid")); + + b.Property("DeviceId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Uid"); + + b.ToTable("GuestAccounts"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("BoundCharacterServerId") + .HasColumnType("bigint"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("StarGrade") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Weapons"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Characters") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Echelons") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Equipment") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Items") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("MissionProgresses") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Weapons") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b => + { + b.Navigation("Characters"); + + b.Navigation("Echelons"); + + b.Navigation("Equipment"); + + b.Navigation("Items"); + + b.Navigation("MissionProgresses"); + + b.Navigation("Weapons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SCHALE.Common/Migrations/20240510093842_Weapons.cs b/SCHALE.Common/Migrations/20240510093842_Weapons.cs new file mode 100644 index 0000000..4987e51 --- /dev/null +++ b/SCHALE.Common/Migrations/20240510093842_Weapons.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SCHALE.Common.Migrations +{ + /// + public partial class Weapons : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Weapons", + columns: table => new + { + ServerId = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + AccountServerId = table.Column(type: "bigint", nullable: false), + UniqueId = table.Column(type: "bigint", nullable: false), + Level = table.Column(type: "int", nullable: false), + Exp = table.Column(type: "bigint", nullable: false), + StarGrade = table.Column(type: "int", nullable: false), + BoundCharacterServerId = table.Column(type: "bigint", nullable: false), + IsLocked = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Weapons", x => x.ServerId); + table.ForeignKey( + name: "FK_Weapons_Accounts_AccountServerId", + column: x => x.AccountServerId, + principalTable: "Accounts", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Weapons_AccountServerId", + table: "Weapons", + column: "AccountServerId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Weapons"); + } + } +} diff --git a/SCHALE.Common/Migrations/SCHALEContextModelSnapshot.cs b/SCHALE.Common/Migrations/SCHALEContextModelSnapshot.cs index 74f3825..7c746db 100644 --- a/SCHALE.Common/Migrations/SCHALEContextModelSnapshot.cs +++ b/SCHALE.Common/Migrations/SCHALEContextModelSnapshot.cs @@ -212,6 +212,45 @@ namespace SCHALE.Common.Migrations b.ToTable("Echelons"); }); + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("BoundCharacterServerId") + .HasColumnType("bigint"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("StackCount") + .HasColumnType("bigint"); + + b.Property("Tier") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Equipment"); + }); + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => { b.Property("ServerId") @@ -305,6 +344,42 @@ namespace SCHALE.Common.Migrations b.ToTable("GuestAccounts"); }); + modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b => + { + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ServerId")); + + b.Property("AccountServerId") + .HasColumnType("bigint"); + + b.Property("BoundCharacterServerId") + .HasColumnType("bigint"); + + b.Property("Exp") + .HasColumnType("bigint"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("StarGrade") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("bigint"); + + b.HasKey("ServerId"); + + b.HasIndex("AccountServerId"); + + b.ToTable("Weapons"); + }); + modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b => { b.HasOne("SCHALE.Common.Database.AccountDB", "Account") @@ -327,6 +402,17 @@ namespace SCHALE.Common.Migrations b.Navigation("Account"); }); + modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Equipment") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b => { b.HasOne("SCHALE.Common.Database.AccountDB", "Account") @@ -349,15 +435,30 @@ namespace SCHALE.Common.Migrations b.Navigation("Account"); }); + modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b => + { + b.HasOne("SCHALE.Common.Database.AccountDB", "Account") + .WithMany("Weapons") + .HasForeignKey("AccountServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b => { b.Navigation("Characters"); b.Navigation("Echelons"); + b.Navigation("Equipment"); + b.Navigation("Items"); b.Navigation("MissionProgresses"); + + b.Navigation("Weapons"); }); #pragma warning restore 612, 618 } diff --git a/SCHALE.Common/NetworkProtocol/protos.cs b/SCHALE.Common/NetworkProtocol/protos.cs index 4190ed2..2d58d92 100644 --- a/SCHALE.Common/NetworkProtocol/protos.cs +++ b/SCHALE.Common/NetworkProtocol/protos.cs @@ -2693,7 +2693,7 @@ namespace SCHALE.Common.NetworkProtocol { get { - return NetworkProtocol.Protocol.None; + return NetworkProtocol.Protocol.Character_SetFavorites; } } public List CharacterDBs { get; set; } @@ -2819,7 +2819,7 @@ namespace SCHALE.Common.NetworkProtocol { get { - return NetworkProtocol.Protocol.None; + return NetworkProtocol.Protocol.Character_BatchSkillLevelUpdate; } } public CharacterDB CharacterDB { get; set; } @@ -2870,7 +2870,7 @@ namespace SCHALE.Common.NetworkProtocol { get { - return NetworkProtocol.Protocol.None; + return NetworkProtocol.Protocol.Clan_Search; } } public List ClanDBs { get; set; } @@ -3487,7 +3487,7 @@ namespace SCHALE.Common.NetworkProtocol { get { - return NetworkProtocol.Protocol.None; + return NetworkProtocol.Protocol.Clan_SetAssist; } } public EchelonType EchelonType { get; set; } @@ -5460,8 +5460,8 @@ namespace SCHALE.Common.NetworkProtocol return NetworkProtocol.Protocol.Equipment_Equip; } } - public CharacterDB CharacterDB; - public List EquipmentDBs; + public CharacterDB CharacterDB { get; set; } + public List EquipmentDBs { get; set; } } @@ -8477,7 +8477,7 @@ namespace SCHALE.Common.NetworkProtocol public bool IsPractice { get; set; } [JsonIgnore] public int LastBossIndex { get; set; } - [JsonIgnore] + //[JsonIgnore] //public IEnumerable RaidBossDamages { get; set; } //[JsonIgnore] //public RaidBossResultCollection RaidBossResults { get; set; } @@ -8712,7 +8712,7 @@ namespace SCHALE.Common.NetworkProtocol } public RaidSeasonType SeasonType { get; set; } public RaidGiveUpDB RaidGiveUpDB { get; set; } - //public SingleRaidLobbyInfoDB RaidLobbyInfoDB { get; set; } + public SingleRaidLobbyInfoDB RaidLobbyInfoDB { get; set; } public AccountCurrencyDB AccountCurrencyDB { get; set; } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs index 6f891cd..c4af67f 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs @@ -170,6 +170,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } } }; }).ToList(); + account.AddCharacters(context, [.. newCharacters]); context.SaveChanges(); @@ -218,6 +219,12 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { var account = sessionKeyService.GetAccount(req.SessionKey); + // add everything manually + //AddAllCharacters(account); + //AddAllEquipment(account); + //AddAllItems(account); + //AddAllWeapons(account); + return new AccountLoginSyncResponse() { AccountCurrencySyncResponse = new AccountCurrencySyncResponse() @@ -230,8 +237,8 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { { CurrencyTypes.Gem, long.MaxValue }, // gacha currency 600 { CurrencyTypes.GemPaid, 0 }, - { CurrencyTypes.GemBonus, 89473598435 }, // default blue gem? - { CurrencyTypes.Gold, long.MaxValue }, // credit 10,000 + { CurrencyTypes.GemBonus, long.MaxValue }, // default blue gem? + { CurrencyTypes.Gold, 962_350_000 }, // credit 10,000 { CurrencyTypes.ActionPoint, long.MaxValue }, // energy 24 { CurrencyTypes.AcademyTicket, 3 }, { CurrencyTypes.ArenaTicket, 5 }, @@ -277,16 +284,21 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { CurrencyTypes.EliminateTicketB, DateTime.Parse("2024-04-26T19:29:12") }, { CurrencyTypes.EliminateTicketC, DateTime.Parse("2024-04-26T19:29:12") }, { CurrencyTypes.EliminateTicketD, DateTime.Parse("2024-04-26T19:29:12") } - } + } } }, CharacterListResponse = new CharacterListResponse() { CharacterDBs = [.. account.Characters], TSSCharacterDBs = [], - WeaponDBs = [], + WeaponDBs = [.. account.Weapons], CostumeDBs = [], }, + ItemListResponse = new ItemListResponse() + { + ItemDBs = [.. account.Items], + }, + EchelonListResponse = new EchelonListResponse() { EchelonDBs = [.. account.Echelons] @@ -309,7 +321,13 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers new() { EventContentId = 900701 }, ], }, - FriendCode = "SCHALE" + + EquipmentItemListResponse = new EquipmentItemListResponse() + { + EquipmentDBs = [.. account.Equipment] + }, + + FriendCode = "SCHALE", }; } @@ -389,13 +407,16 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers public ResponsePacket OpenCondition_EventListHandler(OpenConditionEventListRequest req) { - return new OpenConditionEventListResponse(); + return new OpenConditionEventListResponse() + { + // all open for now ig + StaticOpenConditions = Enum.GetValues(typeof(OpenConditionContent)).Cast().ToDictionary(key => key, key => OpenConditionLockReason.None) + }; } [ProtocolHandler(Protocol.Notification_EventContentReddotCheck)] public ResponsePacket Notification_EventContentReddotCheckHandler(NotificationEventContentReddotRequest req) { - return new NotificationEventContentReddotResponse(); } @@ -405,6 +426,107 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers return new BillingPurchaseListByYostarResponse(); } + + [ProtocolHandler(Protocol.WeekDungeon_List)] + public ResponsePacket WeekDungeon_ListHandler(WeekDungeonListRequest req) + { + return new WeekDungeonListResponse(); + } + + [ProtocolHandler(Protocol.SchoolDungeon_List)] + public ResponsePacket SchoolDungeon_ListHandler(SchoolDungeonListRequest req) + { + return new SchoolDungeonListResponse(); + } + + [ProtocolHandler(Protocol.MiniGame_MissionList)] + public ResponsePacket MiniGame_MissionListHandler(MiniGameMissionListRequest req) + { + return new MiniGameMissionListResponse(); + } + + // these will probably be commands + private void AddAllCharacters(AccountDB account) + { + var characterExcel = excelTableService.GetTable().UnPack().DataList; + var allCharacters = characterExcel.Where(x => x.IsPlayable && x.IsPlayableCharacter && x.CollectionVisible && !account.Characters.Any(c => c.UniqueId == x.Id)).Select(x => + { + return new CharacterDB() + { + UniqueId = x.Id, + StarGrade = x.MaxStarGrade, + Level = 90, + Exp = 0, + PublicSkillLevel = 10, + ExSkillLevel = 5, + PassiveSkillLevel = 10, + ExtraPassiveSkillLevel = 10, + LeaderSkillLevel = 1, + FavorRank = 500, + IsNew = true, + IsLocked = true, + PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } }, + EquipmentServerIds = [0, 0, 0] + }; + }).ToList(); + + account.AddCharacters(context, [.. allCharacters]); + context.SaveChanges(); + } + + private void AddAllEquipment(AccountDB account) + { + var equipmentExcel = excelTableService.GetTable().UnPack().DataList; + var allEquipment = equipmentExcel.Select(x => + { + return new EquipmentDB() + { + UniqueId = x.Id, + Level = 1, + StackCount = 100, // ~ 90,000 cap, auto converted if over + }; + }).ToList(); + + account.AddEquipment(context, [.. allEquipment]); + context.SaveChanges(); + } + + private void AddAllItems(AccountDB account) + { + var itemExcel = excelTableService.GetTable().UnPack().DataList; + var allItems = itemExcel.Select(x => + { + return new ItemDB() + { + IsNew = true, + UniqueId = x.Id, + StackCount = 5555, + }; + }).ToList(); + + account.AddItems(context, [.. allItems]); + context.SaveChanges(); + } + + private void AddAllWeapons(AccountDB account) + { + // only for current characters + var allWeapons = account.Characters.Select(x => + { + return new WeaponDB() + { + UniqueId = x.UniqueId, + BoundCharacterServerId = x.ServerId, + IsLocked = false, + StarGrade = 5, + Level = 70 + }; + }); + + account.AddWeapons(context, [.. allWeapons]); + context.SaveChanges(); + } + } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Character.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Character.cs new file mode 100644 index 0000000..c57c23a --- /dev/null +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Character.cs @@ -0,0 +1,68 @@ +using SCHALE.Common.Database; +using SCHALE.Common.Database.ModelExtensions; +using SCHALE.Common.NetworkProtocol; +using SCHALE.GameServer.Services; + +namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers +{ + public class Character : ProtocolHandlerBase + { + private readonly ISessionKeyService sessionKeyService; + private readonly SCHALEContext context; + private readonly ExcelTableService excelTableService; + + public Character(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) + { + sessionKeyService = _sessionKeyService; + context = _context; + excelTableService = _excelTableService; + } + + [ProtocolHandler(Protocol.Character_SetFavorites)] + public ResponsePacket SetFavoritesHandler(CharacterSetFavoritesRequest req) + { + return new CharacterSetFavoritesResponse(); + } + + [ProtocolHandler(Protocol.Character_UnlockWeapon)] + public ResponsePacket UnlockWeaponHandler(CharacterUnlockWeaponRequest req) + { + var account = sessionKeyService.GetAccount(req.SessionKey); + var newWeapon = new WeaponDB() + { + UniqueId = account.Characters.FirstOrDefault(x => x.ServerId == req.TargetCharacterServerId).UniqueId, + BoundCharacterServerId = req.TargetCharacterServerId, + IsLocked = false, + StarGrade = 1, + Level = 1 + }; + + account.AddWeapons(context, [newWeapon]); + context.SaveChanges(); + + return new CharacterUnlockWeaponResponse() + { + WeaponDB = newWeapon, + }; + } + + [ProtocolHandler(Protocol.Character_PotentialGrowth)] + public ResponsePacket PotentialGrowthHandler(CharacterPotentialGrowthRequest req) + { + var account = sessionKeyService.GetAccount(req.SessionKey); + var targetCharacter = account.Characters.FirstOrDefault(x => x.ServerId == req.TargetCharacterDBId); + + foreach (var growthReq in req.PotentialGrowthRequestDBs) + { + targetCharacter.PotentialStats[(int)growthReq.Type] = growthReq.Level; + } + + context.SaveChanges(); + + return new CharacterPotentialGrowthResponse() + { + CharacterDB = targetCharacter + }; + } + } +} diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Clan.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Clan.cs index 9a17c8c..a3e1c74 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Clan.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Clan.cs @@ -9,11 +9,30 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers [ProtocolHandler(Protocol.Clan_Check)] public ResponsePacket CheckHandler(ClanCheckRequest req) { + return new ClanCheckResponse(); + } - return new ClanCheckResponse() + [ProtocolHandler(Protocol.Clan_AllAssistList)] + public ResponsePacket AllAssistListHandler(ClanAllAssistListRequest req) + { + return new ClanAllAssistListResponse() { - + AssistCharacterDBs = [ + new() { + AccountId = 1, + AssistCharacterServerId = 1, + EchelonType = Common.FlatData.EchelonType.Raid, + AssistRelation = Common.Database.AssistRelation.Friend, + EquipmentDBs = [], + WeaponDB = new(), + NickName = "Arona", + UniqueId = 20024, + } + ], + AssistCharacterRentHistoryDBs = [] }; } + + } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs index 0f732c5..ecfcaee 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs @@ -1,4 +1,6 @@ using SCHALE.Common.Database; +using SCHALE.Common.Database.ModelExtensions; +using SCHALE.Common.FlatData; using SCHALE.Common.NetworkProtocol; using SCHALE.GameServer.Services; @@ -8,11 +10,13 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { private readonly ISessionKeyService sessionKeyService; private readonly SCHALEContext context; + private readonly ExcelTableService excelTableService; - public Echelon(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory) + public Echelon(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) { sessionKeyService = _sessionKeyService; context = _context; + excelTableService = _excelTableService; } [ProtocolHandler(Protocol.Echelon_List)] @@ -25,5 +29,14 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers EchelonDBs = account.Echelons.ToList() }; } + + [ProtocolHandler(Protocol.Echelon_Save)] + public ResponsePacket SaveHandler(EchelonSaveRequest req) + { + return new EchelonSaveResponse() + { + EchelonDB = req.EchelonDB, + }; + } } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Equipment.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Equipment.cs new file mode 100644 index 0000000..45abae3 --- /dev/null +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Equipment.cs @@ -0,0 +1,103 @@ +using SCHALE.Common.Database; +using SCHALE.Common.Database.ModelExtensions; +using SCHALE.Common.NetworkProtocol; +using SCHALE.GameServer.Services; + +namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers +{ + public class Equipment : ProtocolHandlerBase + { + private readonly ISessionKeyService sessionKeyService; + private readonly SCHALEContext context; + private readonly ExcelTableService excelTableService; + + public Equipment(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) + { + sessionKeyService = _sessionKeyService; + context = _context; + excelTableService = _excelTableService; + } + + [ProtocolHandler(Protocol.Equipment_Equip)] + public ResponsePacket EquipHandler(EquipmentItemEquipRequest req) + { + var account = sessionKeyService.GetAccount(req.SessionKey); + + var originalStack = account.Equipment.FirstOrDefault(x => x.ServerId == req.EquipmentServerId); + var newEquipment = new EquipmentDB() + { + UniqueId = originalStack.UniqueId, + Level = originalStack.Level, + StackCount = 1, + BoundCharacterServerId = req.CharacterServerId, + }; + + var equippedCharacter = account.Characters.FirstOrDefault(x => x.ServerId == req.CharacterServerId); + + // remove 1 from original equipment stack + originalStack.StackCount--; + + // add new equipment w BoundCharacterServerId (with different EquipmentServerId) + account.AddEquipment(context, [newEquipment]); + context.SaveChanges(); // (need newEquipment.ServerId in the next line, so save here first, otherwise its 0) + + // set the character's EquipmentServerIds + equippedCharacter.EquipmentServerIds[req.SlotIndex] = newEquipment.ServerId; + + context.SaveChanges(); + + return new EquipmentItemEquipResponse() + { + CharacterDB = equippedCharacter, + EquipmentDBs = [newEquipment, originalStack] + }; + } + + // dont use this, too lazy to implement, just use batch growth ty + [ProtocolHandler(Protocol.Equipment_LevelUp)] + public ResponsePacket LevelUpHandler(EquipmentItemLevelUpRequest req) + { + var account = sessionKeyService.GetAccount(req.SessionKey); + var targetEquipment = account.Equipment.FirstOrDefault(x => x.ServerId == req.TargetServerId); + + targetEquipment.Level = 65; + targetEquipment.Tier = 9; + + context.SaveChanges(); + + return new EquipmentItemLevelUpResponse() + { + EquipmentDB = targetEquipment, + }; + } + + [ProtocolHandler(Protocol.Equipment_BatchGrowth)] + public ResponsePacket Equipment_BatchGrowthHandler(EquipmentBatchGrowthRequest req) + { + var account = sessionKeyService.GetAccount(req.SessionKey); + var upgradedEquipment = new List(); + + foreach (var batchGrowthDB in req.EquipmentBatchGrowthRequestDBs) + { + var targetEquipment = account.Equipment.FirstOrDefault(x => x.ServerId == batchGrowthDB.TargetServerId); + + targetEquipment.Tier = (int)batchGrowthDB.AfterTier; + targetEquipment.Level = (int)batchGrowthDB.AfterLevel; + targetEquipment.UniqueId = targetEquipment.UniqueId + batchGrowthDB.AfterTier - 1; // should prob use excel, im lazyzz... + targetEquipment.IsNew = true; + targetEquipment.StackCount = 1; + + context.SaveChanges(); + upgradedEquipment.Add(targetEquipment); + } + + context.SaveChanges(); + + return new EquipmentBatchGrowthResponse() + { + EquipmentDBs = upgradedEquipment, + }; + } + + } +} diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Item.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Item.cs index c045f58..0a27456 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Item.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Item.cs @@ -26,5 +26,13 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers ExpiryItemDBs = [] }; } + + [ProtocolHandler(Protocol.Item_AutoSynth)] + public ResponsePacket AutoSynthHandler(ItemAutoSynthRequest req) + { + return new ItemAutoSynthResponse() + { + }; + } } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Raid.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Raid.cs new file mode 100644 index 0000000..5eef9a7 --- /dev/null +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Raid.cs @@ -0,0 +1,65 @@ +using SCHALE.Common.Database; +using SCHALE.Common.NetworkProtocol; +using SCHALE.GameServer.Services; + +namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers +{ + public class Raid : ProtocolHandlerBase + { + private readonly ISessionKeyService sessionKeyService; + private readonly SCHALEContext context; + private readonly ExcelTableService excelTableService; + + public Raid(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) + { + sessionKeyService = _sessionKeyService; + context = _context; + excelTableService = _excelTableService; + } + + [ProtocolHandler(Protocol.Raid_Lobby)] + public ResponsePacket LobbyHandler(RaidLobbyRequest req) + { + return new RaidLobbyResponse() + { + + }; + } + + [ProtocolHandler(Protocol.Raid_OpponentList)] + public ResponsePacket OpponentListHandler(RaidOpponentListRequest req) + { + return new RaidOpponentListResponse() + { + OpponentUserDBs = [] + }; + } + + [ProtocolHandler(Protocol.Raid_CreateBattle)] + public ResponsePacket CreateBattleHandller(RaidCreateBattleRequest req) + { + return new RaidCreateBattleResponse() + { + + }; + } + + [ProtocolHandler(Protocol.Raid_EnterBattle)] // clicked restart + public ResponsePacket EnterBattleHandler(RaidEnterBattleRequest req) + { + return new RaidEnterBattleResponse() + { + + }; + } + + [ProtocolHandler(Protocol.Raid_EndBattle)] + public ResponsePacket EndBattleHandler(RaidEndBattleRequest req) + { + return new RaidEndBattleResponse() + { + + }; + } + } +} diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Scenario.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Scenario.cs index 9fef772..13a875c 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Scenario.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Scenario.cs @@ -10,10 +10,6 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers [ProtocolHandler(Protocol.Scenario_Skip)] public ResponsePacket SkipHandler(ScenarioSkipRequest req) { - Log.Debug($"ScenarioSkipRequest ScriptGroupId:" + req.ScriptGroupId); - Log.Debug($"ScenarioSkipRequest SkipPointScriptCount: " + req.SkipPointScriptCount); - - // skip story doesn't work yet, probably need to implement missiondb return new ScenarioSkipResponse(); } @@ -22,5 +18,11 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { return new ScenarioSelectResponse(); } + + [ProtocolHandler(Protocol.Scenario_GroupHistoryUpdate)] + public ResponsePacket GroupHistoryUpdateHandler(ScenarioGroupHistoryUpdateRequest req) + { + return new ScenarioGroupHistoryUpdateResponse(); + } } } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Shop.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Shop.cs index f820bc9..4482094 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Shop.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Shop.cs @@ -27,15 +27,14 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers [ProtocolHandler(Protocol.Shop_BeforehandGachaRun)] public ResponsePacket BeforehandGachaRunHandler(ShopBeforehandGachaRunRequest req) { - // character ids here, just some limited 3 stars for now for fun - SavedGachaResults = [10059, 20007, 10033, 10074, 10045, 10053, 10054, 10021, 20022, 10057]; + SavedGachaResults = [16003, 16003, 16003, 16003, 16003, 16003, 16003, 16003, 16003, 16003]; return new ShopBeforehandGachaRunResponse() { SelectGachaSnapshot = new BeforehandGachaSnapshotDB() { ShopUniqueId = 3, - GoodsId = 1, + GoodsId = 1, LastResults = SavedGachaResults } }; @@ -46,7 +45,12 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { return new ShopBeforehandGachaSaveResponse() { - + SelectGachaSnapshot = new BeforehandGachaSnapshotDB() + { + ShopUniqueId = 3, + GoodsId = 1, + LastResults = SavedGachaResults + } }; } @@ -85,6 +89,53 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers }; } + [ProtocolHandler(Protocol.Shop_BuyGacha3)] + public ResponsePacket ShopBuyGacha3ResponseHandler(ShopBuyGacha3Request req) + { + var gachaResults = new List(); + + for (int i = 0; i < 10; i++) + { + long id = 10000 + new Random().Next(0, 94); + + gachaResults.Add(new(id) + { + Character = new() // hardcoded util proper db + { + ServerId = req.AccountId, + UniqueId = 20007, + StarGrade = 3, + Level = 1, + FavorRank = 1, + PublicSkillLevel = 1, + ExSkillLevel = 1, + PassiveSkillLevel = 1, + ExtraPassiveSkillLevel = 1, + LeaderSkillLevel = 1, + IsNew = true, + IsLocked = true + } + }); + } + + return new ShopBuyGacha3Response() + { + UpdateTime = DateTime.UtcNow, + GemBonusRemain = long.MaxValue, + ConsumedItems = [], + AcquiredItems = [], + MissionProgressDBs = [], + }; + } + + [ProtocolHandler(Protocol.Shop_List)] + public ResponsePacket ListHandler(ShopListRequest req) + { + return new ShopListResponse() + { + ShopInfos = [] + }; + } } }