Feature:Asynchronous Operation & Formatting Code

- Now the async operation is enabled!
- Code formatted by Resharper plugin <3
This commit is contained in:
Somebody
2024-07-22 17:12:03 +08:00
parent e983375620
commit 87d228eb79
793 changed files with 34764 additions and 40190 deletions

View File

@@ -4,86 +4,194 @@ using EggLink.DanhengServer.Util;
using EggLink.DanhengServer.WebServer.Handler;
using EggLink.DanhengServer.WebServer.Objects;
using Google.Protobuf;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Cors;
namespace EggLink.DanhengServer.WebServer.Controllers
using Microsoft.AspNetCore.Mvc;
namespace EggLink.DanhengServer.WebServer.Controllers;
[ApiController]
[EnableCors("AllowAll")]
[Route("/")]
public class DispatchRoutes
{
[ApiController]
[EnableCors("AllowAll")]
[Route("/")]
public class DispatchRoutes
public static ConfigContainer config = ConfigManager.Config;
public static Logger Logger = new("DispatchServer");
[HttpGet("query_dispatch")]
public string QueryDispatch()
{
public static ConfigContainer config = ConfigManager.Config;
public static Logger Logger = new("DispatchServer");
[HttpGet("query_dispatch")]
public string QueryDispatch()
var data = new Dispatch();
data.RegionList.Add(new RegionInfo
{
var data = new Dispatch();
data.RegionList.Add(new RegionInfo()
{
Name = config.GameServer.GameServerId,
DispatchUrl = $"{config.HttpServer.GetDisplayAddress()}/query_gateway",
EnvType = "2",
DisplayName = config.GameServer.GameServerName
});
Logger.Info("Client request: query_dispatch");
return Convert.ToBase64String(data.ToByteArray());
}
[HttpPost("/account/risky/api/check")]
public ContentResult RiskyCheck() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}", ContentType = "application/json" };
// === AUTHENTICATION ===
[HttpPost("/hkrpg_global/mdk/shield/api/login")]
public JsonResult Login([FromBody] LoginReqJson req) => new UsernameLoginHandler().Handle(req.account!, req.password!, req.is_crypto);
[HttpPost("/hkrpg_global/account/ma-passport/api/appLoginByPassword")]
public JsonResult Login([FromBody] NewLoginReqJson req) => new NewUsernameLoginHandler().Handle(req.account!, req.password!);
[HttpPost("/hkrpg_global/mdk/shield/api/verify")]
public JsonResult Verify([FromBody] VerifyReqJson req) => new TokenLoginHandler().Handle(req.uid!, req.token!);
[HttpPost("/hkrpg_global/combo/granter/login/v2/login")]
public JsonResult LoginV2([FromBody] LoginV2ReqJson req) => new ComboTokenGranterHandler().Handle(req.app_id, req.channel_id, req.data!, req.device!, req.sign!);
[HttpGet("/hkrpg_global/combo/granter/api/getConfig")]
public ContentResult GetConfig() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"\",\"push_alias_type\":0,\"disable_ysdk_guard\":true,\"enable_announce_pic_popup\":false,\"app_name\":\"崩<>??RPG\",\"qr_enabled_apps\":{\"bbs\":false,\"cloud\":false},\"qr_app_icons\":{\"app\":\"\",\"bbs\":\"\",\"cloud\":\"\"},\"qr_cloud_display_name\":\"\",\"enable_user_center\":true,\"functional_switch_configs\":{}}}", ContentType = "application/json" };
[HttpGet("/hkrpg_global/combo/red_dot/list")]
[HttpPost("/hkrpg_global/combo/red_dot/list")]
public ContentResult RedDot() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"infos\":[]}}", ContentType = "application/json" };
[HttpGet("/common/hkrpg_global/announcement/api/getAlertAnn")]
public ContentResult AlertAnn() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":false,\"extra_remind\":false}}", ContentType = "application/json" };
[HttpGet("/common/hkrpg_global/announcement/api/getAlertPic")]
public ContentResult AlertPic() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}", ContentType = "application/json" };
[HttpGet("/hkrpg_global/mdk/shield/api/loadConfig")]
public ContentResult LoadConfig() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":24,\"game_key\":\"hkrpg_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"崩<>??RPG\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\",\"gl\",\"ap\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":2592000},\"ap\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":2592000},\"gl\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}},\"initialize_firebase\":false,\"bbs_auth_login\":false,\"bbs_auth_login_ignore\":[],\"fetch_instance_id\":false,\"enable_flash_login\":false}}", ContentType = "application/json" };
// === EXTRA ===
[HttpPost("/hkrpg_global/combo/granter/api/compareProtocolVersion")]
public ContentResult CompareProtocolVer() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":false,\"protocol\":null}}", ContentType = "application/json" };
[HttpGet("/hkrpg_global/mdk/agreement/api/getAgreementInfos")]
public ContentResult GetAgreementInfo() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}", ContentType = "application/json" };
[HttpGet("/combo/box/api/config/sdk/combo")]
public ContentResult Combo() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"kibana_pc_config\":\"{ \\\"enable\\\": 0, \\\"level\\\": \\\"Info\\\",\\\"modules\\\": [\\\"download\\\"] }\\n\",\"network_report_config\":\"{ \\\"enable\\\": 0, \\\"status_codes\\\": [206], \\\"url_paths\\\": [\\\"dataUpload\\\", \\\"red_dot\\\"] }\\n\",\"list_price_tierv2_enable\":\"false\\n\",\"pay_payco_centered_host\":\"bill.payco.com\",\"telemetry_config\":\"{\\n \\\"dataupload_enable\\\": 0,\\n}\",\"enable_web_dpi\":\"true\"}}}", ContentType = "application/json" };
[HttpGet("/combo/box/api/config/sw/precache")]
public ContentResult Precache() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"url\":\"\",\"enable\":\"false\"}}}", ContentType = "application/json" };
[HttpGet("/device-fp/api/getFp")]
public JsonResult GetFp([FromQuery] string device_fp) => new FingerprintHandler().GetFp(device_fp);
[HttpGet("/device-fp/api/getExtList")]
public ContentResult GetExtList() => new() { Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"code\":200,\"msg\":\"ok\",\"ext_list\":[],\"pkg_list\":[],\"pkg_str\":\"/vK5WTh5SS3SAj8Zm0qPWg==\"}}", ContentType = "application/json" };
[HttpPost("/data_abtest_api/config/experiment/list")]
public ContentResult GetExperimentList() => new() { Content = "{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6125_197\",\"version\":\"1\",\"configs\":{\"cardType\":\"direct\"}}]}", ContentType = "application/json" };
Name = config.GameServer.GameServerId,
DispatchUrl = $"{config.HttpServer.GetDisplayAddress()}/query_gateway",
EnvType = "2",
DisplayName = config.GameServer.GameServerName
});
Logger.Info("Client request: query_dispatch");
return Convert.ToBase64String(data.ToByteArray());
}
}
[HttpPost("/account/risky/api/check")]
public ContentResult RiskyCheck()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}",
ContentType = "application/json"
};
}
// === AUTHENTICATION ===
[HttpPost("/hkrpg_global/mdk/shield/api/login")]
public JsonResult Login([FromBody] LoginReqJson req)
{
return new UsernameLoginHandler().Handle(req.account!, req.password!, req.is_crypto);
}
[HttpPost("/hkrpg_global/account/ma-passport/api/appLoginByPassword")]
public JsonResult Login([FromBody] NewLoginReqJson req)
{
return new NewUsernameLoginHandler().Handle(req.account!, req.password!);
}
[HttpPost("/hkrpg_global/mdk/shield/api/verify")]
public JsonResult Verify([FromBody] VerifyReqJson req)
{
return new TokenLoginHandler().Handle(req.uid!, req.token!);
}
[HttpPost("/hkrpg_global/combo/granter/login/v2/login")]
public JsonResult LoginV2([FromBody] LoginV2ReqJson req)
{
return new ComboTokenGranterHandler().Handle(req.app_id, req.channel_id, req.data!, req.device!, req.sign!);
}
[HttpGet("/hkrpg_global/combo/granter/api/getConfig")]
public ContentResult GetConfig()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"\",\"push_alias_type\":0,\"disable_ysdk_guard\":true,\"enable_announce_pic_popup\":false,\"app_name\":\"崩<>??RPG\",\"qr_enabled_apps\":{\"bbs\":false,\"cloud\":false},\"qr_app_icons\":{\"app\":\"\",\"bbs\":\"\",\"cloud\":\"\"},\"qr_cloud_display_name\":\"\",\"enable_user_center\":true,\"functional_switch_configs\":{}}}",
ContentType = "application/json"
};
}
[HttpGet("/hkrpg_global/combo/red_dot/list")]
[HttpPost("/hkrpg_global/combo/red_dot/list")]
public ContentResult RedDot()
{
return new ContentResult
{
Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"infos\":[]}}", ContentType = "application/json"
};
}
[HttpGet("/common/hkrpg_global/announcement/api/getAlertAnn")]
public ContentResult AlertAnn()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":false,\"extra_remind\":false}}",
ContentType = "application/json"
};
}
[HttpGet("/common/hkrpg_global/announcement/api/getAlertPic")]
public ContentResult AlertPic()
{
return new ContentResult
{
Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}",
ContentType = "application/json"
};
}
[HttpGet("/hkrpg_global/mdk/shield/api/loadConfig")]
public ContentResult LoadConfig()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":24,\"game_key\":\"hkrpg_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"崩<>??RPG\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\",\"gl\",\"ap\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":2592000},\"ap\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":2592000},\"gl\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}},\"initialize_firebase\":false,\"bbs_auth_login\":false,\"bbs_auth_login_ignore\":[],\"fetch_instance_id\":false,\"enable_flash_login\":false}}",
ContentType = "application/json"
};
}
// === EXTRA ===
[HttpPost("/hkrpg_global/combo/granter/api/compareProtocolVersion")]
public ContentResult CompareProtocolVer()
{
return new ContentResult
{
Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":false,\"protocol\":null}}",
ContentType = "application/json"
};
}
[HttpGet("/hkrpg_global/mdk/agreement/api/getAgreementInfos")]
public ContentResult GetAgreementInfo()
{
return new ContentResult
{
Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}",
ContentType = "application/json"
};
}
[HttpGet("/combo/box/api/config/sdk/combo")]
public ContentResult Combo()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"kibana_pc_config\":\"{ \\\"enable\\\": 0, \\\"level\\\": \\\"Info\\\",\\\"modules\\\": [\\\"download\\\"] }\\n\",\"network_report_config\":\"{ \\\"enable\\\": 0, \\\"status_codes\\\": [206], \\\"url_paths\\\": [\\\"dataUpload\\\", \\\"red_dot\\\"] }\\n\",\"list_price_tierv2_enable\":\"false\\n\",\"pay_payco_centered_host\":\"bill.payco.com\",\"telemetry_config\":\"{\\n \\\"dataupload_enable\\\": 0,\\n}\",\"enable_web_dpi\":\"true\"}}}",
ContentType = "application/json"
};
}
[HttpGet("/combo/box/api/config/sw/precache")]
public ContentResult Precache()
{
return new ContentResult
{
Content = "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"url\":\"\",\"enable\":\"false\"}}}",
ContentType = "application/json"
};
}
[HttpGet("/device-fp/api/getFp")]
public JsonResult GetFp([FromQuery] string device_fp)
{
return new FingerprintHandler().GetFp(device_fp);
}
[HttpGet("/device-fp/api/getExtList")]
public ContentResult GetExtList()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"code\":200,\"msg\":\"ok\",\"ext_list\":[],\"pkg_list\":[],\"pkg_str\":\"/vK5WTh5SS3SAj8Zm0qPWg==\"}}",
ContentType = "application/json"
};
}
[HttpPost("/data_abtest_api/config/experiment/list")]
public ContentResult GetExperimentList()
{
return new ContentResult
{
Content =
"{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6125_197\",\"version\":\"1\",\"configs\":{\"cardType\":\"direct\"}}]}",
ContentType = "application/json"
};
}
}

View File

@@ -1,13 +1,15 @@
using EggLink.DanhengServer.WebServer.Handler;
using Microsoft.AspNetCore.Mvc;
namespace EggLink.DanhengServer.WebServer.Controllers
namespace EggLink.DanhengServer.WebServer.Controllers;
[ApiController]
[Route("/")]
public class GateServerRoutes
{
[ApiController]
[Route("/")]
public class GateServerRoutes
[HttpGet("/query_gateway")]
public string QueryGateway()
{
[HttpGet("/query_gateway")]
public string QueryGateway() => new QueryGatewayHandler().Data;
return new QueryGatewayHandler().Data;
}
}
}

View File

@@ -1,17 +1,23 @@
using Microsoft.AspNetCore.Mvc;
namespace EggLink.DanhengServer.WebServer.Controllers
{
[ApiController]
[Route("/")]
public class LogServerRoutes
{
[HttpPost("/sdk/dataUpload")]
[HttpPost("/crashdump/dataUpload")]
[HttpPost("/apm/dataUpload")]
public ContentResult LogUpload() => new() { Content = "{\"code\":0}", ContentType = "application/json" };
namespace EggLink.DanhengServer.WebServer.Controllers;
[HttpPost("/common/h5log/log/batch")]
public ContentResult BatchUpload() => new() { Content = "{\"retcode\":0,\"message\":\"success\",\"data\":null}", ContentType = "application/json" };
[ApiController]
[Route("/")]
public class LogServerRoutes
{
[HttpPost("/sdk/dataUpload")]
[HttpPost("/crashdump/dataUpload")]
[HttpPost("/apm/dataUpload")]
public ContentResult LogUpload()
{
return new ContentResult { Content = "{\"code\":0}", ContentType = "application/json" };
}
}
[HttpPost("/common/h5log/log/batch")]
public ContentResult BatchUpload()
{
return new ContentResult
{ Content = "{\"retcode\":0,\"message\":\"success\",\"data\":null}", ContentType = "application/json" };
}
}

View File

@@ -1,49 +1,46 @@
using EggLink.DanhengServer.Util;
using EggLink.DanhengServer.WebServer.Request;
using EggLink.DanhengServer.WebServer.Request;
using EggLink.DanhengServer.WebServer.Response;
using EggLink.DanhengServer.WebServer.Server;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Cors;
namespace EggLink.DanhengServer.WebServer.Controllers
namespace EggLink.DanhengServer.WebServer.Controllers;
[ApiController]
[EnableCors("AllowAll")]
[Route("/")]
public class MuipServerRoutes
{
[ApiController]
[EnableCors("AllowAll")]
[Route("/")]
public class MuipServerRoutes
[HttpGet("/muip/auth_admin")]
[HttpPost("/muip/auth_admin")]
public IActionResult AuthAdminKey([FromBody] AuthAdminKeyRequestBody req)
{
[HttpGet("/muip/auth_admin")]
[HttpPost("/muip/auth_admin")]
public IActionResult AuthAdminKey([FromBody] AuthAdminKeyRequestBody req)
{
var data = MuipManager.AuthAdminAndCreateSession(req.admin_key, req.key_type);
if (data == null)
{
return new JsonResult(new AuthAdminKeyResponse(1, "Admin key is invalid or the function is not enabled!", null));
}
return new JsonResult(new AuthAdminKeyResponse(0, "Authorized admin key successfully!", data));
}
[HttpGet("/muip/exec_cmd")]
[HttpPost("/muip/exec_cmd")]
public IActionResult ExecuteCommand([FromBody] AdminExecRequest req)
{
var resp = MuipManager.ExecuteCommand(req.SessionId, req.Command, req.TargetUid);
return new JsonResult(resp);
}
[HttpGet("/muip/server_information")]
public IActionResult GetServerInformation([FromQuery] ServerInformationRequest req)
{
var resp = MuipManager.GetInformation(req.SessionId);
return new JsonResult(resp);
}
[HttpGet("/muip/player_information")]
public IActionResult GetPlayerInformation([FromQuery] PlayerInformationRequest req)
{
var resp = MuipManager.GetPlayerInformation(req.SessionId, req.Uid);
return new JsonResult(resp);
}
var data = MuipManager.AuthAdminAndCreateSession(req.admin_key, req.key_type);
if (data == null)
return new JsonResult(new AuthAdminKeyResponse(1, "Admin key is invalid or the function is not enabled!",
null));
return new JsonResult(new AuthAdminKeyResponse(0, "Authorized admin key successfully!", data));
}
}
[HttpGet("/muip/exec_cmd")]
[HttpPost("/muip/exec_cmd")]
public IActionResult ExecuteCommand([FromBody] AdminExecRequest req)
{
var resp = MuipManager.ExecuteCommand(req.SessionId, req.Command, req.TargetUid);
return new JsonResult(resp);
}
[HttpGet("/muip/server_information")]
public IActionResult GetServerInformation([FromQuery] ServerInformationRequest req)
{
var resp = MuipManager.GetInformation(req.SessionId);
return new JsonResult(resp);
}
[HttpGet("/muip/player_information")]
public IActionResult GetPlayerInformation([FromQuery] PlayerInformationRequest req)
{
var resp = MuipManager.GetPlayerInformation(req.SessionId, req.Uid);
return new JsonResult(resp);
}
}

View File

@@ -3,38 +3,38 @@ using EggLink.DanhengServer.WebServer.Objects;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
public class ComboTokenGranterHandler
{
public class ComboTokenGranterHandler
public JsonResult Handle(int app_id, int channel_id, string data, string device, string sign)
{
public JsonResult Handle(int app_id, int channel_id, string data, string device, string sign)
var tokenData = JsonConvert.DeserializeObject<LoginTokenData>(data);
var res = new ComboTokenResJson();
if (tokenData == null)
{
var tokenData = JsonConvert.DeserializeObject<LoginTokenData>(data);
ComboTokenResJson res = new ComboTokenResJson();
if (tokenData == null)
{
res.retcode = -202;
res.message = "Invalid login data";
return new JsonResult(res);
}
AccountData? account = AccountData.GetAccountByUid(int.Parse(tokenData.uid!));
if (account == null)
{
res.retcode = -201;
res.message = "Game account cache information error";
return new JsonResult(res);
} else
{
res.message = "OK";
res.data = new ComboTokenResJson.LoginData(account.Uid.ToString(), account.GenerateComboToken());
}
res.retcode = -202;
res.message = "Invalid login data";
return new JsonResult(res);
}
}
public class LoginTokenData
{
public string? uid { get; set; }
public string? token { get; set; }
public bool guest { get; set; }
var account = AccountData.GetAccountByUid(int.Parse(tokenData.uid!));
if (account == null)
{
res.retcode = -201;
res.message = "Game account cache information error";
return new JsonResult(res);
}
res.message = "OK";
res.data = new ComboTokenResJson.LoginData(account.Uid.ToString(), account.GenerateComboToken());
return new JsonResult(res);
}
}
public class LoginTokenData
{
public string? uid { get; set; }
public string? token { get; set; }
public bool guest { get; set; }
}

View File

@@ -1,45 +1,45 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using static EggLink.DanhengServer.WebServer.Handler.FingerprintResJson;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
public class FingerprintHandler
{
public class FingerprintHandler
public JsonResult GetFp(string device_fp)
{
public JsonResult GetFp(string device_fp)
FingerprintResJson res = new();
if (device_fp == null)
{
FingerprintResJson res = new();
if (device_fp == null)
{
res.retcode = -202;
res.message = "Error";
} else
{
res.message = "OK";
res.data = new FingerprintDataJson(device_fp);
}
return new JsonResult(res);
res.retcode = -202;
res.message = "Error";
}
}
public class FingerprintResJson
{
public string? message { get; set; }
public int retcode { get; set; }
public FingerprintDataJson? data { get; set; }
public class FingerprintDataJson
else
{
public string device_fp { get; set; }
public string message { get; set; }
public int code { get; set; }
public FingerprintDataJson(string fp)
{
code = 200;
message = "OK";
device_fp = fp;
}
res.message = "OK";
res.data = new FingerprintDataJson(device_fp);
}
return new JsonResult(res);
}
}
public class FingerprintResJson
{
public string? message { get; set; }
public int retcode { get; set; }
public FingerprintDataJson? data { get; set; }
public class FingerprintDataJson
{
public FingerprintDataJson(string fp)
{
code = 200;
message = "OK";
device_fp = fp;
}
public string device_fp { get; set; }
public string message { get; set; }
public int code { get; set; }
}
}

View File

@@ -1,37 +1,38 @@
using Microsoft.AspNetCore.Mvc;
using EggLink.DanhengServer.Database.Account;
using EggLink.DanhengServer.Database.Account;
using EggLink.DanhengServer.Util;
using static EggLink.DanhengServer.WebServer.Objects.NewLoginResJson;
using EggLink.DanhengServer.WebServer.Objects;
using Microsoft.AspNetCore.Mvc;
using static EggLink.DanhengServer.WebServer.Objects.NewLoginResJson;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
public class NewUsernameLoginHandler
{
public class NewUsernameLoginHandler
public JsonResult Handle(string account, string password)
{
public JsonResult Handle(string account, string password)
NewLoginResJson res = new();
var accountData = AccountData.GetAccountByUserName(account);
if (accountData == null)
{
NewLoginResJson res = new();
AccountData? accountData = AccountData.GetAccountByUserName(account);
if (accountData == null)
if (ConfigManager.Config.ServerOption.AutoCreateUser)
{
if (ConfigManager.Config.ServerOption.AutoCreateUser)
{
AccountHelper.CreateAccount(account, 0);
accountData = AccountData.GetAccountByUserName(account);
}
else
{
return new JsonResult(new NewLoginResJson { message = "Account not found", retcode = -201 });
}
AccountHelper.CreateAccount(account, 0);
accountData = AccountData.GetAccountByUserName(account);
}
if (accountData != null)
else
{
res.message = "OK";
res.data = new VerifyData(accountData.Uid.ToString(), accountData.Username + "@egglink.me", accountData.GenerateDispatchToken());
return new JsonResult(new NewLoginResJson { message = "Account not found", retcode = -201 });
}
return new JsonResult(res);
}
if (accountData != null)
{
res.message = "OK";
res.data = new VerifyData(accountData.Uid.ToString(), accountData.Username + "@egglink.me",
accountData.GenerateDispatchToken());
}
return new JsonResult(res);
}
}
}

View File

@@ -2,55 +2,52 @@
using EggLink.DanhengServer.Util;
using Google.Protobuf;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
internal class QueryGatewayHandler
{
internal class QueryGatewayHandler
public static Logger Logger = new("GatewayServer");
public string Data;
public QueryGatewayHandler()
{
public static Logger Logger = new("GatewayServer");
public string Data;
public QueryGatewayHandler()
var config = ConfigManager.Config;
var urlData = config.DownloadUrl;
// build gateway proto
var gateServer = new GateServer
{
var config = ConfigManager.Config;
var urlData = config.DownloadUrl;
RegionName = config.GameServer.GameServerId,
Ip = config.GameServer.PublicAddress,
Port = config.GameServer.PublicPort,
Msg = "Access verification failed. Please check if you have logged in to the correct account and server.",
B1 = true,
B2 = true,
B3 = true,
B4 = true,
B5 = true
};
// build gateway proto
var gateServer = new GateServer()
{
RegionName = config.GameServer.GameServerId,
Ip = config.GameServer.PublicAddress,
Port = config.GameServer.PublicPort,
Msg = "Access verification failed. Please check if you have logged in to the correct account and server.",
B1 = true,
B2 = true,
B3 = true,
B4 = true,
B5 = true,
};
if (urlData.AssetBundleUrl != null && urlData.AssetBundleUrl.Length > 0)
gateServer.AssetBundleUrl = urlData.AssetBundleUrl;
if (urlData.AssetBundleUrl != null && urlData.AssetBundleUrl.Length > 0)
{
gateServer.AssetBundleUrl = urlData.AssetBundleUrl;
}
if (urlData.ExResourceUrl != null && urlData.ExResourceUrl.Length > 0)
gateServer.ExResourceUrl = urlData.ExResourceUrl;
if (urlData.ExResourceUrl != null && urlData.ExResourceUrl.Length > 0)
{
gateServer.ExResourceUrl = urlData.ExResourceUrl;
}
if (urlData.LuaUrl != null && urlData.LuaUrl.Length > 0)
{
gateServer.LuaUrl = urlData.LuaUrl;
gateServer.MdkResVersion = urlData.LuaUrl.Split('/')[^1].Split('_')[1];
}
if (urlData.IfixUrl != null && urlData.IfixUrl.Length > 0)
{
gateServer.IfixUrl = urlData.IfixUrl;
gateServer.IfixVersion = urlData.IfixUrl.Split('/')[^1].Split('_')[1];
}
Logger.Info("Client request: query_gateway");
Data = Convert.ToBase64String(gateServer.ToByteArray());
if (urlData.LuaUrl != null && urlData.LuaUrl.Length > 0)
{
gateServer.LuaUrl = urlData.LuaUrl;
gateServer.MdkResVersion = urlData.LuaUrl.Split('/')[^1].Split('_')[1];
}
if (urlData.IfixUrl != null && urlData.IfixUrl.Length > 0)
{
gateServer.IfixUrl = urlData.IfixUrl;
gateServer.IfixVersion = urlData.IfixUrl.Split('/')[^1].Split('_')[1];
}
Logger.Info("Client request: query_gateway");
Data = Convert.ToBase64String(gateServer.ToByteArray());
}
}
}

View File

@@ -3,25 +3,25 @@ using EggLink.DanhengServer.WebServer.Objects;
using Microsoft.AspNetCore.Mvc;
using static EggLink.DanhengServer.WebServer.Objects.LoginResJson;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
public class TokenLoginHandler
{
public class TokenLoginHandler
public JsonResult Handle(string uid, string token)
{
public JsonResult Handle(string uid, string token)
var account = AccountData.GetAccountByUid(int.Parse(uid));
var res = new LoginResJson();
if (account == null || !account?.DispatchToken?.Equals(token) == true)
{
AccountData? account = AccountData.GetAccountByUid(int.Parse(uid));
var res = new LoginResJson();
if (account == null || !account?.DispatchToken?.Equals(token) == true)
{
res.retcode = -201;
res.message = "Game account cache information error";
}
else
{
res.message = "OK";
res.data = new VerifyData(account!.Uid.ToString(), account.Username + "@egglink.me", token);
}
return new JsonResult(res);
res.retcode = -201;
res.message = "Game account cache information error";
}
else
{
res.message = "OK";
res.data = new VerifyData(account!.Uid.ToString(), account.Username + "@egglink.me", token);
}
return new JsonResult(res);
}
}
}

View File

@@ -1,37 +1,38 @@
using Microsoft.AspNetCore.Mvc;
using EggLink.DanhengServer.Database.Account;
using EggLink.DanhengServer.Database.Account;
using EggLink.DanhengServer.Util;
using static EggLink.DanhengServer.WebServer.Objects.LoginResJson;
using EggLink.DanhengServer.WebServer.Objects;
using Microsoft.AspNetCore.Mvc;
using static EggLink.DanhengServer.WebServer.Objects.LoginResJson;
namespace EggLink.DanhengServer.WebServer.Handler
namespace EggLink.DanhengServer.WebServer.Handler;
public class UsernameLoginHandler
{
public class UsernameLoginHandler
public JsonResult Handle(string account, string password, bool isCrypto)
{
public JsonResult Handle(string account, string password, bool isCrypto)
LoginResJson res = new();
var accountData = AccountData.GetAccountByUserName(account);
if (accountData == null)
{
LoginResJson res = new();
AccountData? accountData = AccountData.GetAccountByUserName(account);
if (accountData == null)
if (ConfigManager.Config.ServerOption.AutoCreateUser)
{
if (ConfigManager.Config.ServerOption.AutoCreateUser)
{
AccountHelper.CreateAccount(account, 0);
accountData = AccountData.GetAccountByUserName(account);
}
else
{
return new JsonResult(new LoginResJson { message = "Account not found", retcode = -201 });
}
AccountHelper.CreateAccount(account, 0);
accountData = AccountData.GetAccountByUserName(account);
}
if (accountData != null)
else
{
res.message = "OK";
res.data = new VerifyData(accountData.Uid.ToString(), accountData.Username + "@egglink.me", accountData.GenerateDispatchToken());
return new JsonResult(new LoginResJson { message = "Account not found", retcode = -201 });
}
return new JsonResult(res);
}
if (accountData != null)
{
res.message = "OK";
res.data = new VerifyData(accountData.Uid.ToString(), accountData.Username + "@egglink.me",
accountData.GenerateDispatchToken());
}
return new JsonResult(res);
}
}
}

View File

@@ -1,26 +1,25 @@
namespace EggLink.DanhengServer.WebServer.Objects
namespace EggLink.DanhengServer.WebServer.Objects;
public class ComboTokenResJson
{
public class ComboTokenResJson
public string? message { get; set; }
public int retcode { get; set; }
public LoginData? data { get; set; } = null;
public class LoginData
{
public string? message { get; set; }
public int retcode { get; set; }
public LoginData? data { get; set; } = null;
public class LoginData
public LoginData(string openId, string comboToken)
{
public int account_type { get; set; } = 1;
public bool heartbeat { get; set; }
public string? combo_id { get; set; }
public string? combo_token { get; set; }
public string? open_id { get; set; }
public string data { get; set; } = "{\"guest\":false}";
public string? fatigue_remind { get; set; } = null; // ?
public LoginData(string openId, string comboToken)
{
open_id = openId;
combo_token = comboToken;
}
open_id = openId;
combo_token = comboToken;
}
public int account_type { get; set; } = 1;
public bool heartbeat { get; set; }
public string? combo_id { get; set; }
public string? combo_token { get; set; }
public string? open_id { get; set; }
public string data { get; set; } = "{\"guest\":false}";
public string? fatigue_remind { get; set; } = null; // ?
}
}
}

View File

@@ -1,49 +1,48 @@
namespace EggLink.DanhengServer.WebServer.Objects
namespace EggLink.DanhengServer.WebServer.Objects;
public class LoginResJson
{
public class LoginResJson
public string? message { get; set; }
public int retcode { get; set; }
public VerifyData? data { get; set; }
public class VerifyData
{
public string? message { get; set; }
public int retcode { get; set; }
public VerifyData? data { get; set; }
public class VerifyData
public VerifyData(string accountUid, string email, string token)
{
public VerifyAccountData account { get; set; } = new();
public bool device_grant_required { get; set; } = false;
public string realname_operation { get; set; } = "NONE";
public bool realperson_required { get; set; } = false;
public bool safe_mobile_required { get; set; } = false;
public VerifyData(string accountUid, string email, string token)
{
account.uid = accountUid;
account.email = email;
account.token = token;
}
account.uid = accountUid;
account.email = email;
account.token = token;
}
public class VerifyAccountData
{
public string? uid { get; set; }
public string name { get; set; } = "";
public string email { get; set; } = "";
public string mobile { get; set; } = "";
public string is_email_verify { get; set; } = "0";
public string realname { get; set; } = "";
public string identity_card { get; set; } = "";
public string? token { get; set; }
public string? safe_mobile { get; set; } = "";
public string facebook_name { get; set; } = "";
public string twitter_name { get; set; } = "";
public string game_center_name { get; set; } = "";
public string google_name { get; set; } = "";
public string apple_name { get; set; } = "";
public string sony_name { get; set; } = "";
public string tap_name { get; set; } = "";
public string country { get; set; } = "US";
public string reactivate_ticket { get; set; } = "";
public string area_code { get; set; } = "**";
public string device_grant_ticket { get; set; } = "";
}
public VerifyAccountData account { get; set; } = new();
public bool device_grant_required { get; set; } = false;
public string realname_operation { get; set; } = "NONE";
public bool realperson_required { get; set; } = false;
public bool safe_mobile_required { get; set; } = false;
}
}
public class VerifyAccountData
{
public string? uid { get; set; }
public string name { get; set; } = "";
public string email { get; set; } = "";
public string mobile { get; set; } = "";
public string is_email_verify { get; set; } = "0";
public string realname { get; set; } = "";
public string identity_card { get; set; } = "";
public string? token { get; set; }
public string? safe_mobile { get; set; } = "";
public string facebook_name { get; set; } = "";
public string twitter_name { get; set; } = "";
public string game_center_name { get; set; } = "";
public string google_name { get; set; } = "";
public string apple_name { get; set; } = "";
public string sony_name { get; set; } = "";
public string tap_name { get; set; } = "";
public string country { get; set; } = "US";
public string reactivate_ticket { get; set; } = "";
public string area_code { get; set; } = "**";
public string device_grant_ticket { get; set; } = "";
}
}

View File

@@ -1,65 +1,68 @@
namespace EggLink.DanhengServer.WebServer.Objects
namespace EggLink.DanhengServer.WebServer.Objects;
public class NewLoginResJson
{
public class NewLoginResJson
public NewLoginResJson()
{
public string? message { get; set; }
public int retcode { get; set; }
public VerifyData? data { get; set; }
public NewLoginResJson() { }
public NewLoginResJson(string aid, string email, string token)
{
data = new VerifyData(aid, email, token);
}
public class VerifyData
{
public UserInfoData user_info { get; set; } = new UserInfoData();
public TokenData token { get; set; } = new TokenData();
public VerifyData(string aid, string email, string token)
{
user_info.aid = aid;
user_info.email = email;
this.token.token = token;
}
}
public class UserInfoData
{
public string account_name { get; set; } = "";
public string aid { get; set; } = "";
public string area_code { get; set; } = "";
public string country { get; set; } = "";
public string email { get; set; } = "";
public int is_email_verify { get; set; } = 0;
public string identity_code { get; set; } = "";
public List<LinkData> links { get; set; } = new List<LinkData>
{
new LinkData()
};
public string mid { get; set; } = "";
public string mobile { get; set; } = "";
public string realname { get; set; } = "";
public string rebind_area_code { get; set; } = "";
public string rebind_mobile { get; set; } = "";
public string rebind_mobile_time { get; set; } = "";
public string safe_area_code { get; set; } = "";
public string safe_mobile { get; set; } = "";
}
public class TokenData
{
public string token { get; set; } = "";
public int token_type { get; set; } = 1;
}
public class LinkData
{
public string nickname { get; set; } = "";
public string thirdparty { get; set; } = "";
public string union_id { get; set; } = "";
}
}
}
public NewLoginResJson(string aid, string email, string token)
{
data = new VerifyData(aid, email, token);
}
public string? message { get; set; }
public int retcode { get; set; }
public VerifyData? data { get; set; }
public class VerifyData
{
public VerifyData(string aid, string email, string token)
{
user_info.aid = aid;
user_info.email = email;
this.token.token = token;
}
public UserInfoData user_info { get; set; } = new();
public TokenData token { get; set; } = new();
}
public class UserInfoData
{
public string account_name { get; set; } = "";
public string aid { get; set; } = "";
public string area_code { get; set; } = "";
public string country { get; set; } = "";
public string email { get; set; } = "";
public int is_email_verify { get; set; } = 0;
public string identity_code { get; set; } = "";
public List<LinkData> links { get; set; } = new()
{
new()
};
public string mid { get; set; } = "";
public string mobile { get; set; } = "";
public string realname { get; set; } = "";
public string rebind_area_code { get; set; } = "";
public string rebind_mobile { get; set; } = "";
public string rebind_mobile_time { get; set; } = "";
public string safe_area_code { get; set; } = "";
public string safe_mobile { get; set; } = "";
}
public class TokenData
{
public string token { get; set; } = "";
public int token_type { get; set; } = 1;
}
public class LinkData
{
public string nickname { get; set; } = "";
public string thirdparty { get; set; } = "";
public string union_id { get; set; } = "";
}
}

View File

@@ -1,29 +1,29 @@
namespace EggLink.DanhengServer.WebServer.Objects
namespace EggLink.DanhengServer.WebServer.Objects;
public class LoginReqJson
{
public class LoginReqJson
{
public string? account { get; set; }
public string? password { get; set; }
public bool is_crypto { get; set; }
}
public class NewLoginReqJson
{
public string? account { get; set; }
public string? password { get; set; }
}
public class VerifyReqJson
{
public string? uid { get; set; }
public string? token { get; set; }
}
public class LoginV2ReqJson
{
public int app_id { get; set; }
public int channel_id { get; set; }
public string? data { get; set; }
public string? device { get; set; }
public string? sign { get; set; }
}
public string? account { get; set; }
public string? password { get; set; }
public bool is_crypto { get; set; }
}
public class NewLoginReqJson
{
public string? account { get; set; }
public string? password { get; set; }
}
public class VerifyReqJson
{
public string? uid { get; set; }
public string? token { get; set; }
}
public class LoginV2ReqJson
{
public int app_id { get; set; }
public int channel_id { get; set; }
public string? data { get; set; }
public string? device { get; set; }
public string? sign { get; set; }
}

View File

@@ -1,8 +1,7 @@
namespace EggLink.DanhengServer.WebServer.Request
namespace EggLink.DanhengServer.WebServer.Request;
public class AuthAdminKeyRequestBody
{
public class AuthAdminKeyRequestBody
{
public string admin_key { get; set; } = "";
public string key_type { get; set; } = "XML";
}
}
public string admin_key { get; set; } = "";
public string key_type { get; set; } = "XML";
}

View File

@@ -1,9 +1,8 @@
namespace EggLink.DanhengServer.WebServer.Request
namespace EggLink.DanhengServer.WebServer.Request;
public class AdminExecRequest
{
public class AdminExecRequest
{
public string SessionId { get; set; } = "";
public string Command { get; set; } = "";
public int TargetUid { get; set; } = 0;
}
}
public string SessionId { get; set; } = "";
public string Command { get; set; } = "";
public int TargetUid { get; set; } = 0;
}

View File

@@ -1,13 +1,12 @@
namespace EggLink.DanhengServer.WebServer.Request
{
public class ServerInformationRequest
{
public string SessionId { get; set; } = "";
}
namespace EggLink.DanhengServer.WebServer.Request;
public class PlayerInformationRequest
{
public string SessionId { get; set; } = "";
public int Uid { get; set; }
}
public class ServerInformationRequest
{
public string SessionId { get; set; } = "";
}
public class PlayerInformationRequest
{
public string SessionId { get; set; } = "";
public int Uid { get; set; }
}

View File

@@ -1,13 +1,13 @@
namespace EggLink.DanhengServer.WebServer.Response
{
public class AuthAdminKeyResponse(int code, string message, AuthAdminKeyData? data) : BaseResponse<AuthAdminKeyData>(code, message, data)
{
}
namespace EggLink.DanhengServer.WebServer.Response;
public class AuthAdminKeyData
{
public string RsaPublicKey { get; set; } = "";
public string SessionId { get; set; } = "";
public long ExpireTimeStamp { get; set; } = 0;
}
public class AuthAdminKeyResponse(int code, string message, AuthAdminKeyData? data)
: BaseResponse<AuthAdminKeyData>(code, message, data)
{
}
public class AuthAdminKeyData
{
public string RsaPublicKey { get; set; } = "";
public string SessionId { get; set; } = "";
public long ExpireTimeStamp { get; set; } = 0;
}

View File

@@ -1,14 +1,13 @@
namespace EggLink.DanhengServer.WebServer.Response
namespace EggLink.DanhengServer.WebServer.Response;
public class BaseResponse<T>(int code, string message, T? data)
{
public class BaseResponse<T>(int code, string message, T? data)
{
public int Code { get; set; } = code;
public string Message { get; set; } = message;
public int Code { get; set; } = code;
public string Message { get; set; } = message;
public T? Data { get; set; } = data;
}
public class BasicResponse(int code, string message) : BaseResponse<object>(code, message, null)
{
}
public T? Data { get; set; } = data;
}
public class BasicResponse(int code, string message) : BaseResponse<object>(code, message, null)
{
}

View File

@@ -1,12 +1,12 @@
namespace EggLink.DanhengServer.WebServer.Response
{
public class ExecuteCommandResponse(int code, string message, ExecuteCommandData? data = null) : BaseResponse<ExecuteCommandData>(code, message, data)
{
}
namespace EggLink.DanhengServer.WebServer.Response;
public class ExecuteCommandData
{
public string SessionId { get; set; } = "";
public string Message { get; set; } = "";
}
public class ExecuteCommandResponse(int code, string message, ExecuteCommandData? data = null)
: BaseResponse<ExecuteCommandData>(code, message, data)
{
}
public class ExecuteCommandData
{
public string SessionId { get; set; } = "";
public string Message { get; set; } = "";
}

View File

@@ -1,76 +1,75 @@
using EggLink.DanhengServer.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using EggLink.DanhengServer.Enums;
using EggLink.DanhengServer.WebServer.Server;
using Newtonsoft.Json.Converters;
namespace EggLink.DanhengServer.WebServer.Response;
namespace EggLink.DanhengServer.WebServer.Response
public class ServerInformationResponse(int code, string message, ServerInformationData? data = null)
: BaseResponse<ServerInformationData>(code, message, data)
{
public class ServerInformationResponse(int code, string message, ServerInformationData? data = null) : BaseResponse<ServerInformationData>(code, message, data)
{
}
}
public class ServerInformationData
{
public List<SimplePlayerInformationData> OnlinePlayers { get; set; } = [];
public long ServerTime { get; set; } = 0;
public float MaxMemory { get; set; } = 0;
public float UsedMemory { get; set; } = 0;
public float ProgramUsedMemory { get; set; } = 0;
public float CpuUsage { get; set; } = MuipManager.GetCpuUsage();
public string CpuModel { get; set; } = MuipManager.GetCpuDetails().ModelName;
public int CpuCores { get; set; } = MuipManager.GetCpuDetails().Cores;
public float CpuFrequency { get; set; } = MuipManager.GetCpuDetails().Frequency;
public string SystemVersion { get; set; } = MuipManager.GetSystemVersion();
}
public class ServerInformationData
{
public List<SimplePlayerInformationData> OnlinePlayers { get; set; } = [];
public long ServerTime { get; set; } = 0;
public float MaxMemory { get; set; } = 0;
public float UsedMemory { get; set; } = 0;
public float ProgramUsedMemory { get; set; } = 0;
public float CpuUsage { get; set; } = MuipManager.GetCpuUsage();
public string CpuModel { get; set; } = MuipManager.GetCpuDetails().ModelName;
public int CpuCores { get; set; } = MuipManager.GetCpuDetails().Cores;
public float CpuFrequency { get; set; } = MuipManager.GetCpuDetails().Frequency;
public string SystemVersion { get; set; } = MuipManager.GetSystemVersion();
}
public class SimplePlayerInformationData
{
public int Uid { get; set; }
public string Name { get; set; } = "";
public int HeadIconId { get; set; }
}
public class SimplePlayerInformationData
{
public int Uid { get; set; }
public string Name { get; set; } = "";
public int HeadIconId { get; set; }
}
public class PlayerInformationResponse(int code, string message, PlayerInformationData? data = null) : BaseResponse<PlayerInformationData>(code, message, data)
{
}
public class PlayerInformationResponse(int code, string message, PlayerInformationData? data = null)
: BaseResponse<PlayerInformationData>(code, message, data)
{
}
public class PlayerInformationData
{
// Basic info
public int Uid { get; set; }
public string Name { get; set; } = "";
public string Signature { get; set; } = "";
public int HeadIconId { get; set; }
public int Credit { get; set; }
public int Jade { get; set; }
public class PlayerInformationData
{
// Basic info
public int Uid { get; set; }
public string Name { get; set; } = "";
public string Signature { get; set; } = "";
public int HeadIconId { get; set; }
public int Credit { get; set; }
public int Jade { get; set; }
// Scene info
public int CurPlaneId { get; set; }
public int CurFloorId { get; set; }
// Scene info
public int CurPlaneId { get; set; }
public int CurFloorId { get; set; }
// Player info
[JsonConverter(typeof(StringEnumConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
public PlayerStatusEnum PlayerStatus { get; set; } = PlayerStatusEnum.Explore;
// Player info
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(JsonStringEnumConverter))]
public PlayerStatusEnum PlayerStatus { get; set; } = PlayerStatusEnum.Explore;
[JsonConverter(typeof(StringEnumConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
public PlayerSubStatusEnum PlayerSubStatus { get; set; } = PlayerSubStatusEnum.None;
public int Stamina { get; set; } = 0;
public int RecoveryStamina { get; set; } = 0;
public List<int> AssistAvatarList { get; set; } = [];
public List<int> DisplayAvatarList { get; set; } = [];
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
public PlayerSubStatusEnum PlayerSubStatus { get; set; } = PlayerSubStatusEnum.None;
// Mission info
public List<int> FinishedMainMissionIdList { get; set; } = [];
public List<int> FinishedSubMissionIdList { get; set; } = [];
public List<int> AcceptedMainMissionIdList { get; set; } = [];
public List<int> AcceptedSubMissionIdList { get; set; } = [];
public int Stamina { get; set; } = 0;
public int RecoveryStamina { get; set; } = 0;
public List<int> AssistAvatarList { get; set; } = [];
public List<int> DisplayAvatarList { get; set; } = [];
// Lineup info
public List<int> LineupBaseAvatarIdList { get; set; } = [];
// Mission info
public List<int> FinishedMainMissionIdList { get; set; } = [];
public List<int> FinishedSubMissionIdList { get; set; } = [];
public List<int> AcceptedMainMissionIdList { get; set; } = [];
public List<int> AcceptedSubMissionIdList { get; set; } = [];
}
// Lineup info
public List<int> LineupBaseAvatarIdList { get; set; } = [];
}

View File

@@ -1,31 +1,28 @@
using EggLink.DanhengServer.Command;
namespace EggLink.DanhengServer.WebServer.Server
namespace EggLink.DanhengServer.WebServer.Server;
public class MuipCommandSender(MuipSession session, Action<string> action) : ICommandSender
{
public class MuipCommandSender(MuipSession session, Action<string> action) : ICommandSender
public MuipSession Session { get; } = session;
public Action<string> MsgAction { get; } = action;
public int SenderUid { get; set; } = session.Account?.Uid ?? 0;
public bool HasPermission(string permission)
{
public MuipSession Session { get; } = session;
public Action<string> MsgAction { get; } = action;
public int SenderUid { get; set; } = session.Account?.Uid ?? 0;
if (Session.IsAdmin) return true;
public bool HasPermission(string permission)
{
if (Session.IsAdmin)
{
return true;
}
return Session.Account?.Permissions?.Contains(permission) ?? false;
}
public void SendMsg(string msg)
{
MsgAction(msg);
}
public int GetSender()
{
return SenderUid;
}
return Session.Account?.Permissions?.Contains(permission) ?? false;
}
}
public async ValueTask SendMsg(string msg)
{
MsgAction(msg);
await Task.CompletedTask;
}
public int GetSender()
{
return SenderUid;
}
}

View File

@@ -1,475 +1,437 @@
using EggLink.DanhengServer.Util;
using EggLink.DanhengServer.WebServer.Response;
using Org.BouncyCastle.Crypto.Parameters;
using System.Numerics;
using System.Diagnostics;
using System.Management;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.X509;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using EggLink.DanhengServer.Database.Player;
using System.Security.Cryptography;
using System.Text;
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Database;
using EggLink.DanhengServer.Database.Avatar;
using EggLink.DanhengServer.Database.Mission;
using EggLink.DanhengServer.Enums;
using Spectre.Console;
using EggLink.DanhengServer.Database.Lineup;
using EggLink.DanhengServer.Data;
namespace EggLink.DanhengServer.WebServer.Server
using EggLink.DanhengServer.Database.Mission;
using EggLink.DanhengServer.Database.Player;
using EggLink.DanhengServer.Enums;
using EggLink.DanhengServer.Util;
using EggLink.DanhengServer.WebServer.Response;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.X509;
namespace EggLink.DanhengServer.WebServer.Server;
public static class MuipManager
{
public static class MuipManager
public delegate void ExecuteCommandDelegate(string message, MuipCommandSender sender);
public delegate void GetPlayerStatusDelegate(int uid, out PlayerStatusEnum status,
out PlayerSubStatusEnum subStatus);
public delegate void ServerInformationDelegate(Dictionary<int, PlayerData> resultData);
private static readonly Logger logger = Logger.GetByClassName();
public static string RsaPublicKey { get; private set; } = "";
public static string RsaPrivateKey { get; private set; } = "";
public static Dictionary<string, MuipSession> Sessions { get; } = [];
public static event ExecuteCommandDelegate? OnExecuteCommand;
public static event ServerInformationDelegate? OnGetServerInformation;
public static event GetPlayerStatusDelegate? OnGetPlayerStatus;
public static AuthAdminKeyData? AuthAdminAndCreateSession(string key, string key_type)
{
private static readonly Logger logger = Logger.GetByClassName();
public delegate void ExecuteCommandDelegate(string message, MuipCommandSender sender);
public static event ExecuteCommandDelegate? OnExecuteCommand;
public delegate void ServerInformationDelegate(Dictionary<int, PlayerData> resultData);
public static event ServerInformationDelegate? OnGetServerInformation;
public delegate void GetPlayerStatusDelegate(int uid, out PlayerStatusEnum status, out PlayerSubStatusEnum subStatus);
public static event GetPlayerStatusDelegate? OnGetPlayerStatus;
if (ConfigManager.Config.MuipServer.AdminKey == "" ||
ConfigManager.Config.MuipServer.AdminKey != key) return null;
public static string RsaPublicKey { get; private set; } = "";
public static string RsaPrivateKey { get; private set; } = "";
public static Dictionary<string, MuipSession> Sessions { get; } = [];
public static AuthAdminKeyData? AuthAdminAndCreateSession(string key, string key_type)
var session = new MuipSession
{
if (ConfigManager.Config.MuipServer.AdminKey == "" || ConfigManager.Config.MuipServer.AdminKey != key)
SessionId = Guid.NewGuid().ToString(),
RsaPublicKey = GetRsaKeyPair().Item1,
ExpireTimeStamp = DateTime.Now.AddMinutes(15).ToUnixSec(),
IsAdmin = true
};
if (key_type == "PEM")
// convert to PEM
session.RsaPublicKey = XMLToPEM_Pub(session.RsaPublicKey);
Sessions.Add(session.SessionId, session);
var data = new AuthAdminKeyData
{
RsaPublicKey = session.RsaPublicKey,
SessionId = session.SessionId,
ExpireTimeStamp = session.ExpireTimeStamp
};
return data;
}
public static MuipSession? GetSession(string sessionId)
{
if (Sessions.TryGetValue(sessionId, out var value))
{
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return null;
}
var session = new MuipSession()
{
SessionId = Guid.NewGuid().ToString(),
RsaPublicKey = GetRsaKeyPair().Item1,
ExpireTimeStamp = DateTime.Now.AddMinutes(15).ToUnixSec(),
IsAdmin = true,
};
if (key_type == "PEM")
{
// convert to PEM
session.RsaPublicKey = XMLToPEM_Pub(session.RsaPublicKey);
}
Sessions.Add(session.SessionId, session);
var data = new AuthAdminKeyData
{
RsaPublicKey = session.RsaPublicKey,
SessionId = session.SessionId,
ExpireTimeStamp = session.ExpireTimeStamp,
};
return data;
return session;
}
public static MuipSession? GetSession(string sessionId)
return null;
}
public static ExecuteCommandResponse ExecuteCommand(string sessionId, string command, int targetUid)
{
if (Sessions.TryGetValue(sessionId, out var value))
{
if (Sessions.TryGetValue(sessionId, out MuipSession? value))
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return null;
}
return session;
Sessions.Remove(sessionId);
return new ExecuteCommandResponse(1, "Session has expired!");
}
return null;
}
public static ExecuteCommandResponse ExecuteCommand(string sessionId, string command, int targetUid)
{
if (Sessions.TryGetValue(sessionId, out MuipSession? value))
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(GetRsaKeyPair().Item2);
byte[] decrypted;
try
{
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return new(1, "Session has expired!");
}
decrypted = rsa.Decrypt(Convert.FromBase64String(command), RSAEncryptionPadding.Pkcs1);
}
catch
{
return new ExecuteCommandResponse(3, "Wrong encrypted key");
}
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(GetRsaKeyPair().Item2);
byte[] decrypted;
var commandStr = Encoding.UTF8.GetString(decrypted);
logger.Info($"SessionId: {sessionId}, UID: {targetUid}, ExecuteCommand: {commandStr}");
var returnStr = "";
try
var sync = Task.Run(() => OnExecuteCommand?.Invoke(commandStr,
new MuipCommandSender(session, msg => { returnStr += msg + "\r\n"; })
{
decrypted = rsa.Decrypt(Convert.FromBase64String(command), RSAEncryptionPadding.Pkcs1);
} catch
{
return new(3, "Wrong encrypted key");
}
var commandStr = Encoding.UTF8.GetString(decrypted);
logger.Info($"SessionId: {sessionId}, UID: {targetUid}, ExecuteCommand: {commandStr}");
var returnStr = "";
var sync = Task.Run(() => OnExecuteCommand?.Invoke(commandStr, new MuipCommandSender(session, (msg) =>
{
returnStr += msg + "\r\n";
})
{
SenderUid = targetUid,
SenderUid = targetUid
}));
sync.Wait();
sync.Wait();
return new(0, "Success", new()
{
SessionId = sessionId,
Message = Convert.ToBase64String(Encoding.UTF8.GetBytes(returnStr)),
});
}
return new(2, "Session not found!");
return new ExecuteCommandResponse(0, "Success", new ExecuteCommandData
{
SessionId = sessionId,
Message = Convert.ToBase64String(Encoding.UTF8.GetBytes(returnStr))
});
}
public static ServerInformationResponse GetInformation(string sessionId)
{
if (Sessions.TryGetValue(sessionId, out MuipSession? value))
{
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return new(1, "Session has expired!", null);
}
Process currentProcess = Process.GetCurrentProcess();
return new ExecuteCommandResponse(2, "Session not found!");
}
long currentProcessMemory = currentProcess.WorkingSet64;
// get system info
var totalMemory = -1f;
var availableMemory = -1f;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
totalMemory = GetTotalMemoryWindows();
availableMemory = GetAvailableMemoryWindows();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
totalMemory = GetTotalMemoryLinux();
availableMemory = GetAvailableMemoryLinux();
}
var result = new Dictionary<int, PlayerData>();
var sync = Task.Run(() => OnGetServerInformation?.Invoke(result));
sync.Wait();
return new(0, "Success", new()
{
ServerTime = DateTime.Now.ToUnixSec(),
MaxMemory = totalMemory,
ProgramUsedMemory = currentProcessMemory / 1024 / 1024,
UsedMemory = totalMemory - availableMemory,
OnlinePlayers = result.Values.Select(x => new SimplePlayerInformationData()
{
Name = x.Name ?? "",
HeadIconId = x.HeadIcon,
Uid = x.Uid
}).ToList(),
});
}
return new(2, "Session not found!", null);
}
public static PlayerInformationResponse GetPlayerInformation(string sessionId, int uid)
{
if (Sessions.TryGetValue(sessionId, out MuipSession? value))
{
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return new(1, "Session has expired!", null);
}
var result = new Dictionary<int, PlayerData>();
var player = DatabaseHelper.Instance?.GetInstance<PlayerData>(uid);
if (player == null) return new(2, "Player not exist!", null);
var status = PlayerStatusEnum.Offline;
var subStatus = PlayerSubStatusEnum.None;
var statusSync = Task.Run(() => OnGetPlayerStatus?.Invoke(player.Uid, out status, out subStatus));
statusSync.Wait();
var avatarData = DatabaseHelper.Instance!.GetInstance<AvatarData>(player.Uid)!;
var lineupData = DatabaseHelper.Instance!.GetInstance<LineupData>(player.Uid)!;
var missionData = DatabaseHelper.Instance!.GetInstance<MissionData>(player.Uid)!;
var curLineupAvatars = new List<int>();
var index = lineupData.CurExtraLineup > 0 ? lineupData.CurExtraLineup : lineupData.CurLineup;
lineupData.Lineups.TryGetValue(index, out var lineup);
if (lineup != null)
{
foreach (var avatar in lineup.BaseAvatars ?? [])
{
GameData.AvatarConfigData.TryGetValue(avatar.BaseAvatarId, out var excel);
if (excel != null)
{
curLineupAvatars.Add(avatar.BaseAvatarId);
}
}
}
return new(0, "Success", new()
{
Uid = player.Uid,
Name = player.Name ?? "",
Signature = player.Signature ?? "",
Stamina = player.Stamina,
RecoveryStamina = (int)player.StaminaReserve,
HeadIconId = player.HeadIcon,
CurFloorId = player.FloorId,
CurPlaneId = player.PlaneId,
AssistAvatarList = avatarData.AssistAvatars,
DisplayAvatarList = avatarData.DisplayAvatars,
AcceptedSubMissionIdList = missionData.RunningSubMissionIds,
AcceptedMainMissionIdList = missionData.RunningMainMissionIds,
FinishedMainMissionIdList = missionData.FinishedMainMissionIds,
FinishedSubMissionIdList = missionData.FinishedSubMissionIds,
PlayerStatus = status,
PlayerSubStatus = subStatus,
Credit = player.Scoin,
Jade = player.Hcoin,
LineupBaseAvatarIdList = curLineupAvatars
});
}
return new(3, "Session not found!", null);
}
#region Tools
/// <summary>
/// get rsa key pair
/// </summary>
/// <returns>item 1 is public key, item 2 is private key</returns>
public static (string, string) GetRsaKeyPair()
{
if (string.IsNullOrEmpty(RsaPublicKey) || string.IsNullOrEmpty(RsaPrivateKey))
{
var rsa = new RSACryptoServiceProvider(2048);
RsaPublicKey = rsa.ToXmlString(false);
RsaPrivateKey = rsa.ToXmlString(true);
}
return (RsaPublicKey, RsaPrivateKey);
}
public static string XMLToPEM_Pub(string xmlpubkey)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlpubkey);
var p = rsa.ExportParameters(false);
RsaKeyParameters key = new RsaKeyParameters(false, new Org.BouncyCastle.Math.BigInteger(1, p.Modulus), new Org.BouncyCastle.Math.BigInteger(1, p.Exponent));
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string publicKey = Convert.ToBase64String(serializedPublicBytes);
return Format(publicKey, true);
}
private static string Format(string key, bool type)
{
string result = string.Empty;
int length = key.Length / 64;
for (int i = 0; i < length; i++)
{
int start = i * 64;
result = result + key.Substring(start, 64) + "\r\n";
}
result = result + key.Substring(length * 64);
if (type)
{
result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n");
result += "\r\n-----END PUBLIC KEY-----";
}
else
{
result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n");
result += "\r\n-----END PRIVATE KEY-----";
}
return result;
}
public static float GetTotalMemoryWindows()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
foreach (var obj in searcher.Get())
{
var memory = Convert.ToUInt64(obj["TotalPhysicalMemory"]);
return memory / 1024 / 1024;
}
}
return 0;
}
public static float GetAvailableMemoryWindows()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var pc = new PerformanceCounter("Memory", "Available MBytes");
return pc.NextValue();
}
return 0;
}
public static float GetTotalMemoryLinux()
{
string[] lines = File.ReadAllLines("/proc/meminfo");
foreach (string line in lines)
{
if (line.StartsWith("MemTotal"))
{
return float.Parse(line.Split(':')[1].Trim().Split(' ')[0]) / 1024;
}
}
return 0;
}
public static float GetAvailableMemoryLinux()
{
string[] lines = File.ReadAllLines("/proc/meminfo");
foreach (string line in lines)
{
if (line.StartsWith("MemAvailable"))
{
return float.Parse(line.Split(':')[1].Trim().Split(' ')[0]) / 1024;
}
}
return 0;
}
public static float GetCpuUsage()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return GetCpuUsageLinux();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return GetCpuUsageWindows();
}
throw new NotSupportedException("Unsupported OS platform");
}
private static float GetCpuUsageLinux()
{
string[] lines = File.ReadAllLines("/proc/stat");
string[] cpuInfo = lines[0].Split(' ', StringSplitOptions.RemoveEmptyEntries);
float idleTime = float.Parse(cpuInfo[4]);
float totalTime = 0;
for (int i = 1; i < cpuInfo.Length; i++)
{
totalTime += float.Parse(cpuInfo[i]);
}
return 100 * (1 - idleTime / totalTime);
}
private static float GetCpuUsageWindows()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
throw new PlatformNotSupportedException("PerformanceCounter is only supported on Windows");
}
var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
cpuCounter.NextValue();
System.Threading.Thread.Sleep(1000);
return cpuCounter.NextValue();
}
public static (string ModelName, int Cores, float Frequency) GetCpuDetails()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return GetCpuDetailsLinux();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return GetCpuDetailsWindows();
}
throw new NotSupportedException("Unsupported OS platform");
}
private static (string ModelName, int Cores, float Frequency) GetCpuDetailsLinux()
{
string[] lines = File.ReadAllLines("/proc/cpuinfo");
string modelName = "";
int cores = 0;
float frequency = 0;
foreach (string line in lines)
{
if (line.StartsWith("model name"))
{
modelName = line.Split(':')[1].Trim();
}
if (line.StartsWith("cpu cores"))
{
cores = int.Parse(line.Split(':')[1].Trim());
}
if (line.StartsWith("cpu MHz"))
{
frequency = float.Parse(line.Split(':')[1].Trim());
}
}
return (modelName, cores, frequency);
}
private static (string ModelName, int Cores, float Frequency) GetCpuDetailsWindows()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
throw new PlatformNotSupportedException("ManagementObjectSearcher is only supported on Windows");
}
string modelName = "";
int cores = 0;
float frequency = 0;
var searcher = new ManagementObjectSearcher("select * from Win32_Processor");
foreach (var item in searcher.Get())
{
modelName = item["Name"]?.ToString() ?? "Unknown";
cores = int.Parse(item["NumberOfCores"]?.ToString() ?? "0");
frequency = float.Parse(item["MaxClockSpeed"]?.ToString() ?? "0") / 1000; // MHz to GHz
}
return (modelName, cores, frequency);
}
public static string GetSystemVersion()
public static ServerInformationResponse GetInformation(string sessionId)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
if (Sessions.TryGetValue(sessionId, out var value))
{
return GetWindowsVersion();
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return new ServerInformationResponse(1, "Session has expired!");
}
var currentProcess = Process.GetCurrentProcess();
var currentProcessMemory = currentProcess.WorkingSet64;
// get system info
var totalMemory = -1f;
var availableMemory = -1f;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
totalMemory = GetTotalMemoryWindows();
availableMemory = GetAvailableMemoryWindows();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
totalMemory = GetTotalMemoryLinux();
availableMemory = GetAvailableMemoryLinux();
}
var result = new Dictionary<int, PlayerData>();
var sync = Task.Run(() => OnGetServerInformation?.Invoke(result));
sync.Wait();
return new ServerInformationResponse(0, "Success", new ServerInformationData
{
ServerTime = DateTime.Now.ToUnixSec(),
MaxMemory = totalMemory,
ProgramUsedMemory = currentProcessMemory / 1024 / 1024,
UsedMemory = totalMemory - availableMemory,
OnlinePlayers = result.Values.Select(x => new SimplePlayerInformationData
{
Name = x.Name ?? "",
HeadIconId = x.HeadIcon,
Uid = x.Uid
}).ToList()
});
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return new ServerInformationResponse(2, "Session not found!");
}
public static PlayerInformationResponse GetPlayerInformation(string sessionId, int uid)
{
if (Sessions.TryGetValue(sessionId, out var value))
{
return GetLinuxVersion();
var session = value;
if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec())
{
Sessions.Remove(sessionId);
return new PlayerInformationResponse(1, "Session has expired!");
}
var result = new Dictionary<int, PlayerData>();
var player = DatabaseHelper.Instance?.GetInstance<PlayerData>(uid);
if (player == null) return new PlayerInformationResponse(2, "Player not exist!");
var status = PlayerStatusEnum.Offline;
var subStatus = PlayerSubStatusEnum.None;
var statusSync = Task.Run(() => OnGetPlayerStatus?.Invoke(player.Uid, out status, out subStatus));
statusSync.Wait();
var avatarData = DatabaseHelper.Instance!.GetInstance<AvatarData>(player.Uid)!;
var lineupData = DatabaseHelper.Instance!.GetInstance<LineupData>(player.Uid)!;
var missionData = DatabaseHelper.Instance!.GetInstance<MissionData>(player.Uid)!;
var curLineupAvatars = new List<int>();
var index = lineupData.CurExtraLineup > 0 ? lineupData.CurExtraLineup : lineupData.CurLineup;
lineupData.Lineups.TryGetValue(index, out var lineup);
if (lineup != null)
foreach (var avatar in lineup.BaseAvatars ?? [])
{
GameData.AvatarConfigData.TryGetValue(avatar.BaseAvatarId, out var excel);
if (excel != null) curLineupAvatars.Add(avatar.BaseAvatarId);
}
return new PlayerInformationResponse(0, "Success", new PlayerInformationData
{
Uid = player.Uid,
Name = player.Name ?? "",
Signature = player.Signature ?? "",
Stamina = player.Stamina,
RecoveryStamina = (int)player.StaminaReserve,
HeadIconId = player.HeadIcon,
CurFloorId = player.FloorId,
CurPlaneId = player.PlaneId,
AssistAvatarList = avatarData.AssistAvatars,
DisplayAvatarList = avatarData.DisplayAvatars,
AcceptedSubMissionIdList = missionData.RunningSubMissionIds,
AcceptedMainMissionIdList = missionData.RunningMainMissionIds,
FinishedMainMissionIdList = missionData.FinishedMainMissionIds,
FinishedSubMissionIdList = missionData.FinishedSubMissionIds,
PlayerStatus = status,
PlayerSubStatus = subStatus,
Credit = player.Scoin,
Jade = player.Hcoin,
LineupBaseAvatarIdList = curLineupAvatars
});
}
return new PlayerInformationResponse(3, "Session not found!");
}
#region Tools
/// <summary>
/// get rsa key pair
/// </summary>
/// <returns>item 1 is public key, item 2 is private key</returns>
public static (string, string) GetRsaKeyPair()
{
if (string.IsNullOrEmpty(RsaPublicKey) || string.IsNullOrEmpty(RsaPrivateKey))
{
var rsa = new RSACryptoServiceProvider(2048);
RsaPublicKey = rsa.ToXmlString(false);
RsaPrivateKey = rsa.ToXmlString(true);
}
return (RsaPublicKey, RsaPrivateKey);
}
public static string XMLToPEM_Pub(string xmlpubkey)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlpubkey);
var p = rsa.ExportParameters(false);
var key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent));
var publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
var serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
var publicKey = Convert.ToBase64String(serializedPublicBytes);
return Format(publicKey, true);
}
private static string Format(string key, bool type)
{
var result = string.Empty;
var length = key.Length / 64;
for (var i = 0; i < length; i++)
{
var start = i * 64;
result = result + key.Substring(start, 64) + "\r\n";
}
result = result + key.Substring(length * 64);
if (type)
{
result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n");
result += "\r\n-----END PUBLIC KEY-----";
}
else
{
throw new PlatformNotSupportedException("This method only supports Windows and Linux.");
result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n");
result += "\r\n-----END PRIVATE KEY-----";
}
return result;
}
public static float GetTotalMemoryWindows()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
foreach (var obj in searcher.Get())
{
var memory = Convert.ToUInt64(obj["TotalPhysicalMemory"]);
return memory / 1024 / 1024;
}
}
return 0;
}
public static float GetAvailableMemoryWindows()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var pc = new PerformanceCounter("Memory", "Available MBytes");
return pc.NextValue();
}
return 0;
}
public static float GetTotalMemoryLinux()
{
var lines = File.ReadAllLines("/proc/meminfo");
foreach (var line in lines)
if (line.StartsWith("MemTotal"))
return float.Parse(line.Split(':')[1].Trim().Split(' ')[0]) / 1024;
return 0;
}
public static float GetAvailableMemoryLinux()
{
var lines = File.ReadAllLines("/proc/meminfo");
foreach (var line in lines)
if (line.StartsWith("MemAvailable"))
return float.Parse(line.Split(':')[1].Trim().Split(' ')[0]) / 1024;
return 0;
}
public static float GetCpuUsage()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return GetCpuUsageLinux();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return GetCpuUsageWindows();
throw new NotSupportedException("Unsupported OS platform");
}
private static float GetCpuUsageLinux()
{
var lines = File.ReadAllLines("/proc/stat");
var cpuInfo = lines[0].Split(' ', StringSplitOptions.RemoveEmptyEntries);
var idleTime = float.Parse(cpuInfo[4]);
float totalTime = 0;
for (var i = 1; i < cpuInfo.Length; i++) totalTime += float.Parse(cpuInfo[i]);
return 100 * (1 - idleTime / totalTime);
}
private static float GetCpuUsageWindows()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new PlatformNotSupportedException("PerformanceCounter is only supported on Windows");
var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
cpuCounter.NextValue();
Thread.Sleep(1000);
return cpuCounter.NextValue();
}
public static (string ModelName, int Cores, float Frequency) GetCpuDetails()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return GetCpuDetailsLinux();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return GetCpuDetailsWindows();
throw new NotSupportedException("Unsupported OS platform");
}
private static (string ModelName, int Cores, float Frequency) GetCpuDetailsLinux()
{
var lines = File.ReadAllLines("/proc/cpuinfo");
var modelName = "";
var cores = 0;
float frequency = 0;
foreach (var line in lines)
{
if (line.StartsWith("model name")) modelName = line.Split(':')[1].Trim();
if (line.StartsWith("cpu cores")) cores = int.Parse(line.Split(':')[1].Trim());
if (line.StartsWith("cpu MHz")) frequency = float.Parse(line.Split(':')[1].Trim());
}
return (modelName, cores, frequency);
}
private static (string ModelName, int Cores, float Frequency) GetCpuDetailsWindows()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new PlatformNotSupportedException("ManagementObjectSearcher is only supported on Windows");
var modelName = "";
var cores = 0;
float frequency = 0;
var searcher = new ManagementObjectSearcher("select * from Win32_Processor");
foreach (var item in searcher.Get())
{
modelName = item["Name"]?.ToString() ?? "Unknown";
cores = int.Parse(item["NumberOfCores"]?.ToString() ?? "0");
frequency = float.Parse(item["MaxClockSpeed"]?.ToString() ?? "0") / 1000; // MHz to GHz
}
return (modelName, cores, frequency);
}
public static string GetSystemVersion()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return GetWindowsVersion();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return GetLinuxVersion();
throw new PlatformNotSupportedException("This method only supports Windows and Linux.");
}
private static string GetWindowsVersion()
@@ -479,26 +441,24 @@ namespace EggLink.DanhengServer.WebServer.Server
private static string GetLinuxVersion()
{
string version = string.Empty;
var version = string.Empty;
if (File.Exists("/etc/os-release"))
{
var lines = File.ReadAllLines("/etc/os-release");
foreach (var line in lines)
{
if (line.StartsWith("PRETTY_NAME"))
{
version = line.Split('=')[1].Trim('"');
break;
}
}
}
else if (File.Exists("/proc/version"))
{
version = File.ReadAllText("/proc/version");
}
return version;
}
#endregion
}
#endregion
}

View File

@@ -1,14 +1,13 @@
using EggLink.DanhengServer.Database.Account;
namespace EggLink.DanhengServer.WebServer.Server
{
public class MuipSession
{
public string RsaPublicKey { get; set; } = "";
public string SessionId { get; set; } = "";
public long ExpireTimeStamp { get; set; } = 0;
namespace EggLink.DanhengServer.WebServer.Server;
public bool IsAdmin { get; set; } = false;
public AccountData? Account { get; set; } = null;
}
}
public class MuipSession
{
public string RsaPublicKey { get; set; } = "";
public string SessionId { get; set; } = "";
public long ExpireTimeStamp { get; set; } = 0;
public bool IsAdmin { get; set; } = false;
public AccountData? Account { get; set; } = null;
}

View File

@@ -1,106 +1,85 @@
using EggLink.DanhengServer.Util;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using System.Net;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using System.IO;
using EggLink.DanhengServer.Util;
using Microsoft.AspNetCore;
namespace EggLink.DanhengServer.WebServer
namespace EggLink.DanhengServer.WebServer;
public class WebProgram
{
public class WebProgram
public static void Main(string[] args, int port, string address)
{
public static void Main(string[] args, int port, string address)
{
BuildWebHost(args, port, address).Start();
}
public static IWebHost BuildWebHost(string[] args, int port, string address)
{
var b = WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
})
.UseUrls(address);
if (ConfigManager.Config.HttpServer.UseSSL)
{
b.UseKestrel(options =>
{
options.Listen(IPAddress.Any, port, listenOptions =>
{
listenOptions.UseHttps(
ConfigManager.Config.KeyStore.KeyStorePath,
ConfigManager.Config.KeyStore.KeyStorePassword
);
});
});
}
return b.Build();
}
BuildWebHost(args, port, address).Start();
}
public class Startup
public static IWebHost BuildWebHost(string[] args, int port, string address)
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
var b = WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) => { logging.ClearProviders(); })
.UseUrls(address);
if (ConfigManager.Config.HttpServer.UseSSL)
b.UseKestrel(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
options.Listen(IPAddress.Any, port, listenOptions =>
{
listenOptions.UseHttps(
ConfigManager.Config.KeyStore.KeyStorePath,
ConfigManager.Config.KeyStore.KeyStorePassword
);
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Use(async (context, next) =>
{
using var buffer = new MemoryStream();
var request = context.Request;
var response = context.Response;
var bodyStream = response.Body;
response.Body = buffer;
await next.Invoke();
buffer.Position = 0;
context.Response.Headers["Content-Length"] = (response.ContentLength ?? buffer.Length).ToString();
context.Response.Headers.Remove("Transfer-Encoding");
await buffer.CopyToAsync(bodyStream);
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("AllowAll");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
return b.Build();
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.Use(async (context, next) =>
{
using var buffer = new MemoryStream();
var request = context.Request;
var response = context.Response;
var bodyStream = response.Body;
response.Body = buffer;
await next.Invoke();
buffer.Position = 0;
context.Response.Headers["Content-Length"] = (response.ContentLength ?? buffer.Length).ToString();
context.Response.Headers.Remove("Transfer-Encoding");
await buffer.CopyToAsync(bodyStream);
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("AllowAll");
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}