diff --git a/Command/Command.csproj b/Command/Command.csproj
index 50071390..555b228c 100644
--- a/Command/Command.csproj
+++ b/Command/Command.csproj
@@ -8,6 +8,10 @@
DanhengCommand
+
+
+
+
diff --git a/Common/Common.csproj b/Common/Common.csproj
index 4766b2b4..691a01c6 100644
--- a/Common/Common.csproj
+++ b/Common/Common.csproj
@@ -18,6 +18,7 @@
+
diff --git a/Common/Enums/PlayerStatusEnum.cs b/Common/Enums/PlayerStatusEnum.cs
new file mode 100644
index 00000000..ee406ac5
--- /dev/null
+++ b/Common/Enums/PlayerStatusEnum.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EggLink.DanhengServer.Enums
+{
+ public enum PlayerStatusEnum
+ {
+ Offline = 0,
+ Explore = 1,
+ Rogue = 2,
+ Challenge = 3,
+ Mission = 4
+ }
+}
diff --git a/GameServer/Game/ChessRogue/ChessRogueInstance.cs b/GameServer/Game/ChessRogue/ChessRogueInstance.cs
index b38bfeca..14fdd126 100644
--- a/GameServer/Game/ChessRogue/ChessRogueInstance.cs
+++ b/GameServer/Game/ChessRogue/ChessRogueInstance.cs
@@ -214,10 +214,10 @@ namespace EggLink.DanhengServer.Game.ChessRogue
};
RogueCells.Add(item.Key, cell);
- if (cell.GetCellId() == CurBoardExcel.MapInfo!.EndGridItemID) // last cell
- {
+ //if (cell.GetCellId() == CurBoardExcel.MapInfo!.EndGridItemID) // last cell
+ //{
cell.Init();
- }
+ //}
}
}
diff --git a/GameServer/GameServer.csproj b/GameServer/GameServer.csproj
index 947cd21b..5b334718 100644
--- a/GameServer/GameServer.csproj
+++ b/GameServer/GameServer.csproj
@@ -32,6 +32,7 @@
+
diff --git a/Program/Program.csproj b/Program/Program.csproj
index 287be6a9..0e4e0d70 100644
--- a/Program/Program.csproj
+++ b/Program/Program.csproj
@@ -14,6 +14,10 @@
+
+
+
+
diff --git a/Program/Program/EntryPoint.cs b/Program/Program/EntryPoint.cs
index 2f918d23..f3b9c58c 100644
--- a/Program/Program/EntryPoint.cs
+++ b/Program/Program/EntryPoint.cs
@@ -13,6 +13,7 @@ using EggLink.DanhengServer.Command;
using EggLink.DanhengServer.Server.Packet;
using EggLink.DanhengServer.GameServer.Command;
using EggLink.DanhengServer.WebServer.Server;
+using EggLink.DanhengServer.Enums;
namespace EggLink.DanhengServer.Program
{
@@ -139,6 +140,40 @@ namespace EggLink.DanhengServer.Program
};
MuipManager.OnExecuteCommand += CommandManager.HandleCommand;
+ MuipManager.OnGetServerInformation += x =>
+ {
+ foreach (var con in Listener.Connections.Values)
+ {
+ if (con.Player != null)
+ {
+ x.Add(con.Player.Uid, con.Player.Data);
+ }
+ }
+ };
+ MuipManager.OnGetPlayerStatus += (int uid, out PlayerStatusEnum status) =>
+ {
+ foreach (var con in Listener.Connections.Values)
+ {
+ if (con.Player != null && con.Player.Uid == uid)
+ {
+ if (con.Player.RogueManager?.GetRogueInstance() != null)
+ {
+ status = PlayerStatusEnum.Rogue;
+ }
+ else if (con.Player.ChallengeManager?.ChallengeInstance != null)
+ {
+ status = PlayerStatusEnum.Challenge;
+ }
+ else
+ {
+ status = PlayerStatusEnum.Explore;
+ }
+ return;
+ }
+ }
+
+ status = PlayerStatusEnum.Offline;
+ };
// generate the handbook
HandbookGenerator.Generate();
diff --git a/WebServer/Controllers/MuipServerRoutes.cs b/WebServer/Controllers/MuipServerRoutes.cs
index 7abf5b02..06a7ac89 100644
--- a/WebServer/Controllers/MuipServerRoutes.cs
+++ b/WebServer/Controllers/MuipServerRoutes.cs
@@ -29,5 +29,19 @@ namespace EggLink.DanhengServer.WebServer.Controllers
var resp = MuipManager.ExecuteCommand(req.SessionId, req.Command, req.TargetUid);
return new JsonResult(resp);
}
+
+ [HttpGet("/muip/server_information")]
+ public IActionResult GetServerInformation([FromBody] ServerInformationRequest req)
+ {
+ var resp = MuipManager.GetInformation(req.SessionId);
+ return new JsonResult(resp);
+ }
+
+ [HttpGet("/muip/player_information")]
+ public IActionResult GetPlayerInformation([FromBody] PlayerInformationRequest req)
+ {
+ var resp = MuipManager.GetPlayerInformation(req.SessionId, req.Uid);
+ return new JsonResult(resp);
+ }
}
}
diff --git a/WebServer/Request/InformationRequest.cs b/WebServer/Request/InformationRequest.cs
new file mode 100644
index 00000000..3d67f19d
--- /dev/null
+++ b/WebServer/Request/InformationRequest.cs
@@ -0,0 +1,13 @@
+namespace EggLink.DanhengServer.WebServer.Request
+{
+ public class ServerInformationRequest
+ {
+ public string SessionId { get; set; } = "";
+ }
+
+ public class PlayerInformationRequest
+ {
+ public string SessionId { get; set; } = "";
+ public int Uid { get; set; }
+ }
+}
diff --git a/WebServer/Response/InformationResponse.cs b/WebServer/Response/InformationResponse.cs
new file mode 100644
index 00000000..05c40fd7
--- /dev/null
+++ b/WebServer/Response/InformationResponse.cs
@@ -0,0 +1,59 @@
+using EggLink.DanhengServer.Enums;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace EggLink.DanhengServer.WebServer.Response
+{
+ public class ServerInformationResponse(int code, string message, ServerInformationData? data = null) : BaseResponse(code, message, data)
+ {
+ }
+
+ public class ServerInformationData
+ {
+ public List 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 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(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; }
+
+ // 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;
+ public int Stamina { get; set; } = 0;
+ public int RecoveryStamina { get; set; } = 0;
+ public List AssistAvatarList { get; set; } = [];
+ public List DisplayAvatarList { get; set; } = [];
+
+ // Mission info
+ public List FinishedMainMissionIdList { get; set; } = [];
+ public List FinishedSubMissionIdList { get; set; } = [];
+ public List AcceptedMainMissionIdList { get; set; } = [];
+ public List AcceptedSubMissionIdList { get; set; } = [];
+
+ }
+}
diff --git a/WebServer/Server/MuipManager.cs b/WebServer/Server/MuipManager.cs
index 29573e62..4c572d45 100644
--- a/WebServer/Server/MuipManager.cs
+++ b/WebServer/Server/MuipManager.cs
@@ -7,6 +7,14 @@ 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 EggLink.DanhengServer.Database;
+using EggLink.DanhengServer.Database.Avatar;
+using EggLink.DanhengServer.Database.Mission;
+using EggLink.DanhengServer.Enums;
+using Spectre.Console;
namespace EggLink.DanhengServer.WebServer.Server
{
@@ -14,6 +22,10 @@ namespace EggLink.DanhengServer.WebServer.Server
{
public delegate void ExecuteCommandDelegate(string message, MuipCommandSender sender);
public static event ExecuteCommandDelegate? OnExecuteCommand;
+ public delegate void ServerInformationDelegate(Dictionary resultData);
+ public static event ServerInformationDelegate? OnGetServerInformation;
+ public delegate void GetPlayerStatusDelegate(int uid, out PlayerStatusEnum status);
+ public static event GetPlayerStatusDelegate? OnGetPlayerStatus;
public static string RsaPublicKey { get; private set; } = "";
public static string RsaPrivateKey { get; private set; } = "";
@@ -113,6 +125,108 @@ namespace EggLink.DanhengServer.WebServer.Server
return new(2, "Session not found!");
}
+ 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();
+
+ 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();
+ 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();
+ var sync = Task.Run(() => OnGetServerInformation?.Invoke(result));
+
+ sync.Wait();
+
+ result.TryGetValue(uid, out var player);
+ if (player == null) return new(2, "Player not exist or is offline!", null);
+
+ var status = PlayerStatusEnum.Offline;
+
+ var statusSync = Task.Run(() => OnGetPlayerStatus?.Invoke(player.Uid, out status));
+
+ statusSync.Wait();
+
+ var avatarData = DatabaseHelper.Instance!.GetInstance(player.Uid)!;
+ var missionData = DatabaseHelper.Instance!.GetInstance(player.Uid)!;
+
+ 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
+ });
+ }
+ return new(3, "Session not found!", null);
+ }
+
+ #region Tools
+
///
/// get rsa key pair
///
@@ -167,5 +281,57 @@ namespace EggLink.DanhengServer.WebServer.Server
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;
+ }
+
+ #endregion
}
}
diff --git a/WebServer/WebServer.csproj b/WebServer/WebServer.csproj
index 3e1dff7d..7d1e0f58 100644
--- a/WebServer/WebServer.csproj
+++ b/WebServer/WebServer.csproj
@@ -19,6 +19,7 @@
+