yet another new system

This commit is contained in:
rfi 2024-04-28 08:41:38 +07:00
parent f2d6b6d547
commit 7aa5b297d0
19 changed files with 328 additions and 619 deletions

View File

@ -9,6 +9,6 @@ namespace SCHALE.Common.Database.Models
[Key] [Key]
[Column("_id")] [Column("_id")]
public string Id { get; set; } public string Id { get; set; }
public uint Seq { get; set; } public long Seq { get; set; }
} }
} }

View File

@ -1,39 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using SCHALE.Common.FlatData;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver.Core.Servers;
namespace SCHALE.Common.Database.Models.Game
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public class Account
{
[Key]
[Column("_id")]
public required uint ServerId { get; set; }
public AccountDB AccountDB { get; set; }
public static Account Create(uint guest_account_uid) // make sure ServerId matches GuestAccount UID
{
Account account = new()
{
ServerId = guest_account_uid,
AccountDB = new AccountDB()
{
ServerId = guest_account_uid,
State = AccountState.Normal,
Level = 0,
Exp = 0,
RepresentCharacterServerId = 1037810385, // i think this is the default
LastConnectTime = DateTime.Now,
CreateDate = DateTime.Now,
}
};
return account;
}
}
}

View File

@ -1,14 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace SCHALE.Common.Database.Models.Game
{
public class Player
{
[Key]
[Column("_id")]
public required uint ServerId { get; set; }
public List<MissionProgressDB> MissionProgressDBs { get; set; }
}
}

View File

@ -6,12 +6,12 @@ namespace SCHALE.Common.Database.Models
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public class GuestAccount public class GuestAccount
{ {
public uint Uid { get; set; } [Key]
[Column("_id")]
public long Uid { get; set; }
public string DeviceId { get; set; } public string DeviceId { get; set; }
[Key]
[Column("_id")]
public string Token { get; set; } public string Token { get; set; }
} }
} }

View File

@ -3,18 +3,16 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ValueGeneration; using Microsoft.EntityFrameworkCore.ValueGeneration;
using MongoDB.EntityFrameworkCore.Extensions; using MongoDB.EntityFrameworkCore.Extensions;
using SCHALE.Common.Database.Models; using SCHALE.Common.Database.Models;
using SCHALE.Common.Database.Models.Game; using System.Text.Json;
namespace SCHALE.Common.Database namespace SCHALE.Common.Database
{ {
public class SCHALEContext : DbContext public class SCHALEContext : DbContext
{ {
public DbSet<GuestAccount> GuestAccounts { get; set; } public DbSet<GuestAccount> GuestAccounts { get; set; }
public DbSet<Account> Accounts { get; set; } public DbSet<AccountDB> Accounts { get; set; }
public DbSet<MissionProgressDB> MissionProgresses { get; set; }
public DbSet<Counter> Counters { get; set; } public DbSet<Counter> Counters { get; set; }
public DbSet<Player> Players { get; set; }
public Player CurrentPlayer { get { return Players.FirstOrDefault();} } // temp
public SCHALEContext(DbContextOptions<SCHALEContext> options) : base(options) public SCHALEContext(DbContextOptions<SCHALEContext> options) : base(options)
{ {
@ -27,26 +25,36 @@ namespace SCHALE.Common.Database
modelBuilder.Entity<GuestAccount>().Property(x => x.Uid).HasValueGenerator<GuestAccountAutoIncrementValueGenerator>(); modelBuilder.Entity<GuestAccount>().Property(x => x.Uid).HasValueGenerator<GuestAccountAutoIncrementValueGenerator>();
modelBuilder.Entity<GuestAccount>().ToCollection("guest_accounts"); modelBuilder.Entity<GuestAccount>().ToCollection("guest_accounts");
modelBuilder.Entity<Account>().ToCollection("accounts"); modelBuilder.Entity<AccountDB>().Property(x => x.ServerId).HasValueGenerator<AccountAutoIncrementValueGenerator>();
modelBuilder.Entity<Player>().ToCollection("players"); modelBuilder.Entity<AccountDB>().ToCollection("accounts");
// attempt to fix MissionProgressDB.Dictionary<long, long> ProgressParameters serialization modelBuilder.Entity<MissionProgressDB>().Property(x => x.ServerId).HasValueGenerator<MissionProgressAutoIncrementValueGenerator>();
modelBuilder.Entity<Player>().Property(e => e.MissionProgressDBs).HasJsonConversion<List<MissionProgressDB>>(); modelBuilder.Entity<MissionProgressDB>().ToCollection("mission_progresses");
modelBuilder.Entity<Counter>().ToCollection("counters"); modelBuilder.Entity<Counter>().ToCollection("counters");
} }
private class AccountAutoIncrementValueGenerator : AutoIncrementValueGenerator
{
protected override string Collection => "account";
}
private class GuestAccountAutoIncrementValueGenerator : AutoIncrementValueGenerator private class GuestAccountAutoIncrementValueGenerator : AutoIncrementValueGenerator
{ {
protected override string Collection => "guest_account"; protected override string Collection => "guest_account";
} }
private abstract class AutoIncrementValueGenerator : ValueGenerator<uint> private class MissionProgressAutoIncrementValueGenerator : AutoIncrementValueGenerator
{
protected override string Collection => "mission_progress";
}
private abstract class AutoIncrementValueGenerator : ValueGenerator<long>
{ {
protected abstract string Collection { get; } protected abstract string Collection { get; }
public override bool GeneratesTemporaryValues => false; public override bool GeneratesTemporaryValues => false;
public override uint Next(EntityEntry entry) public override long Next(EntityEntry entry)
{ {
if (entry.Context is not SCHALEContext) if (entry.Context is not SCHALEContext)
{ {

View File

@ -14,32 +14,7 @@ namespace SCHALE.Common.Database
services.AddDbContext<SCHALEContext>(opt => services.AddDbContext<SCHALEContext>(opt =>
{ {
opt.UseMongoDB(connectionString, "SCHALE"); opt.UseMongoDB(connectionString, "SCHALE");
}); }, ServiceLifetime.Singleton, ServiceLifetime.Singleton);
}
}
public static class ValueConversionExtensions
{
public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder) where T : class, new()
{
ValueConverter<T, string> converter = new ValueConverter<T, string>
(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<T>(v) ?? new T()
);
ValueComparer<T> comparer = new ValueComparer<T>
(
(l, r) => JsonConvert.SerializeObject(l) == JsonConvert.SerializeObject(r),
v => v == null ? 0 : JsonConvert.SerializeObject(v).GetHashCode(),
v => JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(v))
);
propertyBuilder.HasConversion(converter);
propertyBuilder.Metadata.SetValueConverter(converter);
propertyBuilder.Metadata.SetValueComparer(comparer);
return propertyBuilder;
} }
} }
} }

View File

@ -1,10 +1,9 @@
using MongoDB.Bson.Serialization.Attributes; using Newtonsoft.Json;
using MongoDB.Bson.Serialization.Options;
using SCHALE.Common.FlatData; using SCHALE.Common.FlatData;
using SCHALE.Common.NetworkProtocol; using SCHALE.Common.NetworkProtocol;
using SCHALE.Common.Parcel; using SCHALE.Common.Parcel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace SCHALE.Common.Database namespace SCHALE.Common.Database
{ {
@ -186,6 +185,19 @@ namespace SCHALE.Common.Database
public class AccountDB public class AccountDB
{ {
public AccountDB() { }
public AccountDB(long publisherAccountId)
{
PublisherAccountId = publisherAccountId;
State = AccountState.Normal;
Level = 1;
LastConnectTime = DateTime.Now;
CreateDate = DateTime.Now;
}
[Key]
[Column("_id")]
public long ServerId { get; set; } public long ServerId { get; set; }
public string Nickname { get; set; } public string Nickname { get; set; }
@ -1526,6 +1538,8 @@ namespace SCHALE.Common.Database
public class MissionProgressDB public class MissionProgressDB
{ {
[Key]
[Column("_id")]
[JsonIgnore] [JsonIgnore]
public long ServerId { get; set; } public long ServerId { get; set; }
@ -1536,8 +1550,21 @@ namespace SCHALE.Common.Database
public bool Complete { get; set; } public bool Complete { get; set; }
public DateTime StartTime { get; set; } public DateTime StartTime { get; set; }
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)] [JsonIgnore]
public Dictionary<long, long> ProgressParameters { get; set; } 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);
}
}
} }

View File

@ -1,6 +1,5 @@
using SCHALE.Common.Database; using SCHALE.Common.Database;
using SCHALE.Common.FlatData; using SCHALE.Common.FlatData;
using System.Text.Json.Serialization;
namespace SCHALE.Common.NetworkProtocol namespace SCHALE.Common.NetworkProtocol
{ {
@ -40,7 +39,7 @@ namespace SCHALE.Common.NetworkProtocol
public ServerNotificationFlag ServerNotification { get; set; } public ServerNotificationFlag ServerNotification { get; set; }
public List<MissionProgressDB> MissionProgressDBs { get; set; } public List<MissionProgressDB> MissionProgressDBs { get; set; }
public Dictionary<long, List<MissionProgressDB>> EventMissionProgressDBDict { get; set; } public Dictionary<long, List<MissionProgressDB>> EventMissionProgressDBDict { get; set; }
public Dictionary<OpenConditionContent, OpenConditionLockReason> StaticOpenConditions { get; set; } public Dictionary<OpenConditionContent, OpenConditionLockReason> StaticOpenConditions { get; set; }
} }
[Flags] [Flags]

View File

@ -62,7 +62,7 @@ namespace SCHALE.GameServer.Controllers.Api
goto protocolErrorRet; goto protocolErrorRet;
} }
logger.LogDebug(Encoding.ASCII.GetString(payloadMs.ToArray())); logger.LogDebug(payloadStr);
var payload = (JsonSerializer.Deserialize(payloadStr, requestType) as RequestPacket)!; var payload = (JsonSerializer.Deserialize(payloadStr, requestType) as RequestPacket)!;
@ -78,6 +78,9 @@ namespace SCHALE.GameServer.Controllers.Api
goto protocolErrorRet; goto protocolErrorRet;
} }
if ((rsp as BasePacket)!.SessionKey is null)
(rsp as BasePacket)!.SessionKey = payload.SessionKey;
return Results.Json(new return Results.Json(new
{ {
packet = JsonSerializer.Serialize(rsp), packet = JsonSerializer.Serialize(rsp),

View File

@ -5,14 +5,20 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class Academy : ProtocolHandlerBase public class Academy : ProtocolHandlerBase
{ {
public Academy(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } private SCHALEContext context;
public Academy(IProtocolHandlerFactory protocolHandlerFactory, SCHALEContext _context) : base(protocolHandlerFactory)
{
context = _context;
}
[ProtocolHandler(Protocol.Academy_GetInfo)] [ProtocolHandler(Protocol.Academy_GetInfo)]
public ResponsePacket GetInfoHandler(AcademyGetInfoRequest req) public ResponsePacket GetInfoHandler(AcademyGetInfoRequest req)
{ {
//Context.CurrentPlayer.MissionProgressDBs // context.CurrentPlayer.MissionProgressDBs
var MissionProgressDBs = new List<MissionProgressDB> { var MissionProgressDBs = new List<MissionProgressDB>
new MissionProgressDB() { {
new() {
MissionUniqueId = 1700, MissionUniqueId = 1700,
Complete = false, Complete = false,
StartTime = DateTime.UtcNow, StartTime = DateTime.UtcNow,
@ -27,11 +33,11 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
AcademyDB = new() AcademyDB = new()
{ {
AccountId = Context.CurrentPlayer.ServerId, AccountId = req.SessionKey?.AccountServerId ?? 0
}, },
AcademyLocationDBs = [], AcademyLocationDBs = [],
MissionProgressDBs = MissionProgressDBs, MissionProgressDBs = MissionProgressDBs,
//MissionProgressDBs = Context.CurrentPlayer.MissionProgressDBs, //MissionProgressDBs = context.CurrentPlayer.MissionProgressDBs,
}; };
} }
} }

View File

@ -1,23 +1,28 @@
using SCHALE.Common.Database; using SCHALE.Common.Database;
using SCHALE.Common.FlatData;
using SCHALE.Common.NetworkProtocol; using SCHALE.Common.NetworkProtocol;
using SCHALE.Common.Parcel; using SCHALE.GameServer.Services;
using SCHALE.Common.Database.Models.Game; using MongoDB.Driver.Linq;
using Serilog;
namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class Account : ProtocolHandlerBase public class Account : ProtocolHandlerBase
{ {
public Account(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } private ISessionKeyService sessionKeyService;
private SCHALEContext context;
public Account(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory)
{
sessionKeyService = _sessionKeyService;
context = _context;
}
// most handlers empty // most handlers empty
[ProtocolHandler(Protocol.Account_CheckYostar)] [ProtocolHandler(Protocol.Account_CheckYostar)]
public ResponsePacket CheckYostarHandler(AccountCheckYostarRequest req) public ResponsePacket CheckYostarHandler(AccountCheckYostarRequest req)
{ {
string[] uid_token = req.EnterTicket.Split(':'); string[] uidToken = req.EnterTicket.Split(':');
var account = Context.GuestAccounts.SingleOrDefault(x => x.Uid == uint.Parse(uid_token[0]) && x.Token == uid_token[1]); var account = context.GuestAccounts.SingleOrDefault(x => x.Uid == long.Parse(uidToken[0]) && x.Token == uidToken[1]);
if (account is null) if (account is null)
{ {
@ -31,139 +36,29 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
return new AccountCheckYostarResponse() return new AccountCheckYostarResponse()
{ {
ResultState = 1, ResultState = 1,
SessionKey = new() SessionKey = sessionKeyService.Create(account.Uid) ?? new SessionKey() { MxToken = req.EnterTicket }
{
AccountServerId = account.Uid,
MxToken = req.EnterTicket,
}
}; };
} }
[ProtocolHandler(Protocol.Account_Auth)] [ProtocolHandler(Protocol.Account_Auth)]
public ResponsePacket AuthHandler(AccountAuthRequest req) public ResponsePacket AuthHandler(AccountAuthRequest req)
{ {
var account = Context.Accounts.SingleOrDefault(x => x.ServerId == req.AccountId); if (req.SessionKey is null || req.SessionKey.AccountServerId == 0)
if (account == null)
{ {
return new ErrorPacket() return new ErrorPacket()
{ {
ErrorCode = WebAPIErrorCode.AccountAuthNotCreated ErrorCode = WebAPIErrorCode.AccountAuthNotCreated
}; };
} else }
else
{ {
var account = sessionKeyService.GetAccount(req.SessionKey);
return new AccountAuthResponse() return new AccountAuthResponse()
{ {
CurrentVersion = req.Version, CurrentVersion = req.Version,
AccountDB = account.AccountDB, AccountDB = account,
MissionProgressDBs = [.. context.MissionProgresses.Where(x => x.AccountServerId == account.ServerId)]
SessionKey = new()
{
AccountServerId = account.ServerId,
MxToken = req.SessionKey.MxToken,
},
MissionProgressDBs = new List<MissionProgressDB>
{
new MissionProgressDB
{
MissionUniqueId = 1501,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44") },
new MissionProgressDB
{
MissionUniqueId = 1700,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1500,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44") },
new MissionProgressDB
{
MissionUniqueId = 2200,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 }, { 1, 5 } }
},
new MissionProgressDB
{
MissionUniqueId = 300000,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000210,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000220,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000230,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000240,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000250,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000260,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000270,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001327,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001357,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001377,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
}
}; };
} }
@ -172,37 +67,153 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
[ProtocolHandler(Protocol.Account_Create)] [ProtocolHandler(Protocol.Account_Create)]
public ResponsePacket CreateHandler(AccountCreateRequest req) public ResponsePacket CreateHandler(AccountCreateRequest req)
{ {
var account = Common.Database.Models.Game.Account.Create((uint)req.AccountId); if (req.SessionKey is null)
{
return new ErrorPacket()
{
ErrorCode = WebAPIErrorCode.InvalidSession
};
}
Context.Accounts.Add(account); string[] uidToken = req.SessionKey.MxToken.Split(':');
var account = new AccountDB(long.Parse(uidToken[0]));
Context.Players.Add(new Player() { ServerId = (uint)req.AccountId }); context.Accounts.Add(account);
context.MissionProgresses.AddRange([
Context.SaveChanges(); new MissionProgressDB
{
Log.Information("Account Created " + Context.Accounts.Count()); AccountServerId = account.ServerId,
MissionUniqueId = 1501,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44")
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1700,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1500,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44")
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 2200,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 }, { 1, 5 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 300000,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000210,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000220,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000230,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000240,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000250,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000260,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1000270,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1001327,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1001357,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
AccountServerId = account.ServerId,
MissionUniqueId = 1001377,
Complete = true,
StartTime = DateTime.Parse("2024-04-26T20:46:44"),
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
}
]);
context.SaveChanges();
return new AccountCreateResponse() return new AccountCreateResponse()
{ {
SessionKey = new() SessionKey = sessionKeyService.Create(account.PublisherAccountId)
{
AccountServerId = account.ServerId,
MxToken = req.SessionKey.MxToken,
},
}; };
} }
[ProtocolHandler(Protocol.Account_Nickname)] [ProtocolHandler(Protocol.Account_Nickname)]
public ResponsePacket NicknameHandler(AccountNicknameRequest req) public ResponsePacket NicknameHandler(AccountNicknameRequest req)
{ {
var account = Context.Accounts.SingleOrDefault(x => x.ServerId == req.AccountId); var account = sessionKeyService.GetAccount(req.SessionKey!);
account.AccountDB.Nickname = req.Nickname; account.Nickname = req.Nickname;
Context.SaveChanges(); context.SaveChanges();
return new AccountNicknameResponse() return new AccountNicknameResponse()
{ {
AccountDB = account.AccountDB AccountDB = account
}; };
} }
@ -256,8 +267,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
return new NetworkTimeSyncResponse() return new NetworkTimeSyncResponse()
{ {
ReceiveTick = received_tick, ReceiveTick = received_tick,
EchoSendTick = DateTimeOffset.Now.Ticks, EchoSendTick = DateTimeOffset.Now.Ticks
ServerTimeTicks = received_tick,
}; };
} }
@ -279,7 +289,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
MxToken = req.SessionKey.MxToken, MxToken = req.SessionKey.MxToken,
AccountServerId = req.SessionKey.AccountServerId, AccountServerId = req.SessionKey.AccountServerId,
}, }
}; };
} }

View File

@ -1,348 +1,32 @@
using SCHALE.Common.Database; using MongoDB.Driver.Linq;
using SCHALE.Common.Database;
using SCHALE.Common.NetworkProtocol; using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Services;
using Serilog; using Serilog;
namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class Mission : ProtocolHandlerBase public class Mission : ProtocolHandlerBase
{ {
public Mission(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } private ISessionKeyService sessionKeyService;
private SCHALEContext context;
public Mission(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context) : base(protocolHandlerFactory)
{
sessionKeyService = _sessionKeyService;
context = _context;
}
[ProtocolHandler(Protocol.Mission_List)] [ProtocolHandler(Protocol.Mission_List)]
public ResponsePacket ListHandler(MissionListRequest req) public ResponsePacket ListHandler(MissionListRequest req)
{ {
var player = Context.Players.SingleOrDefault(x => x.ServerId == req.AccountId);
Log.Information($"MissionListRequest EventContentId: {req.EventContentId}"); Log.Information($"MissionListRequest EventContentId: {req.EventContentId}");
Context.CurrentPlayer.MissionProgressDBs = new List<MissionProgressDB> var missionProgresses = context.MissionProgresses.Where(x => x.AccountServerId == sessionKeyService.GetAccount(req.SessionKey).ServerId).ToList();
{
new MissionProgressDB
{
MissionUniqueId = 1501,
Complete = true,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 1700,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 2 } }
},
new MissionProgressDB
{
MissionUniqueId = 1500,
Complete = true,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 2200,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 }, { 1, 5 } }
},
new MissionProgressDB
{
MissionUniqueId = 300000,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000210,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000220,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000230,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000240,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000250,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000260,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1000270,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001327,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001357,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001377,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001011,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001014,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001015,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001016,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001019,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 4 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001020,
Complete = true,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001021,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001025,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001026,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001028,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001030,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 1, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001031,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001036,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001037,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001039,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001041,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001046,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001050,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001051,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001055,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 1, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001056,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001057,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001059,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001060,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001061,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001065,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001067,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001069,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001070,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001071,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001075,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 13003, 1 }, { 13010, 1 }, { 16003, 1 }, { 26000, 1 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001079,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 7, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001080,
StartTime = DateTime.Now,
ProgressParameters = new Dictionary<long, long> { { 0, 0 } }
},
new MissionProgressDB
{
MissionUniqueId = 1001013,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 1001023,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 1001034,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 1001044,
StartTime = DateTime.Now },
new MissionProgressDB
{
MissionUniqueId = 1001054,
StartTime = DateTime.Now },
};
//Context.CurrentPlayer.MissionProgressDBs = [];
Context.SaveChanges();
return new MissionListResponse return new MissionListResponse
{ {
//ProgressDBs = Context.CurrentPlayer.MissionProgressDBs ProgressDBs = missionProgresses
ProgressDBs = Context.CurrentPlayer.MissionProgressDBs
}; };
} }

View File

@ -4,7 +4,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class ProofToken : ProtocolHandlerBase public class ProofToken : ProtocolHandlerBase
{ {
public ProofToken(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } public ProofToken(IProtocolHandlerFactory protocolHandlerFactory) : base(protocolHandlerFactory) { }
[ProtocolHandler(Protocol.ProofToken_RequestQuestion)] [ProtocolHandler(Protocol.ProofToken_RequestQuestion)]
public ResponsePacket RequestQuestionHandler(ProofTokenRequestQuestionRequest req) public ResponsePacket RequestQuestionHandler(ProofTokenRequestQuestionRequest req)
@ -12,26 +12,14 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
return new ProofTokenRequestQuestionResponse() return new ProofTokenRequestQuestionResponse()
{ {
Hint = 69, Hint = 69,
Question = "seggs", Question = "seggs"
SessionKey = new()
{
MxToken = req.SessionKey.MxToken,
AccountServerId = req.SessionKey.AccountServerId,
},
}; };
} }
[ProtocolHandler(Protocol.ProofToken_Submit)] [ProtocolHandler(Protocol.ProofToken_Submit)]
public ResponsePacket SubmitHandler(ProofTokenSubmitRequest req) public ResponsePacket SubmitHandler(ProofTokenSubmitRequest req)
{ {
return new ProofTokenSubmitResponse() return new ProofTokenSubmitResponse();
{
SessionKey = new()
{
MxToken = req.SessionKey.MxToken,
AccountServerId = req.SessionKey.AccountServerId,
},
};
} }
} }
} }

View File

@ -89,36 +89,21 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
public abstract class ProtocolHandlerBase : IHostedService public abstract class ProtocolHandlerBase : IHostedService
{ {
private readonly IServiceScopeFactory scopeFactory; private IProtocolHandlerFactory protocolHandlerFactory;
private IServiceScope scope;
public ProtocolHandlerBase(IServiceScopeFactory _scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) public ProtocolHandlerBase(IProtocolHandlerFactory _protocolHandlerFactory)
{ {
scopeFactory = _scopeFactory; protocolHandlerFactory = _protocolHandlerFactory;
protocolHandlerFactory.RegisterInstance(GetType(), this);
}
public SCHALEContext Context
{
get
{
var db = scope.ServiceProvider.GetRequiredService<SCHALEContext>();
return db;
}
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
scope = scopeFactory.CreateScope(); protocolHandlerFactory.RegisterInstance(GetType(), this);
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken)
{ {
scope.Dispose();
Context.Dispose();
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@ -4,7 +4,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class Queuing : ProtocolHandlerBase public class Queuing : ProtocolHandlerBase
{ {
public Queuing(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } public Queuing(IProtocolHandlerFactory protocolHandlerFactory) : base(protocolHandlerFactory) { }
[ProtocolHandler(Protocol.Queuing_GetTicket)] [ProtocolHandler(Protocol.Queuing_GetTicket)]
public ResponsePacket GetTicketHandler(QueuingGetTicketRequest req) public ResponsePacket GetTicketHandler(QueuingGetTicketRequest req)

View File

@ -5,7 +5,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{ {
public class Scenario : ProtocolHandlerBase public class Scenario : ProtocolHandlerBase
{ {
public Scenario(IServiceScopeFactory scopeFactory, IProtocolHandlerFactory protocolHandlerFactory) : base(scopeFactory, protocolHandlerFactory) { } public Scenario(IProtocolHandlerFactory protocolHandlerFactory) : base(protocolHandlerFactory) { }
[ProtocolHandler(Protocol.Scenario_Skip)] [ProtocolHandler(Protocol.Scenario_Skip)]
public ResponsePacket SkipHandler(ScenarioSkipRequest req) public ResponsePacket SkipHandler(ScenarioSkipRequest req)

View File

@ -4,6 +4,7 @@ using Serilog;
using System.Reflection; using System.Reflection;
using SCHALE.Common.Database; using SCHALE.Common.Database;
using SCHALE.GameServer.Controllers.Api.ProtocolHandlers; using SCHALE.GameServer.Controllers.Api.ProtocolHandlers;
using SCHALE.GameServer.Services;
namespace SCHALE.GameServer namespace SCHALE.GameServer
{ {
@ -46,6 +47,7 @@ namespace SCHALE.GameServer
builder.Services.AddControllers(); builder.Services.AddControllers();
builder.Services.AddMongoDBProvider(config.GetConnectionString("MongoDB") ?? throw new ArgumentNullException("ConnectionStrings/MongoDB in appsettings is missing")); builder.Services.AddMongoDBProvider(config.GetConnectionString("MongoDB") ?? throw new ArgumentNullException("ConnectionStrings/MongoDB in appsettings is missing"));
builder.Services.AddProtocolHandlerFactory(); builder.Services.AddProtocolHandlerFactory();
builder.Services.AddMemorySessionKeyService();
builder.Services.AddProtocolHandlerGroup<Account>(); builder.Services.AddProtocolHandlerGroup<Account>();
builder.Services.AddProtocolHandlerGroup<Queuing>(); builder.Services.AddProtocolHandlerGroup<Queuing>();
builder.Services.AddProtocolHandlerGroup<Academy>(); builder.Services.AddProtocolHandlerGroup<Academy>();

View File

@ -45,7 +45,7 @@ namespace SCHALE.GameServer.Models
class UserCreateResponse : BaseResponse class UserCreateResponse : BaseResponse
{ {
[JsonPropertyName("uid")] [JsonPropertyName("uid")]
public uint Uid { get; set; } public long Uid { get; set; }
[JsonPropertyName("token")] [JsonPropertyName("token")]
public string Token { get; set; } public string Token { get; set; }

View File

@ -0,0 +1,75 @@
using SCHALE.Common.Database;
using SCHALE.Common.NetworkProtocol;
namespace SCHALE.GameServer.Services
{
public class MemorySessionKeyService : ISessionKeyService
{
/// <summary>
/// A map of <see cref="Account.ServerId"/> to <see cref="SessionKey.MxToken"/>
/// </summary>
private readonly Dictionary<long, Guid> sessions = [];
private readonly SCHALEContext context;
public MemorySessionKeyService(SCHALEContext _context)
{
context = _context;
}
public AccountDB GetAccount(SessionKey sessionKey)
{
if (sessions.TryGetValue(sessionKey.AccountServerId, out Guid token) && token.ToString() == sessionKey.MxToken)
{
var account = context.Accounts.SingleOrDefault(x => x.ServerId == sessionKey.AccountServerId);
if (account is not null)
return account;
}
throw new InvalidSessionKeyException();
}
public SessionKey? Create(long publisherAccountId)
{
var account = context.Accounts.SingleOrDefault(x => x.PublisherAccountId == publisherAccountId);
if (account is null)
return null;
if (sessions.ContainsKey(account.ServerId))
{
sessions[account.ServerId] = Guid.NewGuid();
}
else
{
sessions.Add(account.ServerId, Guid.NewGuid());
}
return new()
{
AccountServerId = account.ServerId,
MxToken = sessions[account.ServerId].ToString()
};
}
}
internal static class ServiceExtensions
{
public static void AddMemorySessionKeyService(this IServiceCollection services)
{
services.AddSingleton<ISessionKeyService, MemorySessionKeyService>();
}
}
public interface ISessionKeyService
{
public SessionKey? Create(long publisherAccountId);
public AccountDB GetAccount(SessionKey sessionKey);
}
public class InvalidSessionKeyException : Exception
{
public InvalidSessionKeyException() : base() { }
public InvalidSessionKeyException(string message) : base(message) { }
public InvalidSessionKeyException(string message, Exception innerException) : base(message, innerException) { }
}
}