From 41df375e21e39efaba85195df4ccfbc1c5e3a0e5 Mon Sep 17 00:00:00 2001 From: Kei-Luna Date: Wed, 13 May 2026 08:15:33 +0900 Subject: [PATCH] Changed to use a separate account for each email address. --- Common/Database/Account/AccountData.cs | 17 ++++- .../Message/LanguageCHS.cs | 9 +++ .../Message/LanguageCHT.cs | 9 +++ .../Message/LanguageEN.cs | 9 +++ GameServer/Command/Commands/CommandAccount.cs | 37 +++++++++ .../Packet/Recv/Login/HandlerReqLogin.cs | 8 +- SdkServer/Handlers/RouteController.cs | 76 +++++++++++++++---- 7 files changed, 146 insertions(+), 19 deletions(-) create mode 100644 GameServer/Command/Commands/CommandAccount.cs diff --git a/Common/Database/Account/AccountData.cs b/Common/Database/Account/AccountData.cs index 48d43e7..d75f5b8 100644 --- a/Common/Database/Account/AccountData.cs +++ b/Common/Database/Account/AccountData.cs @@ -26,11 +26,14 @@ public class AccountData : BaseDatabaseDataHelper AccountData? result = null; DatabaseHelper.GetAllInstance()?.ForEach(account => { - if (account.Username == username) result = account; + if (string.Equals(account.Username, username, StringComparison.OrdinalIgnoreCase)) result = account; }); return result; } + public static AccountData? GetAccountByEmail(string email) + => GetAccountByUserName(email); + public static AccountData? GetAccountByUid(int uid, bool force = false) { var result = DatabaseHelper.GetInstance(uid, force); @@ -61,8 +64,15 @@ public class AccountData : BaseDatabaseDataHelper #region Account - public static void CreateAccount(string username, int uid, string password) + public static AccountData CreateAccount(string username, int uid, string password) { + if (string.IsNullOrWhiteSpace(username)) + throw new ArgumentException("Username cannot be empty.", nameof(username)); + if (GetAccountByUserName(username) != null) + throw new InvalidOperationException($"Account '{username}' already exists."); + if (uid != 0 && GetAccountByUid(uid) != null) + throw new InvalidOperationException($"UID '{uid}' is already in use."); + var newUid = uid; if (uid == 0) { @@ -84,6 +94,7 @@ public class AccountData : BaseDatabaseDataHelper SetPassword(account, password); DatabaseHelper.CreateInstance(account); + return account; } public static void DeleteAccount(int uid) @@ -178,4 +189,4 @@ public class AccountData : BaseDatabaseDataHelper } #endregion -} \ No newline at end of file +} diff --git a/Common/Internationalization/Message/LanguageCHS.cs b/Common/Internationalization/Message/LanguageCHS.cs index 24c96da..2274b54 100644 --- a/Common/Internationalization/Message/LanguageCHS.cs +++ b/Common/Internationalization/Message/LanguageCHS.cs @@ -128,6 +128,7 @@ public class CommandTextCHS { public NoticeTextCHS Notice { get; } = new(); public HelpTextCHS Help { get; } = new(); + public AccountTextCHS Account { get; } = new(); public GirlTextCHS Girl { get; } = new(); public GiveAllTextCHS GiveAll { get; } = new(); public DebugTextCHS Debug { get; } = new(); @@ -218,6 +219,14 @@ public class HelpTextCHS public string CommandAlias => "命令别名: "; } +public class AccountTextCHS +{ + public string Desc => "管理 SDK 登录使用的账号映射"; + public string Usage => "用法: /account create <邮箱> "; + public string Created => "已创建账号映射: {0} -> UID {1}"; + public string CreateFailed => "创建账号映射失败: {0}"; +} + /// /// path: Game.Command.Girl /// diff --git a/Common/Internationalization/Message/LanguageCHT.cs b/Common/Internationalization/Message/LanguageCHT.cs index 4888fe1..3350d8b 100644 --- a/Common/Internationalization/Message/LanguageCHT.cs +++ b/Common/Internationalization/Message/LanguageCHT.cs @@ -128,6 +128,7 @@ public class CommandTextCHT { public NoticeTextCHT Notice { get; } = new(); public HelpTextCHT Help { get; } = new(); + public AccountTextCHT Account { get; } = new(); public GirlTextCHT Girl { get; } = new(); public GiveAllTextCHT GiveAll { get; } = new(); public DebugTextCHT Debug { get; } = new(); @@ -218,6 +219,14 @@ public class HelpTextCHT public string CommandAlias => "命令別名: "; } +public class AccountTextCHT +{ + public string Desc => "管理 SDK 登入使用的帳號映射"; + public string Usage => "用法: /account create <郵箱> "; + public string Created => "已建立帳號映射: {0} -> UID {1}"; + public string CreateFailed => "建立帳號映射失敗: {0}"; +} + /// /// path: Game.Command.Girl /// diff --git a/Common/Internationalization/Message/LanguageEN.cs b/Common/Internationalization/Message/LanguageEN.cs index f5d95ea..7d19c86 100644 --- a/Common/Internationalization/Message/LanguageEN.cs +++ b/Common/Internationalization/Message/LanguageEN.cs @@ -87,6 +87,7 @@ public class CommandTextEN { public NoticeTextEN Notice { get; } = new(); public HelpTextEN Help { get; } = new(); + public AccountTextEN Account { get; } = new(); public GirlTextEN Girl { get; } = new(); public GiveAllTextEN GiveAll { get; } = new(); public DebugTextEN Debug { get; } = new(); @@ -184,6 +185,14 @@ public class HelpTextEN public string CommandAlias => "Command Alias:"; } +public class AccountTextEN +{ + public string Desc => "Manage account mappings for SDK logins"; + public string Usage => "Usage: /account create "; + public string Created => "Created account mapping: {0} -> UID {1}"; + public string CreateFailed => "Failed to create account mapping: {0}"; +} + /// /// path: Game.Command.Girl /// diff --git a/GameServer/Command/Commands/CommandAccount.cs b/GameServer/Command/Commands/CommandAccount.cs new file mode 100644 index 0000000..8c20380 --- /dev/null +++ b/GameServer/Command/Commands/CommandAccount.cs @@ -0,0 +1,37 @@ +using MikuSB.Database.Account; +using MikuSB.Enums.Player; +using MikuSB.Internationalization; + +namespace MikuSB.GameServer.Command.Commands; + +[CommandInfo("account", "Game.Command.Account.Desc", "Game.Command.Account.Usage", [], [PermEnum.Admin, PermEnum.Support])] +public class CommandAccount : ICommands +{ + [CommandMethod("create")] + public async ValueTask Create(CommandArg arg) + { + if (!await arg.CheckArgCnt(2)) + return; + + var email = arg.Args[0].Trim(); + if (!int.TryParse(arg.Args[1], out var uid) || uid <= 0) + { + await arg.SendMsg(I18NManager.Translate("Game.Command.Notice.InvalidArguments")); + return; + } + + try + { + var account = AccountData.CreateAccount(email, uid, ""); + await arg.SendMsg(I18NManager.Translate("Game.Command.Account.Created", account.Username, account.Uid.ToString())); + } + catch (InvalidOperationException ex) + { + await arg.SendMsg(I18NManager.Translate("Game.Command.Account.CreateFailed", ex.Message)); + } + catch (ArgumentException ex) + { + await arg.SendMsg(I18NManager.Translate("Game.Command.Account.CreateFailed", ex.Message)); + } + } +} diff --git a/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs b/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs index 6c70d67..aec6f53 100644 --- a/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs +++ b/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs @@ -21,11 +21,13 @@ public class HandlerReqLogin : Handler public override async Task OnHandle(Connection connection, byte[] data, ushort seqNo) { var req = ReqLogin.Parser.ParseFrom(data); - var account = AccountData.GetAccountByUid(1); + var account = AccountData.GetAccountByComboToken(req.Token) + ?? AccountData.GetAccountByDispatchToken(req.Token) + ?? AccountData.GetAccountByUid(10001) + ?? AccountData.GetAccountByUid(1); if (account == null) { - AccountData.CreateAccount("MIKU", 0, ""); - account = AccountData.GetAccountByUid(1); + account = AccountData.CreateAccount("default@mikusb.local", 10001, ""); if (account == null) { await connection.SendPacket(CmdIds.NtfLogout); diff --git a/SdkServer/Handlers/RouteController.cs b/SdkServer/Handlers/RouteController.cs index ccd02a8..91367b6 100644 --- a/SdkServer/Handlers/RouteController.cs +++ b/SdkServer/Handlers/RouteController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using MikuSB.Configuration; +using MikuSB.Database.Account; using MikuSB.SdkServer.Models; using MikuSB.Util; using System.Text; @@ -12,6 +13,8 @@ public class RouteController : ControllerBase { public static ConfigContainer Config = ConfigManager.Config; + private const int DefaultAccountUid = 10001; + public static object BuildServerList(string version = "") { return new @@ -126,6 +129,51 @@ public class RouteController : ControllerBase return Ok(rsp); } + private static AccountData EnsureDefaultAccount() + { + var account = AccountData.GetAccountByUid(DefaultAccountUid) + ?? AccountData.GetAccountByEmail("default@mikusb.local"); + if (account != null) + return account; + + return AccountData.CreateAccount("default@mikusb.local", DefaultAccountUid, ""); + } + + private static AccountData ResolveAccountByUid(string? uid) + { + if (int.TryParse(uid, out var parsedUid)) + { + var accountByUid = AccountData.GetAccountByUid(parsedUid); + if (accountByUid != null) + return accountByUid; + } + + return EnsureDefaultAccount(); + } + + private static AccountData ResolveAccountForSdkLogin(string? email, string? uid, string? token) + { + if (!string.IsNullOrWhiteSpace(token)) + { + var accountByComboToken = AccountData.GetAccountByComboToken(token); + if (accountByComboToken != null) + return accountByComboToken; + + var accountByDispatchToken = AccountData.GetAccountByDispatchToken(token); + if (accountByDispatchToken != null) + return accountByDispatchToken; + } + + if (!string.IsNullOrWhiteSpace(email)) + { + var accountByEmail = AccountData.GetAccountByEmail(email); + if (accountByEmail != null) + return accountByEmail; + } + + return ResolveAccountByUid(uid); + } + [HttpGet("/seasun/loginByToken")] [HttpPost("/seasun/loginByToken")] public IActionResult LoginByToken( @@ -135,9 +183,9 @@ public class RouteController : ControllerBase [FromForm] string? form_token ) { - string finalUid = uid ?? form_uid ?? "10001"; - string finalToken = token ?? form_token ?? Guid.NewGuid().ToString("N"); - int parsedUid = int.TryParse(finalUid, out var numericUid) ? numericUid : 10001; + var account = ResolveAccountForSdkLogin(null, uid ?? form_uid, token ?? form_token); + var finalUid = account.Uid.ToString(); + var finalToken = account.GenerateComboToken(); object rsp = new { @@ -148,14 +196,14 @@ public class RouteController : ControllerBase isFirstLogin = false, isNeedKoreaSciAuth = false, ksOpenId = $"ks_{finalUid}", - nickname = Config.GameServer.GameServerName, + nickname = account.Username, passportId = finalUid, playerFillAgeUrl = "", status = 0, thirdPartyUid = "", token = finalToken, type = "guest", - uid = parsedUid + uid = account.Uid }, msg = "操作成功" }; @@ -174,9 +222,10 @@ public class RouteController : ControllerBase [FromForm] string? form_email ) { - string finalUid = uid ?? form_uid ?? "10001"; - string finalToken = token ?? form_token ?? Guid.NewGuid().ToString("N"); - int parsedUid = int.TryParse(finalUid, out var numericUid) ? numericUid : 10001; + var finalEmail = email ?? form_email; + var account = ResolveAccountForSdkLogin(finalEmail, uid ?? form_uid, token ?? form_token); + var finalUid = account.Uid.ToString(); + var finalToken = account.GenerateComboToken(); object rsp = new { @@ -187,14 +236,14 @@ public class RouteController : ControllerBase isFirstLogin = false, isNeedKoreaSciAuth = false, ksOpenId = $"ks_{finalUid}", - nickname = Config.GameServer.GameServerName, + nickname = account.Username, passportId = finalUid, playerFillAgeUrl = "", status = 0, thirdPartyUid = "", token = finalToken, type = "guest", - uid = parsedUid + uid = account.Uid }, msg = "操作成功" }; @@ -209,7 +258,8 @@ public class RouteController : ControllerBase [FromForm] string? form_uid ) { - string uidString = uid ?? form_uid ?? "10001"; + var account = ResolveAccountByUid(uid ?? form_uid); + var uidString = account.Uid.ToString(); object rsp = new { @@ -219,7 +269,7 @@ public class RouteController : ControllerBase bindAccountTypes = new[] { "google" }, channelUid = uidString, loginAccountType = "google", - nickName = Config.GameServer.GameServerName, + nickName = account.Username, passportId = uidString, uid = $"seasun__{uidString}" }, @@ -288,7 +338,7 @@ public class RouteController : ControllerBase [HttpGet("/account/query-uid/{appId}")] public IActionResult QueryUid(string appId, [FromQuery] string authInfo) { - var uid = ExtractUid(authInfo) ?? "10001"; + var uid = ResolveAccountByUid(ExtractUid(authInfo)).Uid.ToString(); object rsp = new {