sql server + items,character,tuts & echelons impl.

This commit is contained in:
rfi 2024-05-01 16:11:11 +07:00
parent 56f6826cfe
commit e96ebfd33f
34 changed files with 2330 additions and 347 deletions

3
.gitignore vendored
View File

@ -361,3 +361,6 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# EF migration
efbundle.exe

View File

@ -153,55 +153,4 @@ namespace SCHALE.Common.Crypto
return Encoding.Unicode.GetString(strBytes);
}
}
public static class FlatBuffersExtension
{
private static readonly Dictionary<Type, PropertyInfo[]> propertiesCache = [];
private static readonly Dictionary<Type, byte[]> keyCache = [];
/// <summary>
/// <b>Only</b> to be invoked by ExcelT, and only be invoked <b>once</b> per object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="table"></param>
public static void Decode<T>(this T table) where T : class
{
var type = table.GetType();
PropertyInfo[] props;
if (!propertiesCache.TryGetValue(type, out props!))
{
props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
propertiesCache.Add(type, props);
}
foreach (var prop in props)
{
byte[] key;
if (!keyCache.TryGetValue(type, out key!))
{
key = TableEncryptionService.CreateKey(type.Name.Replace("ExcelT", ""));
keyCache.Add(type, key);
}
var baseType = prop.PropertyType.Name == "List`1" ? prop.PropertyType.GenericTypeArguments[0] : prop.PropertyType;
var convertMethod = TableEncryptionService.GetConvertMethod(baseType.IsEnum ? Enum.GetUnderlyingType(baseType) : baseType);
if (convertMethod is not null)
{
if (prop.PropertyType.Name == "List`1")
{
var list = (IList)prop.GetValue(table, null)!;
for (int i = 0; i < list.Count; i++)
{
list[i] = convertMethod.Invoke(null, [list[i], key]);
}
}
else
{
prop.SetValue(table, convertMethod.Invoke(null, [prop.GetValue(table, null), key]));
}
}
}
}
}
}

View File

@ -40,7 +40,7 @@ namespace SCHALE.Common.Crypto
{
foreach (var type in Assembly.GetAssembly(typeof(AcademyFavorScheduleExcelTable))!.GetTypes().Where(t => t.IsAssignableTo(typeof(IFlatbufferObject)) && t.Name.EndsWith("ExcelTable")))
{
var bytesFilePath = Path.Join(bytesDir, $"{type.Name}.bytes");
var bytesFilePath = Path.Join(bytesDir, $"{type.Name.ToLower()}.bytes");
if (!File.Exists(bytesFilePath))
{
Console.WriteLine($"bytes files for {type.Name} not found. skipping...");

View File

@ -0,0 +1,16 @@
namespace SCHALE.Common.Database.ModelExtensions
{
public static class AccountExtensions
{
public static List<CharacterDB> AddCharacters(this AccountDB account, SCHALEContext context, params CharacterDB[] characters)
{
foreach (var character in characters)
{
character.AccountServerId = account.ServerId;
context.Characters.Add(character);
}
return [.. characters];
}
}
}

View File

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace SCHALE.Common.Database.Models
{
public class AccountTutorial
{
[Key]
public required long AccountServerId { get; set; }
public List<long> TutorialIds { get; set; }
}
}

View File

@ -7,7 +7,6 @@ namespace SCHALE.Common.Database.Models
public class GuestAccount
{
[Key]
[Column("_id")]
public long Uid { get; set; }
public string DeviceId { get; set; }

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ValueGeneration;
using MongoDB.EntityFrameworkCore.Extensions;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Newtonsoft.Json;
using SCHALE.Common.Database.Models;
namespace SCHALE.Common.Database
@ -11,7 +11,15 @@ namespace SCHALE.Common.Database
public DbSet<GuestAccount> GuestAccounts { get; set; }
public DbSet<AccountDB> Accounts { get; set; }
public DbSet<MissionProgressDB> MissionProgresses { get; set; }
public DbSet<Counter> Counters { get; set; }
public DbSet<ItemDB> Items { get; set; }
public DbSet<CharacterDB> Characters { get; set; }
public DbSet<EchelonDB> Echelons { get; set; }
public DbSet<AccountTutorial> AccountTutorials { get; set; }
public static SCHALEContext Create(string connectionString) =>
new(new DbContextOptionsBuilder<SCHALEContext>()
.UseSqlServer(connectionString)
.Options);
public SCHALEContext(DbContextOptions<SCHALEContext> options) : base(options)
{
@ -21,59 +29,53 @@ namespace SCHALE.Common.Database
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<GuestAccount>().Property(x => x.Uid).HasValueGenerator<GuestAccountAutoIncrementValueGenerator>();
modelBuilder.Entity<GuestAccount>().ToCollection("guest_accounts");
modelBuilder.Entity<GuestAccount>().Property(x => x.Uid).ValueGeneratedOnAdd();
modelBuilder.Entity<AccountDB>().Property(x => x.ServerId).HasValueGenerator<AccountAutoIncrementValueGenerator>();
modelBuilder.Entity<AccountDB>().ToCollection("accounts");
modelBuilder.Entity<AccountDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<AccountDB>()
.HasMany(x => x.Items)
.WithOne(x => x.Account)
.HasForeignKey(x => x.AccountServerId)
.IsRequired();
modelBuilder.Entity<AccountDB>()
.HasMany(x => x.Characters)
.WithOne(x => x.Account)
.HasForeignKey(x => x.AccountServerId)
.IsRequired();
modelBuilder.Entity<AccountDB>()
.HasMany(x => x.MissionProgresses)
.WithOne(x => x.Account)
.HasForeignKey(x => x.AccountServerId)
.IsRequired();
modelBuilder.Entity<MissionProgressDB>().Property(x => x.ServerId).HasValueGenerator<MissionProgressAutoIncrementValueGenerator>();
modelBuilder.Entity<MissionProgressDB>().ToCollection("mission_progresses");
modelBuilder.Entity<ItemDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<EchelonDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<Counter>().ToCollection("counters");
modelBuilder.Entity<CharacterDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<CharacterDB>().Property(x => x.EquipmentSlotAndDBIds).HasJsonConversion();
modelBuilder.Entity<CharacterDB>().Property(x => x.PotentialStats).HasJsonConversion();
modelBuilder.Entity<AccountTutorial>().Property(x => x.AccountServerId).ValueGeneratedNever();
modelBuilder.Entity<MissionProgressDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<MissionProgressDB>().Property(x => x.ProgressParameters).HasJsonConversion();
}
}
private class AccountAutoIncrementValueGenerator : AutoIncrementValueGenerator
public static class PropertyBuilderExtensions
{
protected override string Collection => "account";
}
private class GuestAccountAutoIncrementValueGenerator : AutoIncrementValueGenerator
public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder) where T : class, new()
{
protected override string Collection => "guest_account";
}
ValueConverter<T, string> converter = new
(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<T>(v) ?? new T()
);
private class MissionProgressAutoIncrementValueGenerator : AutoIncrementValueGenerator
{
protected override string Collection => "mission_progress";
}
propertyBuilder.HasConversion(converter);
propertyBuilder.Metadata.SetValueConverter(converter);
private abstract class AutoIncrementValueGenerator : ValueGenerator<long>
{
protected abstract string Collection { get; }
public override bool GeneratesTemporaryValues => false;
public override long Next(EntityEntry entry)
{
if (entry.Context is not SCHALEContext)
{
throw new ArgumentNullException($"{nameof(AutoIncrementValueGenerator)} is only implemented for {nameof(SCHALEContext)}");
}
var context = ((SCHALEContext)entry.Context);
var counter = context.Counters.SingleOrDefault(x => x.Id == Collection);
if (counter is null)
{
counter = new Counter() { Id = Collection, Seq = 0 };
context.Add(counter);
}
counter.Seq++;
context.SaveChanges();
return counter.Seq;
}
return propertyBuilder;
}
}
}

View File

@ -1,19 +1,19 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
namespace SCHALE.Common.Database
{
public static class ServicesExtesions
{
public static void AddMongoDBProvider(this IServiceCollection services, string connectionString)
public static void AddSQLServerProvider(this IServiceCollection services, string connectionString)
{
services.AddDbContext<SCHALEContext>(opt =>
services.AddDbContext<SCHALEContext>(o =>
{
opt.UseMongoDB(connectionString, "SCHALE");
o.UseSqlServer(connectionString, b =>
{
b.EnableRetryOnFailure(5, TimeSpan.FromSeconds(10), null);
})
.UseLazyLoadingProxies();
}, ServiceLifetime.Singleton, ServiceLifetime.Singleton);
}
}

View File

@ -1,9 +1,9 @@
using Newtonsoft.Json;
using SCHALE.Common.FlatData;
using SCHALE.Common.NetworkProtocol;
using SCHALE.Common.Parcel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace SCHALE.Common.Database
{
@ -185,6 +185,18 @@ namespace SCHALE.Common.Database
public class AccountDB
{
[JsonIgnore]
public virtual ICollection<ItemDB> Items { get; }
[JsonIgnore]
public virtual ICollection<CharacterDB> Characters { get; }
[JsonIgnore]
public virtual ICollection<MissionProgressDB> MissionProgresses { get; }
[JsonIgnore]
public virtual ICollection<EchelonDB> Echelons { get; }
public AccountDB() { }
public AccountDB(long publisherAccountId)
@ -197,14 +209,13 @@ namespace SCHALE.Common.Database
}
[Key]
[Column("_id")]
public long ServerId { get; set; }
public string Nickname { get; set; }
public string? Nickname { get; set; }
public string CallName { get; set; }
public string? CallName { get; set; }
public string DevId { get; set; }
public string? DevId { get; set; }
public AccountState State { get; set; }
@ -212,7 +223,7 @@ namespace SCHALE.Common.Database
public long Exp { get; set; }
public string Comment { get; set; }
public string? Comment { get; set; }
public int LobbyMode { get; set; }
@ -222,7 +233,7 @@ namespace SCHALE.Common.Database
public DateTime LastConnectTime { get; set; }
public DateTime BirthDay { get; set; }
public DateTime? BirthDay { get; set; }
public DateTime CallNameUpdateTime { get; set; }
@ -429,6 +440,8 @@ namespace SCHALE.Common.Database
public int CafeRank { get; set; }
public DateTime LastUpdate { get; set; }
public DateTime? LastSummonDate { get; set; }
[NotMapped]
public bool IsNew { get; set; }
public Dictionary<long, CafeCharacterDB> CafeVisitCharacterDBs { get; set; }
public List<FurnitureDB> FurnitureDBs { get; set; }
@ -560,11 +573,20 @@ namespace SCHALE.Common.Database
public class CharacterDB : ParcelBase
{
[NotMapped]
public override ParcelType Type { get => ParcelType.Character; }
[JsonIgnore]
public virtual AccountDB Account { get; set; }
[JsonIgnore]
public long AccountServerId { get; set; }
[JsonIgnore]
[NotMapped]
public override IEnumerable<ParcelInfo> ParcelInfos { get; }
[Key]
public long ServerId { get; set; }
public long UniqueId { get; set; }
public int StarGrade { get; set; }
@ -577,12 +599,14 @@ namespace SCHALE.Common.Database
public int PassiveSkillLevel { get; set; }
public int ExtraPassiveSkillLevel { get; set; }
public int LeaderSkillLevel { get; set; }
[NotMapped]
public bool IsNew { get; set; }
public bool IsLocked { get; set; }
public bool IsFavorite { get; set; }
public List<long> EquipmentServerIds { get; set; }
public Dictionary<int, int> PotentialStats { get; set; } = new() { };
public Dictionary<int, long> EquipmentSlotAndDBIds { get; set; }
public List<long> EquipmentServerIds { get; set; } = [];
public Dictionary<int, int> PotentialStats { get; set; } = [];
public Dictionary<int, long> EquipmentSlotAndDBIds { get; set; } = [];
}
@ -831,12 +855,19 @@ namespace SCHALE.Common.Database
public abstract class ConsumableItemBaseDB : ParcelBase
{
[JsonIgnore]
public virtual AccountDB Account { get; set; }
[JsonIgnore]
public abstract bool CanConsume { get; }
[JsonIgnore]
public ParcelKeyPair Key { get; }
[JsonIgnore]
public long AccountServerId { get; set; }
[Key]
public long ServerId { get; set; }
public long UniqueId { get; set; }
@ -1002,22 +1033,23 @@ namespace SCHALE.Common.Database
public class EchelonDB
{
[Key]
[JsonIgnore]
public long ServerId { get; set; }
[JsonIgnore]
public virtual AccountDB Account { get; set; }
public long AccountServerId { get; set; }
public EchelonType EchelonType { get; set; }
public long EchelonNumber { get; set; }
public EchelonExtensionType ExtensionType { get; set; }
public long LeaderServerId { get; set; }
public int MainSlotCount { get; set; }
public int SupportSlotCount { get; set; }
public List<long> MainSlotServerIds { get; set; }
public List<long> SupportSlotServerIds { get; set; }
public List<long> MainSlotServerIds { get; set; } = [];
public List<long> SupportSlotServerIds { get; set; } = [];
public long TSSInteractionServerId { get; set; }
public EchelonStatusFlag UsingFlag { get; set; }
public bool IsUsing { get; set; }
public List<long> AllCharacterServerIds { get; set; }
public List<long> AllCharacterWithoutTSSServerIds { get; set; }
public List<long> BattleCharacterServerIds { get; set; }
public List<long> SkillCardMulliganCharacterIds { get; set; }
public List<long> SkillCardMulliganCharacterIds { get; set; } = [];
}
@ -1088,6 +1120,8 @@ namespace SCHALE.Common.Database
public long Exp { get; set; }
public int Tier { get; set; }
public long BoundCharacterServerId { get; set; }
[NotMapped]
public bool IsNew { get; set; }
public bool IsLocked { get; set; }
}
@ -1464,15 +1498,20 @@ namespace SCHALE.Common.Database
public class ItemDB : ConsumableItemBaseDB
{
public override ParcelType Type { get => ParcelType.Item; }
[NotMapped]
public override ParcelType Type => ParcelType.Item;
[NotMapped]
[JsonIgnore]
public override IEnumerable<ParcelInfo> ParcelInfos { get; }
[NotMapped]
[JsonIgnore]
public override bool CanConsume { get; }
public override bool CanConsume => true;
[NotMapped]
public bool IsNew { get; set; }
public bool IsLocked { get; set; }
}
@ -1566,32 +1605,19 @@ namespace SCHALE.Common.Database
public class MissionProgressDB
{
[Key]
[Column("_id")]
[JsonIgnore]
public long ServerId { get; set; }
[JsonIgnore]
public virtual AccountDB Account { get; set; }
[JsonIgnore]
public long AccountServerId { get; set; }
public long MissionUniqueId { get; set; }
public bool Complete { get; set; }
public DateTime StartTime { get; set; }
[JsonIgnore]
public string SerializedProgressParameters { get; private set; } = "{}";
[NotMapped]
public Dictionary<long, long> ProgressParameters
{
get
{
return JsonConvert.DeserializeObject<Dictionary<long, long>>(SerializedProgressParameters) ?? [];
}
set
{
SerializedProgressParameters = JsonConvert.SerializeObject(value);
}
}
public Dictionary<long, long> ProgressParameters { get; set; } = [];
}

View File

@ -20,11 +20,11 @@ public struct Form : IFlatbufferObject
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public Form __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public SCHALE.Common.FlatData.MoveEndTable? MoveEnd { get { int o = __p.__offset(4); return o != 0 ? (SCHALE.Common.FlatData.MoveEndTable?)(new SCHALE.Common.FlatData.MoveEndTable()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public SCHALE.Common.FlatData.MoveEnd? MoveEnd { get { int o = __p.__offset(4); return o != 0 ? (SCHALE.Common.FlatData.MoveEnd?)(new SCHALE.Common.FlatData.MoveEnd()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public SCHALE.Common.FlatData.Motion? PublicSkill { get { int o = __p.__offset(6); return o != 0 ? (SCHALE.Common.FlatData.Motion?)(new SCHALE.Common.FlatData.Motion()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public static Offset<SCHALE.Common.FlatData.Form> CreateForm(FlatBufferBuilder builder,
Offset<SCHALE.Common.FlatData.MoveEndTable> MoveEndOffset = default(Offset<SCHALE.Common.FlatData.MoveEndTable>),
Offset<SCHALE.Common.FlatData.MoveEnd> MoveEndOffset = default(Offset<SCHALE.Common.FlatData.MoveEnd>),
Offset<SCHALE.Common.FlatData.Motion> PublicSkillOffset = default(Offset<SCHALE.Common.FlatData.Motion>)) {
builder.StartTable(2);
Form.AddPublicSkill(builder, PublicSkillOffset);
@ -33,7 +33,7 @@ public struct Form : IFlatbufferObject
}
public static void StartForm(FlatBufferBuilder builder) { builder.StartTable(2); }
public static void AddMoveEnd(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.MoveEndTable> moveEndOffset) { builder.AddOffset(0, moveEndOffset.Value, 0); }
public static void AddMoveEnd(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.MoveEnd> moveEndOffset) { builder.AddOffset(0, moveEndOffset.Value, 0); }
public static void AddPublicSkill(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.Motion> publicSkillOffset) { builder.AddOffset(1, publicSkillOffset.Value, 0); }
public static Offset<SCHALE.Common.FlatData.Form> EndForm(FlatBufferBuilder builder) {
int o = builder.EndTable();
@ -51,7 +51,7 @@ public struct Form : IFlatbufferObject
}
public static Offset<SCHALE.Common.FlatData.Form> Pack(FlatBufferBuilder builder, FormT _o) {
if (_o == null) return default(Offset<SCHALE.Common.FlatData.Form>);
var _MoveEnd = _o.MoveEnd == null ? default(Offset<SCHALE.Common.FlatData.MoveEndTable>) : SCHALE.Common.FlatData.MoveEndTable.Pack(builder, _o.MoveEnd);
var _MoveEnd = _o.MoveEnd == null ? default(Offset<SCHALE.Common.FlatData.MoveEnd>) : SCHALE.Common.FlatData.MoveEnd.Pack(builder, _o.MoveEnd);
var _PublicSkill = _o.PublicSkill == null ? default(Offset<SCHALE.Common.FlatData.Motion>) : SCHALE.Common.FlatData.Motion.Pack(builder, _o.PublicSkill);
return CreateForm(
builder,
@ -62,7 +62,7 @@ public struct Form : IFlatbufferObject
public class FormT
{
public SCHALE.Common.FlatData.MoveEndTableT MoveEnd { get; set; }
public SCHALE.Common.FlatData.MoveEndT MoveEnd { get; set; }
public SCHALE.Common.FlatData.MotionT PublicSkill { get; set; }
public FormT() {
@ -77,7 +77,7 @@ static public class FormVerify
static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
{
return verifier.VerifyTableStart(tablePos)
&& verifier.VerifyTable(tablePos, 4 /*MoveEnd*/, SCHALE.Common.FlatData.MoveEndTableVerify.Verify, false)
&& verifier.VerifyTable(tablePos, 4 /*MoveEnd*/, SCHALE.Common.FlatData.MoveEndVerify.Verify, false)
&& verifier.VerifyTable(tablePos, 6 /*PublicSkill*/, SCHALE.Common.FlatData.MotionVerify.Verify, false)
&& verifier.VerifyTableEnd(tablePos);
}

View File

@ -10,56 +10,56 @@ using global::System.Collections.Generic;
using global::SCHALE.Common.Crypto;
using global::Google.FlatBuffers;
public struct MoveEndTable : IFlatbufferObject
public struct MoveEnd : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_24_3_25(); }
public static MoveEndTable GetRootAsMoveEndTable(ByteBuffer _bb) { return GetRootAsMoveEndTable(_bb, new MoveEndTable()); }
public static MoveEndTable GetRootAsMoveEndTable(ByteBuffer _bb, MoveEndTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static MoveEnd GetRootAsMoveEnd(ByteBuffer _bb) { return GetRootAsMoveEnd(_bb, new MoveEnd()); }
public static MoveEnd GetRootAsMoveEnd(ByteBuffer _bb, MoveEnd obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public MoveEndTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public MoveEnd __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public SCHALE.Common.FlatData.Motion? Normal { get { int o = __p.__offset(4); return o != 0 ? (SCHALE.Common.FlatData.Motion?)(new SCHALE.Common.FlatData.Motion()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public SCHALE.Common.FlatData.Motion? Stand { get { int o = __p.__offset(6); return o != 0 ? (SCHALE.Common.FlatData.Motion?)(new SCHALE.Common.FlatData.Motion()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public SCHALE.Common.FlatData.Motion? Kneel { get { int o = __p.__offset(8); return o != 0 ? (SCHALE.Common.FlatData.Motion?)(new SCHALE.Common.FlatData.Motion()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public static Offset<SCHALE.Common.FlatData.MoveEndTable> CreateMoveEndTable(FlatBufferBuilder builder,
public static Offset<SCHALE.Common.FlatData.MoveEnd> CreateMoveEnd(FlatBufferBuilder builder,
Offset<SCHALE.Common.FlatData.Motion> NormalOffset = default(Offset<SCHALE.Common.FlatData.Motion>),
Offset<SCHALE.Common.FlatData.Motion> StandOffset = default(Offset<SCHALE.Common.FlatData.Motion>),
Offset<SCHALE.Common.FlatData.Motion> KneelOffset = default(Offset<SCHALE.Common.FlatData.Motion>)) {
builder.StartTable(3);
MoveEndTable.AddKneel(builder, KneelOffset);
MoveEndTable.AddStand(builder, StandOffset);
MoveEndTable.AddNormal(builder, NormalOffset);
return MoveEndTable.EndMoveEndTable(builder);
MoveEnd.AddKneel(builder, KneelOffset);
MoveEnd.AddStand(builder, StandOffset);
MoveEnd.AddNormal(builder, NormalOffset);
return MoveEnd.EndMoveEnd(builder);
}
public static void StartMoveEndTable(FlatBufferBuilder builder) { builder.StartTable(3); }
public static void StartMoveEnd(FlatBufferBuilder builder) { builder.StartTable(3); }
public static void AddNormal(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.Motion> normalOffset) { builder.AddOffset(0, normalOffset.Value, 0); }
public static void AddStand(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.Motion> standOffset) { builder.AddOffset(1, standOffset.Value, 0); }
public static void AddKneel(FlatBufferBuilder builder, Offset<SCHALE.Common.FlatData.Motion> kneelOffset) { builder.AddOffset(2, kneelOffset.Value, 0); }
public static Offset<SCHALE.Common.FlatData.MoveEndTable> EndMoveEndTable(FlatBufferBuilder builder) {
public static Offset<SCHALE.Common.FlatData.MoveEnd> EndMoveEnd(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<SCHALE.Common.FlatData.MoveEndTable>(o);
return new Offset<SCHALE.Common.FlatData.MoveEnd>(o);
}
public MoveEndTableT UnPack() {
var _o = new MoveEndTableT();
public MoveEndT UnPack() {
var _o = new MoveEndT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(MoveEndTableT _o) {
public void UnPackTo(MoveEndT _o) {
byte[] key = { 0 };
_o.Normal = this.Normal.HasValue ? this.Normal.Value.UnPack() : null;
_o.Stand = this.Stand.HasValue ? this.Stand.Value.UnPack() : null;
_o.Kneel = this.Kneel.HasValue ? this.Kneel.Value.UnPack() : null;
}
public static Offset<SCHALE.Common.FlatData.MoveEndTable> Pack(FlatBufferBuilder builder, MoveEndTableT _o) {
if (_o == null) return default(Offset<SCHALE.Common.FlatData.MoveEndTable>);
public static Offset<SCHALE.Common.FlatData.MoveEnd> Pack(FlatBufferBuilder builder, MoveEndT _o) {
if (_o == null) return default(Offset<SCHALE.Common.FlatData.MoveEnd>);
var _Normal = _o.Normal == null ? default(Offset<SCHALE.Common.FlatData.Motion>) : SCHALE.Common.FlatData.Motion.Pack(builder, _o.Normal);
var _Stand = _o.Stand == null ? default(Offset<SCHALE.Common.FlatData.Motion>) : SCHALE.Common.FlatData.Motion.Pack(builder, _o.Stand);
var _Kneel = _o.Kneel == null ? default(Offset<SCHALE.Common.FlatData.Motion>) : SCHALE.Common.FlatData.Motion.Pack(builder, _o.Kneel);
return CreateMoveEndTable(
return CreateMoveEnd(
builder,
_Normal,
_Stand,
@ -67,13 +67,13 @@ public struct MoveEndTable : IFlatbufferObject
}
}
public class MoveEndTableT
public class MoveEndT
{
public SCHALE.Common.FlatData.MotionT Normal { get; set; }
public SCHALE.Common.FlatData.MotionT Stand { get; set; }
public SCHALE.Common.FlatData.MotionT Kneel { get; set; }
public MoveEndTableT() {
public MoveEndT() {
this.Normal = null;
this.Stand = null;
this.Kneel = null;
@ -81,7 +81,7 @@ public class MoveEndTableT
}
static public class MoveEndTableVerify
static public class MoveEndVerify
{
static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
{

View File

@ -0,0 +1,189 @@
// <auto-generated />
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("20240501053823_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Token")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Uid");
b.ToTable("GuestAccounts");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,124 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SCHALE.Common.Migrations
{
/// <inheritdoc />
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Accounts",
columns: table => new
{
ServerId = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Nickname = table.Column<string>(type: "nvarchar(max)", nullable: true),
CallName = table.Column<string>(type: "nvarchar(max)", nullable: true),
DevId = table.Column<string>(type: "nvarchar(max)", nullable: true),
State = table.Column<int>(type: "int", nullable: false),
Level = table.Column<int>(type: "int", nullable: false),
Exp = table.Column<long>(type: "bigint", nullable: false),
Comment = table.Column<string>(type: "nvarchar(max)", nullable: true),
LobbyMode = table.Column<int>(type: "int", nullable: false),
RepresentCharacterServerId = table.Column<int>(type: "int", nullable: false),
MemoryLobbyUniqueId = table.Column<long>(type: "bigint", nullable: false),
LastConnectTime = table.Column<DateTime>(type: "datetime2", nullable: false),
BirthDay = table.Column<DateTime>(type: "datetime2", nullable: true),
CallNameUpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
PublisherAccountId = table.Column<long>(type: "bigint", nullable: false),
RetentionDays = table.Column<int>(type: "int", nullable: true),
VIPLevel = table.Column<int>(type: "int", nullable: true),
CreateDate = table.Column<DateTime>(type: "datetime2", nullable: false),
UnReadMailCount = table.Column<int>(type: "int", nullable: true),
LinkRewardDate = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Accounts", x => x.ServerId);
});
migrationBuilder.CreateTable(
name: "AccountTutorials",
columns: table => new
{
AccountServerId = table.Column<long>(type: "bigint", nullable: false),
TutorialIds = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AccountTutorials", x => x.AccountServerId);
});
migrationBuilder.CreateTable(
name: "GuestAccounts",
columns: table => new
{
Uid = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
DeviceId = table.Column<string>(type: "nvarchar(max)", nullable: false),
Token = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GuestAccounts", x => x.Uid);
});
migrationBuilder.CreateTable(
name: "Items",
columns: table => new
{
ServerId = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
IsLocked = table.Column<bool>(type: "bit", nullable: false),
AccountServerId = table.Column<long>(type: "bigint", nullable: false),
UniqueId = table.Column<long>(type: "bigint", nullable: false),
StackCount = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Items", x => x.ServerId);
});
migrationBuilder.CreateTable(
name: "MissionProgresses",
columns: table => new
{
ServerId = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
AccountServerId = table.Column<long>(type: "bigint", nullable: false),
MissionUniqueId = table.Column<long>(type: "bigint", nullable: false),
Complete = table.Column<bool>(type: "bit", nullable: false),
StartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
ProgressParameters = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MissionProgresses", x => x.ServerId);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Accounts");
migrationBuilder.DropTable(
name: "AccountTutorials");
migrationBuilder.DropTable(
name: "GuestAccounts");
migrationBuilder.DropTable(
name: "Items");
migrationBuilder.DropTable(
name: "MissionProgresses");
}
}
}

View File

@ -0,0 +1,307 @@
// <auto-generated />
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("20240501071717_CharacterAndRelations")]
partial class CharacterAndRelations
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("EquipmentServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("EquipmentSlotAndDBIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ExSkillLevel")
.HasColumnType("int");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("ExtraPassiveSkillLevel")
.HasColumnType("int");
b.Property<long>("FavorExp")
.HasColumnType("bigint");
b.Property<int>("FavorRank")
.HasColumnType("int");
b.Property<bool>("IsFavorite")
.HasColumnType("bit");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<bool>("IsNew")
.HasColumnType("bit");
b.Property<int>("LeaderSkillLevel")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PassiveSkillLevel")
.HasColumnType("int");
b.Property<string>("PotentialStats")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PublicSkillLevel")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Characters");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("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.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("Items");
b.Navigation("MissionProgresses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,104 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SCHALE.Common.Migrations
{
/// <inheritdoc />
public partial class CharacterAndRelations : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Characters",
columns: table => new
{
ServerId = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
AccountServerId = table.Column<long>(type: "bigint", nullable: false),
UniqueId = table.Column<long>(type: "bigint", nullable: false),
StarGrade = table.Column<int>(type: "int", nullable: false),
Level = table.Column<int>(type: "int", nullable: false),
Exp = table.Column<long>(type: "bigint", nullable: false),
FavorRank = table.Column<int>(type: "int", nullable: false),
FavorExp = table.Column<long>(type: "bigint", nullable: false),
PublicSkillLevel = table.Column<int>(type: "int", nullable: false),
ExSkillLevel = table.Column<int>(type: "int", nullable: false),
PassiveSkillLevel = table.Column<int>(type: "int", nullable: false),
ExtraPassiveSkillLevel = table.Column<int>(type: "int", nullable: false),
LeaderSkillLevel = table.Column<int>(type: "int", nullable: false),
IsNew = table.Column<bool>(type: "bit", nullable: false),
IsLocked = table.Column<bool>(type: "bit", nullable: false),
IsFavorite = table.Column<bool>(type: "bit", nullable: false),
EquipmentServerIds = table.Column<string>(type: "nvarchar(max)", nullable: false),
PotentialStats = table.Column<string>(type: "nvarchar(max)", nullable: false),
EquipmentSlotAndDBIds = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Characters", x => x.ServerId);
table.ForeignKey(
name: "FK_Characters_Accounts_AccountServerId",
column: x => x.AccountServerId,
principalTable: "Accounts",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_MissionProgresses_AccountServerId",
table: "MissionProgresses",
column: "AccountServerId");
migrationBuilder.CreateIndex(
name: "IX_Items_AccountServerId",
table: "Items",
column: "AccountServerId");
migrationBuilder.CreateIndex(
name: "IX_Characters_AccountServerId",
table: "Characters",
column: "AccountServerId");
migrationBuilder.AddForeignKey(
name: "FK_Items_Accounts_AccountServerId",
table: "Items",
column: "AccountServerId",
principalTable: "Accounts",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_MissionProgresses_Accounts_AccountServerId",
table: "MissionProgresses",
column: "AccountServerId",
principalTable: "Accounts",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Items_Accounts_AccountServerId",
table: "Items");
migrationBuilder.DropForeignKey(
name: "FK_MissionProgresses_Accounts_AccountServerId",
table: "MissionProgresses");
migrationBuilder.DropTable(
name: "Characters");
migrationBuilder.DropIndex(
name: "IX_MissionProgresses_AccountServerId",
table: "MissionProgresses");
migrationBuilder.DropIndex(
name: "IX_Items_AccountServerId",
table: "Items");
}
}
}

View File

@ -0,0 +1,307 @@
// <auto-generated />
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("20240501081158_UnMapIsNew")]
partial class UnMapIsNew
{
/// <inheritdoc />
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<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("EquipmentServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("EquipmentSlotAndDBIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ExSkillLevel")
.HasColumnType("int");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("ExtraPassiveSkillLevel")
.HasColumnType("int");
b.Property<long>("FavorExp")
.HasColumnType("bigint");
b.Property<int>("FavorRank")
.HasColumnType("int");
b.Property<bool>("IsFavorite")
.HasColumnType("bit");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("LeaderSkillLevel")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PassiveSkillLevel")
.HasColumnType("int");
b.Property<string>("PotentialStats")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PublicSkillLevel")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Characters");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("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.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("Items");
b.Navigation("MissionProgresses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SCHALE.Common.Migrations
{
/// <inheritdoc />
public partial class UnMapIsNew : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsNew",
table: "Characters");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsNew",
table: "Characters",
type: "bit",
nullable: false,
defaultValue: false);
}
}
}

View File

@ -0,0 +1,368 @@
// <auto-generated />
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("20240501090227_Echelons")]
partial class Echelons
{
/// <inheritdoc />
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<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("EquipmentServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("EquipmentSlotAndDBIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ExSkillLevel")
.HasColumnType("int");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("ExtraPassiveSkillLevel")
.HasColumnType("int");
b.Property<long>("FavorExp")
.HasColumnType("bigint");
b.Property<int>("FavorRank")
.HasColumnType("int");
b.Property<bool>("IsFavorite")
.HasColumnType("bit");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("LeaderSkillLevel")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PassiveSkillLevel")
.HasColumnType("int");
b.Property<string>("PotentialStats")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PublicSkillLevel")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Characters");
});
modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("EchelonNumber")
.HasColumnType("bigint");
b.Property<int>("EchelonType")
.HasColumnType("int");
b.Property<int>("ExtensionType")
.HasColumnType("int");
b.Property<long>("LeaderServerId")
.HasColumnType("bigint");
b.Property<string>("MainSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillCardMulliganCharacterIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SupportSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long>("TSSInteractionServerId")
.HasColumnType("bigint");
b.Property<int>("UsingFlag")
.HasColumnType("int");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Echelons");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("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.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("Items");
b.Navigation("MissionProgresses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,54 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SCHALE.Common.Migrations
{
/// <inheritdoc />
public partial class Echelons : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Echelons",
columns: table => new
{
ServerId = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
AccountServerId = table.Column<long>(type: "bigint", nullable: false),
EchelonType = table.Column<int>(type: "int", nullable: false),
EchelonNumber = table.Column<long>(type: "bigint", nullable: false),
ExtensionType = table.Column<int>(type: "int", nullable: false),
LeaderServerId = table.Column<long>(type: "bigint", nullable: false),
MainSlotServerIds = table.Column<string>(type: "nvarchar(max)", nullable: false),
SupportSlotServerIds = table.Column<string>(type: "nvarchar(max)", nullable: false),
TSSInteractionServerId = table.Column<long>(type: "bigint", nullable: false),
UsingFlag = table.Column<int>(type: "int", nullable: false),
SkillCardMulliganCharacterIds = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Echelons", x => x.ServerId);
table.ForeignKey(
name: "FK_Echelons_Accounts_AccountServerId",
column: x => x.AccountServerId,
principalTable: "Accounts",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Echelons_AccountServerId",
table: "Echelons",
column: "AccountServerId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Echelons");
}
}
}

View File

@ -0,0 +1,365 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SCHALE.Common.Database;
#nullable disable
namespace SCHALE.Common.Migrations
{
[DbContext(typeof(SCHALEContext))]
partial class SCHALEContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(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<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("EquipmentServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("EquipmentSlotAndDBIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ExSkillLevel")
.HasColumnType("int");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("ExtraPassiveSkillLevel")
.HasColumnType("int");
b.Property<long>("FavorExp")
.HasColumnType("bigint");
b.Property<int>("FavorRank")
.HasColumnType("int");
b.Property<bool>("IsFavorite")
.HasColumnType("bit");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("LeaderSkillLevel")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PassiveSkillLevel")
.HasColumnType("int");
b.Property<string>("PotentialStats")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PublicSkillLevel")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Characters");
});
modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("EchelonNumber")
.HasColumnType("bigint");
b.Property<int>("EchelonType")
.HasColumnType("int");
b.Property<int>("ExtensionType")
.HasColumnType("int");
b.Property<long>("LeaderServerId")
.HasColumnType("bigint");
b.Property<string>("MainSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillCardMulliganCharacterIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SupportSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long>("TSSInteractionServerId")
.HasColumnType("bigint");
b.Property<int>("UsingFlag")
.HasColumnType("int");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Echelons");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("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.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("Items");
b.Navigation("MissionProgresses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -9,7 +9,12 @@
<ItemGroup>
<PackageReference Include="Google.FlatBuffers" Version="24.3.25" />
<PackageReference Include="MongoDB.EntityFrameworkCore" Version="7.0.0-preview.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

View File

@ -1,21 +1,22 @@
using SCHALE.Common.Database;
using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Services;
using MongoDB.Driver.Linq;
using SCHALE.Common.FlatData;
using Serilog;
using SCHALE.Common.Database.ModelExtensions;
namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
public class Account : ProtocolHandlerBase
{
private ISessionKeyService sessionKeyService;
private SCHALEContext context;
private readonly ISessionKeyService sessionKeyService;
private readonly SCHALEContext context;
private readonly ExcelTableService excelTableService;
public Account(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory)
public Account(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory)
{
sessionKeyService = _sessionKeyService;
context = _context;
excelTableService = _excelTableService;
}
// most handlers empty
@ -60,7 +61,59 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
CurrentVersion = req.Version,
AccountDB = account,
StaticOpenConditions = new()
{
{ OpenConditionContent.Shop, OpenConditionLockReason.None },
{ OpenConditionContent.Gacha, OpenConditionLockReason.None },
{ OpenConditionContent.LobbyIllust, OpenConditionLockReason.None },
{ OpenConditionContent.Raid, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Cafe, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Unit_Growth_Skill, OpenConditionLockReason.None },
{ OpenConditionContent.Unit_Growth_LevelUp, OpenConditionLockReason.None },
{ OpenConditionContent.Unit_Growth_Transcendence, OpenConditionLockReason.None },
{ OpenConditionContent.WeekDungeon, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Arena, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Academy, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Equip, OpenConditionLockReason.None },
{ OpenConditionContent.Item, OpenConditionLockReason.None },
{ OpenConditionContent.Mission, OpenConditionLockReason.None },
{ OpenConditionContent.WeekDungeon_Chase, OpenConditionLockReason.StageClear },
{ OpenConditionContent.__Deprecated_WeekDungeon_FindGift, OpenConditionLockReason.None },
{ OpenConditionContent.__Deprecated_WeekDungeon_Blood, OpenConditionLockReason.None },
{ OpenConditionContent.Story_Sub, OpenConditionLockReason.None },
{ OpenConditionContent.Story_Replay, OpenConditionLockReason.None },
{ OpenConditionContent.None, OpenConditionLockReason.None },
{ OpenConditionContent.Shop_Gem, OpenConditionLockReason.None },
{ OpenConditionContent.Craft, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Student, OpenConditionLockReason.None },
{ OpenConditionContent.GuideMission, OpenConditionLockReason.None },
{ OpenConditionContent.Clan, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Echelon, OpenConditionLockReason.None },
{ OpenConditionContent.Campaign, OpenConditionLockReason.None },
{ OpenConditionContent.EventContent, OpenConditionLockReason.None },
{ OpenConditionContent.EventStage_1, OpenConditionLockReason.StageClear },
{ OpenConditionContent.EventStage_2, OpenConditionLockReason.None },
{ OpenConditionContent.Talk, OpenConditionLockReason.None },
{ OpenConditionContent.Billing, OpenConditionLockReason.None },
{ OpenConditionContent.Schedule, OpenConditionLockReason.None },
{ OpenConditionContent.Story, OpenConditionLockReason.None },
{ OpenConditionContent.Tactic_Speed, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Cafe_Invite, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Cafe_Invite_2, OpenConditionLockReason.CafeRank | OpenConditionLockReason.StageClear },
{ OpenConditionContent.EventMiniGame_1, OpenConditionLockReason.StageClear },
{ OpenConditionContent.SchoolDungeon, OpenConditionLockReason.StageClear },
{ OpenConditionContent.TimeAttackDungeon, OpenConditionLockReason.StageClear },
{ OpenConditionContent.ShiftingCraft, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Tactic_Skip, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Mulligan, OpenConditionLockReason.StageClear },
{ OpenConditionContent.EventPermanent, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Main_L_1_2, OpenConditionLockReason.ScenarioModeClear },
{ OpenConditionContent.Main_L_1_3, OpenConditionLockReason.ScenarioModeClear },
{ OpenConditionContent.Main_L_1_4, OpenConditionLockReason.ScenarioModeClear },
{ OpenConditionContent.EliminateRaid, OpenConditionLockReason.StageClear },
{ OpenConditionContent.Cafe_2, OpenConditionLockReason.StageClear },
{ OpenConditionContent.MultiFloorRaid, OpenConditionLockReason.StageClear }
},
MissionProgressDBs = [.. context.MissionProgresses.Where(x => x.AccountServerId == account.ServerId)]
};
@ -84,6 +137,58 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
context.Accounts.Add(account);
context.SaveChanges();
// Default items
context.Items.Add(new()
{
AccountServerId = account.ServerId,
UniqueId = 2,
StackCount = 5
});
// Default chars
var defaultCharacters = excelTableService.GetTable<DefaultCharacterExcelTable>().UnPack().DataList;
var newCharacters = defaultCharacters.Select(x =>
{
var characterExcel = excelTableService.GetTable<CharacterExcelTable>().UnPack().DataList.Find(y => y.Id == x.CharacterId);
return new CharacterDB()
{
UniqueId = x.CharacterId,
StarGrade = x.StarGrade,
Level = x.Level,
Exp = x.Exp,
FavorRank = x.FavorRank,
FavorExp = x.FavorExp,
PublicSkillLevel = 1,
ExSkillLevel = x.ExSkillLevel,
PassiveSkillLevel = x.PassiveSkillLevel,
ExtraPassiveSkillLevel = x.ExtraPassiveSkillLevel,
LeaderSkillLevel = x.LeaderSkillLevel,
IsNew = true,
IsLocked = true,
EquipmentServerIds = characterExcel is not null ? characterExcel.EquipmentSlot.Select(x => (long)0).ToList() : [0, 0, 0],
PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } }
};
}).ToList();
account.AddCharacters(context, [.. newCharacters]);
context.SaveChanges();
var favCharacter = defaultCharacters.Find(x => x.FavoriteCharacter);
if (favCharacter is not null)
{
account.RepresentCharacterServerId = (int)newCharacters.First(x => x.UniqueId == favCharacter.CharacterId).ServerId;
}
if (newCharacters.Count > 0)
{
context.Echelons.Add(new()
{
AccountServerId = account.ServerId,
LeaderServerId = newCharacters[0].ServerId,
MainSlotServerIds = newCharacters.Take(3).Select(x => x.ServerId).Append(0).ToList()
});
}
context.SaveChanges();
return new AccountCreateResponse()
{
SessionKey = sessionKeyService.Create(account.PublisherAccountId)
@ -93,7 +198,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Account_Nickname)]
public ResponsePacket NicknameHandler(AccountNicknameRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey!);
var account = sessionKeyService.GetAccount(req.SessionKey);
account.Nickname = req.Nickname;
context.SaveChanges();
@ -108,6 +213,8 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Account_LoginSync)]
public ResponsePacket LoginSyncHandler(AccountLoginSyncRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey);
return new AccountLoginSyncResponse()
{
AccountCurrencySyncResponse = new AccountCurrencySyncResponse()
@ -172,77 +279,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
},
CharacterListResponse = new CharacterListResponse()
{
CharacterDBs = new List<CharacterDB>
{
new CharacterDB
{
ServerId = 1043998219,
UniqueId = 13003,
StarGrade = 2,
Level = 1,
FavorRank = 1,
PublicSkillLevel = 1,
ExSkillLevel = 1,
PassiveSkillLevel = 1,
ExtraPassiveSkillLevel = 1,
LeaderSkillLevel = 1,
IsNew = true,
IsLocked = true,
EquipmentServerIds = new List<long> { 0, 0, 0 },
PotentialStats = new Dictionary<int, int> { { 1, 0 }, { 2, 0 }, { 3, 0 } }
},
new CharacterDB
{
ServerId = 1043998217,
UniqueId = 13010,
StarGrade = 2,
Level = 1,
FavorRank = 1,
PublicSkillLevel = 1,
ExSkillLevel = 1,
PassiveSkillLevel = 1,
ExtraPassiveSkillLevel = 1,
LeaderSkillLevel = 1,
IsNew = true,
IsLocked = true,
EquipmentServerIds = new List<long> { 0, 0, 0 },
PotentialStats = new Dictionary<int, int> { { 1, 0 }, { 2, 0 }, { 3, 0 } }
},
new CharacterDB
{
ServerId = 1043998218,
UniqueId = 16003,
StarGrade = 1,
Level = 1,
FavorRank = 1,
PublicSkillLevel = 1,
ExSkillLevel = 1,
PassiveSkillLevel = 1,
ExtraPassiveSkillLevel = 1,
LeaderSkillLevel = 1,
IsNew = true,
IsLocked = true,
EquipmentServerIds = new List<long> { 0, 0, 0 },
PotentialStats = new Dictionary<int, int> { { 1, 0 }, { 2, 0 }, { 3, 0 } }
},
new CharacterDB
{
ServerId = 1043998220,
UniqueId = 26000,
StarGrade = 1,
Level = 1,
FavorRank = 1,
PublicSkillLevel = 1,
ExSkillLevel = 1,
PassiveSkillLevel = 1,
ExtraPassiveSkillLevel = 1,
LeaderSkillLevel = 1,
IsNew = true,
IsLocked = true,
EquipmentServerIds = new List<long> { 0, 0, 0 },
PotentialStats = new Dictionary<int, int> { { 1, 0 }, { 2, 0 }, { 3, 0 } }
}
},
CharacterDBs = [.. account.Characters],
TSSCharacterDBs = [],
WeaponDBs = [],
CostumeDBs = [],
@ -255,8 +292,8 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
AccountServerId = req.AccountId,
EchelonType = EchelonType.Adventure,
EchelonNumber = 1,
LeaderServerId = 123,
MainSlotServerIds = [1043998217, 1043998218, 1043998219, 0 ],
LeaderServerId = 1,
MainSlotServerIds = [1, 2, 3, 0 ],
SupportSlotServerIds = [ 444, 0],
SkillCardMulliganCharacterIds = []
}
@ -280,48 +317,51 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
new() { EventContentId = 900701 },
],
},
FriendCode = "SCHALEPS",
ServerNotification = ServerNotificationFlag.HasUnreadMail,
SessionKey = new()
{
AccountServerId = req.AccountId,
MxToken = req.SessionKey.MxToken,
},
FriendCode = "SCHALE"
};
}
[ProtocolHandler(Protocol.Account_GetTutorial)]
public ResponsePacket GetTutorialHandler(AccountGetTutorialRequest req)
{
var tutorialIds = context.AccountTutorials.SingleOrDefault(x => x.AccountServerId == sessionKeyService.GetAccount(req.SessionKey).ServerId)?.TutorialIds;
return new AccountGetTutorialResponse()
{
#if DEBUG
TutorialIds = [1, 2]
#endif
TutorialIds = tutorialIds ?? []
};
}
[ProtocolHandler(Protocol.Account_SetTutorial)]
public ResponsePacket SetTutorialHandler(AccountSetTutorialRequest req)
{
return new AccountSetTutorialResponse()
var account = sessionKeyService.GetAccount(req.SessionKey);
var tutorial = context.AccountTutorials.SingleOrDefault(x => x.AccountServerId == account.ServerId);
if (tutorial == null)
{
tutorial = new()
{
AccountServerId = account.ServerId,
TutorialIds = req.TutorialIds
};
context.AccountTutorials.Add(tutorial);
}
else
{
tutorial.TutorialIds = req.TutorialIds;
}
context.SaveChanges();
return new AccountSetTutorialResponse();
}
// others handlers, move to different handler group later
// TODO: others handlers, move to different handler group later
[ProtocolHandler(Protocol.NetworkTime_Sync)]
public ResponsePacket NetworkTime_SyncHandler(NetworkTimeSyncRequest req)
{
long received_tick = DateTimeOffset.Now.Ticks;
return new NetworkTimeSyncResponse()
{
ReceiveTick = received_tick,
ReceiveTick = DateTimeOffset.Now.Ticks,
EchoSendTick = DateTimeOffset.Now.Ticks
};
}
@ -329,70 +369,49 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.ContentSave_Get)]
public ResponsePacket ContentSave_GetHandler(ContentSaveGetRequest req)
{
return new ContentSaveGetResponse()
{
ServerNotification = ServerNotificationFlag.HasUnreadMail,
};
return new ContentSaveGetResponse();
}
[ProtocolHandler(Protocol.Toast_List)]
public ResponsePacket ToastListHandler(ToastListRequest req)
{
return new ToastListResponse()
{
};
return new ToastListResponse();
}
[ProtocolHandler(Protocol.ContentLog_UIOpenStatistics)]
public ResponsePacket ContentLog_UIOpenStatisticsHandler(ContentLogUIOpenStatisticsRequest req)
{
return new ContentLogUIOpenStatisticsResponse()
{
};
return new ContentLogUIOpenStatisticsResponse();
}
[ProtocolHandler(Protocol.Event_RewardIncrease)]
public ResponsePacket Event_RewardIncreaseHandler(EventRewardIncreaseRequest req)
{
return new EventRewardIncreaseResponse()
{
};
return new EventRewardIncreaseResponse();
}
[ProtocolHandler(Protocol.OpenCondition_EventList)]
public ResponsePacket OpenCondition_EventListHandler(OpenConditionEventListRequest req)
{
return new OpenConditionEventListResponse()
{
};
return new OpenConditionEventListResponse();
}
[ProtocolHandler(Protocol.Notification_EventContentReddotCheck)]
public ResponsePacket Notification_EventContentReddotCheckHandler(NotificationEventContentReddotRequest req)
{
return new NotificationEventContentReddotResponse()
{
};
return new NotificationEventContentReddotResponse();
}
[ProtocolHandler(Protocol.Billing_PurchaseListByYostar)]
public ResponsePacket Billing_PurchaseListByYostarHandler(BillingPurchaseListByYostarRequest req)
{
return new BillingPurchaseListByYostarResponse()
{
};
return new BillingPurchaseListByYostarResponse();
}
}

View File

@ -18,11 +18,12 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Item_List)]
public ResponsePacket ListHandler(ItemListRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey);
return new ItemListResponse()
{
ItemDBs = [],
ExpiryItemDBs = [],
ServerNotification = ServerNotificationFlag.HasUnreadMail,
ItemDBs = [.. account.Items],
ExpiryItemDBs = []
};
}
}

View File

@ -1,5 +1,4 @@
using MongoDB.Driver.Linq;
using SCHALE.Common.Database;
using SCHALE.Common.Database;
using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Services;
using Serilog;
@ -8,8 +7,8 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
public class Mission : ProtocolHandlerBase
{
private ISessionKeyService sessionKeyService;
private SCHALEContext context;
private readonly ISessionKeyService sessionKeyService;
private readonly SCHALEContext context;
public Mission(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory)
{
@ -33,10 +32,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Mission_GuideMissionSeasonList)]
public ResponsePacket GuideMissionSeasonListHandler(GuideMissionSeasonListRequest req)
{
return new GuideMissionSeasonListResponse()
{
};
return new GuideMissionSeasonListResponse();
}
}
}

View File

@ -14,22 +14,13 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
Log.Information($"ScenarioSkipRequest SkipPointScriptCount: " + req.SkipPointScriptCount);
// skip story doesn't work yet, probably need to implement missiondb
return new ScenarioSkipResponse()
{
};
return new ScenarioSkipResponse();
}
[ProtocolHandler(Protocol.Scenario_Select)]
public ResponsePacket SelectHandler(ScenarioSelectRequest req)
{
return new ScenarioSelectResponse()
{
};
return new ScenarioSelectResponse();
}
}
}

View File

@ -1,16 +1,16 @@
using SCHALE.Common.Database;
using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Services;
using Serilog;
namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
public class Shop : ProtocolHandlerBase
{
private ISessionKeyService sessionKeyService;
private SCHALEContext context;
private readonly ISessionKeyService sessionKeyService;
private readonly SCHALEContext context;
public List<long> SavedGachaResults { get; set; } // temp storage until gacha management
// TODO: temp storage until gacha management
public List<long> SavedGachaResults { get; set; } = [];
public Shop(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory)
{
@ -21,14 +21,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Shop_BeforehandGachaGet)]
public ResponsePacket BeforehandGachaGetHandler(ShopBeforehandGachaGetRequest req)
{
return new ShopBeforehandGachaGetResponse()
{
SessionKey = new()
{
MxToken = req.SessionKey.MxToken,
AccountServerId = req.SessionKey.AccountServerId,
}
};
return new ShopBeforehandGachaGetResponse();
}
[ProtocolHandler(Protocol.Shop_BeforehandGachaRun)]

View File

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using SCHALE.Common.Database;
using SCHALE.Common.Database.Models;
using SCHALE.GameServer.Models;
namespace SCHALE.GameServer.Controllers
@ -35,8 +34,9 @@ namespace SCHALE.GameServer.Controllers
if (account is null)
{
account = new() { DeviceId = deviceId, Token = Guid.NewGuid().ToString() };
context.Add(account);
context.GuestAccounts.Add(account);
context.SaveChanges();
rsp.IsNew = 1;
}

View File

@ -5,6 +5,7 @@ using System.Reflection;
using SCHALE.Common.Database;
using SCHALE.GameServer.Controllers.Api.ProtocolHandlers;
using SCHALE.GameServer.Services;
using Microsoft.EntityFrameworkCore;
namespace SCHALE.GameServer
{
@ -13,13 +14,15 @@ namespace SCHALE.GameServer
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!)
.SetBasePath(Path.GetDirectoryName(AppContext.BaseDirectory)!)
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Local.json", true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
.Build();
{
var logFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "logs", "log.txt");
var logFilePath = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory)!, "logs", "log.txt");
if (File.Exists(logFilePath))
{
var prevLogFilePath = Path.Combine(Path.GetDirectoryName(logFilePath)!, "log-prev.txt");
@ -28,6 +31,7 @@ namespace SCHALE.GameServer
File.Move(logFilePath, prevLogFilePath);
}
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File(logFilePath, restrictedToMinimumLevel: LogEventLevel.Verbose, shared: true)
@ -44,10 +48,11 @@ namespace SCHALE.GameServer
builder.Host.UseSerilog();
// Add services to the container.
builder.Services.AddSQLServerProvider(config.GetConnectionString("SQLServer") ?? throw new ArgumentNullException("ConnectionStrings/SQLServer in appsettings is missing"));
builder.Services.AddControllers();
builder.Services.AddMongoDBProvider(config.GetConnectionString("MongoDB") ?? throw new ArgumentNullException("ConnectionStrings/MongoDB in appsettings is missing"));
builder.Services.AddProtocolHandlerFactory();
builder.Services.AddMemorySessionKeyService();
builder.Services.AddExcelTableService();
// Add all Handler Groups
var handlerGroups = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(ProtocolHandlerBase)));
@ -57,6 +62,13 @@ namespace SCHALE.GameServer
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<SCHALEContext>();
if (context.Database.GetPendingMigrations().Any())
context.Database.Migrate();
}
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.UseSerilogRequestLogging();

View File

@ -5,7 +5,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://0.0.0.0:443;http://0.0.0.0:80",
"externalUrlConfiguration": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

View File

@ -7,6 +7,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
</ItemGroup>

View File

@ -0,0 +1,55 @@
using Google.FlatBuffers;
using SCHALE.Common.Crypto;
using System.Reflection;
namespace SCHALE.GameServer.Services
{
// TODO: High priority, cache UnPack-ed table!
public class ExcelTableService
{
private readonly ILogger<ExcelTableService> logger;
private readonly Dictionary<Type, object> caches = [];
public ExcelTableService(ILogger<ExcelTableService> _logger)
{
logger = _logger;
}
/// <summary>
/// Please <b>only</b> use this to get table that <b>have a respective file</b> (i.e. <c>CharacterExcelTable</c> have <c>characterexceltable.bytes</c>)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="FileNotFoundException"></exception>
public T GetTable<T>() where T : IFlatbufferObject
{
var type = typeof(T);
if (caches.TryGetValue(type, out var cache))
return (T)cache;
var bytesFilePath = Path.Join(Path.GetDirectoryName(AppContext.BaseDirectory), "Resources/excel/", $"{type.Name.ToLower()}.bytes");
if (!File.Exists(bytesFilePath))
{
throw new FileNotFoundException($"bytes files for {type.Name} not found");
}
var bytes = File.ReadAllBytes(bytesFilePath);
TableEncryptionService.XOR(type.Name, bytes);
var inst = type.GetMethod($"GetRootAs{type.Name}", BindingFlags.Static | BindingFlags.Public, [typeof(ByteBuffer)])!.Invoke(null, [new ByteBuffer(bytes)]);
caches.Add(type, inst!);
logger.LogDebug("{Excel} loaded and cached", type.Name);
return (T)inst!;
}
}
internal static class ExcelTableServiceExtensions
{
public static void AddExcelTableService(this IServiceCollection services)
{
services.AddSingleton<ExcelTableService>();
}
}
}

View File

@ -17,8 +17,11 @@ namespace SCHALE.GameServer.Services
context = _context;
}
public AccountDB GetAccount(SessionKey sessionKey)
public AccountDB GetAccount(SessionKey? sessionKey)
{
if (sessionKey is null)
throw new WebAPIException(WebAPIErrorCode.InvalidSession, "SessionKey not received");
if (sessions.TryGetValue(sessionKey.AccountServerId, out Guid token) && token.ToString() == sessionKey.MxToken)
{
var account = context.Accounts.SingleOrDefault(x => x.ServerId == sessionKey.AccountServerId);
@ -53,7 +56,7 @@ namespace SCHALE.GameServer.Services
}
}
internal static class ServiceExtensions
internal static class SessionKeyServiceExtensions
{
public static void AddMemorySessionKeyService(this IServiceCollection services)
{
@ -64,6 +67,6 @@ namespace SCHALE.GameServer.Services
public interface ISessionKeyService
{
public SessionKey? Create(long publisherAccountId);
public AccountDB GetAccount(SessionKey sessionKey);
public AccountDB GetAccount(SessionKey? sessionKey);
}
}

View File

@ -1,4 +1,14 @@
{
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://0.0.0.0:80"
},
"Https": {
"Url": "https://0.0.0.0:443"
}
}
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
@ -9,7 +19,7 @@
}
},
"ConnectionStrings": {
"MongoDB": "mongodb://localhost:27017/SCHALE"
"SQLServer": "data source=localhost\\SQLEXPRESS;initial catalog=schale;trusted_connection=true;TrustServerCertificate=True"
},
"AllowedHosts": "*"
}

40
Scripts/migrate.ps1 Normal file
View File

@ -0,0 +1,40 @@
[CmdletBinding()]
param(
[Parameter(ValueFromRemainingArguments)]
[string[]]$Arguments
)
$ScriptDir = ([IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Source))
$CommonProjectPath = ([IO.Path]::Join($ScriptDir, "..\SCHALE.Common\SCHALE.Common.csproj"))
$GameServerProjectPath = ([IO.Path]::Join($ScriptDir, "..\SCHALE.GameServer\SCHALE.GameServer.csproj"))
if ($Arguments.Length -lt 1 -Or $Arguments[0].Equals("-h") -Or $Arguments[0].Equals("--help"))
{
Write-Output @"
Commands
-h|--help shows this help output
undo expands to dotnet ef migrations remove, undo latest migration
create expands to dotnet ef migrations add, second positional argument will be the migration name
Examples
migrate.ps1 create Test
migrate.ps1 undo
"@
exit
}
Switch ($Arguments[0])
{
"undo"
{
dotnet ef migrations remove --project $CommonProjectPath --startup-project $GameServerProjectPath --context SCHALEContext
}
"create"
{
dotnet ef migrations add $Arguments[1] --project $CommonProjectPath --startup-project $GameServerProjectPath --context SCHALEContext
}
default
{
Write-Host "Invalid operation" $Arguments[0]
}
}