From d8980c87addc192c10686fc7bd5e5f17f835cff2 Mon Sep 17 00:00:00 2001 From: Somebody Date: Sun, 23 Nov 2025 11:45:31 +0800 Subject: [PATCH] chore: upgrade to `net9.0` & upgrade packages --- Command/Command.csproj | 6 +- Common/Common.csproj | 21 ++- Common/Util/ICommand.cs | 243 +++++++++++++++++++++++++ Common/Util/Logger.cs | 4 + DanhengKcpSharp/DanhengKcpSharp.csproj | 8 +- GameServer/GameServer.csproj | 12 +- Program/Program.csproj | 6 +- Program/Program/EntryPoint.cs | 15 +- Proto/Proto.csproj | 4 +- ServerSideProto/ServerSideProto.csproj | 4 +- WebServer/WebServer.csproj | 20 +- 11 files changed, 300 insertions(+), 43 deletions(-) create mode 100644 Common/Util/ICommand.cs diff --git a/Command/Command.csproj b/Command/Command.csproj index a77170da..63fc59b6 100644 --- a/Command/Command.csproj +++ b/Command/Command.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable EggLink.DanhengServer.Command @@ -9,8 +9,8 @@ - - + + diff --git a/Common/Common.csproj b/Common/Common.csproj index 3e0adf1c..7a2fa03a 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable EggLink.DanhengServer @@ -9,17 +9,18 @@ - - + + + - - - - - - - + + + + + + + diff --git a/Common/Util/ICommand.cs b/Common/Util/ICommand.cs new file mode 100644 index 00000000..e9c6d378 --- /dev/null +++ b/Common/Util/ICommand.cs @@ -0,0 +1,243 @@ +using Kodnix.Character; + +namespace EggLink.DanhengServer.Util +{ + public static class IConsole + { + public const string PrefixContent = "> "; + private const string PinkColor = "\e[38;2;255;192;203m"; + private const string RedColor = "\e[38;2;255;0;0m"; + private const string ResetColor = "\e[0m"; + + // coloured prefix + public static string Prefix => $"{(IsCommandValid ? ResetColor : RedColor)}{PrefixContent}{ResetColor}"; + + public static bool IsCommandValid { get; private set; } = true; + private const int HistoryMaxCount = 10; + + public static List Input { get; set; } = []; + private static int CursorIndex { get; set; } + private static readonly List InputHistory = []; + private static int HistoryIndex = -1; + + public static event Action? OnConsoleExcuteCommand; + + public static void InitConsole() + { + Console.Title = "Danheng Server"; + } + + public static int GetWidth(string str) + => str.ToCharArray().Sum(EastAsianWidth.GetLength); + + public static void RedrawInput(List input, bool hasPrefix = true) + => RedrawInput(new string([.. input]), hasPrefix); + + public static void RedrawInput(string input, bool hasPrefix = true) + { + // check validity + UpdateCommandValidity(input); + + var length = GetWidth(input); + if (hasPrefix) + { + input = Prefix + input; + length += GetWidth(PrefixContent); + } + + if (Console.GetCursorPosition().Left > 0) + Console.SetCursorPosition(0, Console.CursorTop); + + Console.Write(input + new string(' ', Console.BufferWidth - length)); + + Console.SetCursorPosition(length, Console.CursorTop); + CursorIndex = length - GetWidth(PrefixContent); + } + + // check validity and update + private static void UpdateCommandValidity(string input) + { + IsCommandValid = CheckCommandValid(input); + } + + #region Handlers + + public static void HandleEnter() + { + var input = new string([.. Input]); + if (string.IsNullOrWhiteSpace(input)) return; + + // New line + Console.WriteLine(); + Input = []; + CursorIndex = 0; + if (InputHistory.Count >= HistoryMaxCount) + InputHistory.RemoveAt(0); + InputHistory.Add(input); + HistoryIndex = InputHistory.Count; + + // Handle command + if (input.StartsWith('/')) input = input[1..].Trim(); + OnConsoleExcuteCommand?.Invoke(input); + + // reset + IsCommandValid = true; + } + + public static void HandleBackspace() + { + if (CursorIndex <= 0) return; + CursorIndex--; + var targetWidth = GetWidth(Input[CursorIndex].ToString()); + Input.RemoveAt(CursorIndex); + + var (left, _) = Console.GetCursorPosition(); + Console.SetCursorPosition(left - targetWidth, Console.CursorTop); + var remain = new string([.. Input.Skip(CursorIndex)]); + Console.Write(remain + new string(' ', targetWidth)); + Console.SetCursorPosition(left - targetWidth, Console.CursorTop); + + // update + var prev = IsCommandValid; + UpdateCommandValidity(new string([.. Input])); + + if (IsCommandValid != prev) + { + RedrawInput(Input); + } + } + + public static void HandleUpArrow() + { + if (InputHistory.Count == 0) return; + if (HistoryIndex <= 0) return; + + HistoryIndex--; + var history = InputHistory[HistoryIndex]; + Input = [.. history]; + CursorIndex = Input.Count; + + // update + UpdateCommandValidity(history); + RedrawInput(Input); + } + + public static void HandleDownArrow() + { + if (HistoryIndex >= InputHistory.Count) return; + + HistoryIndex++; + if (HistoryIndex >= InputHistory.Count) + { + HistoryIndex = InputHistory.Count; + Input = []; + CursorIndex = 0; + IsCommandValid = true; + } + else + { + var history = InputHistory[HistoryIndex]; + Input = [.. history]; + CursorIndex = Input.Count; + // update + UpdateCommandValidity(history); + } + RedrawInput(Input); + } + + public static void HandleLeftArrow() + { + if (CursorIndex <= 0) return; + + var (left, _) = Console.GetCursorPosition(); + CursorIndex--; + Console.SetCursorPosition(left - GetWidth(Input[CursorIndex].ToString()), Console.CursorTop); + } + + public static void HandleRightArrow() + { + if (CursorIndex >= Input.Count) return; + + var (left, _) = Console.GetCursorPosition(); + CursorIndex++; + Console.SetCursorPosition(left + GetWidth(Input[CursorIndex - 1].ToString()), Console.CursorTop); + } + + public static void HandleInput(ConsoleKeyInfo keyInfo) + { + if (char.IsControl(keyInfo.KeyChar)) return; + var newWidth = GetWidth(new string([.. Input])) + GetWidth(keyInfo.KeyChar.ToString()); + if (newWidth >= (Console.BufferWidth - GetWidth(PrefixContent))) return; + HandleInput(keyInfo.KeyChar); + } + + public static void HandleInput(char keyChar) + { + Input.Insert(CursorIndex, keyChar); + CursorIndex++; + + var (left, _) = Console.GetCursorPosition(); + var newCursor = left + GetWidth(keyChar.ToString()); + if (newCursor > Console.BufferWidth - 1) newCursor = Console.BufferWidth - 1; + + Console.Write(new string([.. Input.Skip(CursorIndex - 1)])); + Console.SetCursorPosition(newCursor, Console.CursorTop); + + // update + var prev = IsCommandValid; + UpdateCommandValidity(new string([.. Input])); + + if (IsCommandValid != prev) + { + RedrawInput(Input); + } + } + + #endregion + + public static string ListenConsole() + { + while (true) + { + ConsoleKeyInfo keyInfo; + try { keyInfo = Console.ReadKey(true); } + catch (InvalidOperationException) { continue; } + + switch (keyInfo.Key) + { + case ConsoleKey.Enter: + HandleEnter(); + break; + case ConsoleKey.Backspace: + HandleBackspace(); + break; + case ConsoleKey.LeftArrow: + HandleLeftArrow(); + break; + case ConsoleKey.RightArrow: + HandleRightArrow(); + break; + case ConsoleKey.UpArrow: + HandleUpArrow(); + break; + case ConsoleKey.DownArrow: + HandleDownArrow(); + break; + default: + HandleInput(keyInfo); + break; + } + } + } + + private static bool CheckCommandValid(string input) + { + if (string.IsNullOrEmpty(input)) + return true; + + var invalidChars = new[] { '@', '#', '$', '%', '&', '*' }; + return !invalidChars.Any(c => input.Contains(c)); + } + } + +} diff --git a/Common/Util/Logger.cs b/Common/Util/Logger.cs index 72406132..becedf35 100644 --- a/Common/Util/Logger.cs +++ b/Common/Util/Logger.cs @@ -13,9 +13,13 @@ public class Logger(string moduleName) { lock (Lock) { + var savedInput = IConsole.Input.ToList(); // Copy + IConsole.RedrawInput("", false); AnsiConsole.Write(new Markup($"[[[bold deepskyblue3_1]{DateTime.Now:HH:mm:ss}[/]]] " + $"[[[gray]{moduleName}[/]]] [[[{(ConsoleColor)level}]{level}[/]]] {message.Replace("[", "[[").Replace("]", "]]")}\n")); + IConsole.RedrawInput(savedInput); + var logMessage = $"[{DateTime.Now:HH:mm:ss}] [{moduleName}] [{level}] {message}"; PluginEventCommon.InvokeOnConsoleLog(logMessage); diff --git a/DanhengKcpSharp/DanhengKcpSharp.csproj b/DanhengKcpSharp/DanhengKcpSharp.csproj index 43ee9fa3..39b1cd2a 100644 --- a/DanhengKcpSharp/DanhengKcpSharp.csproj +++ b/DanhengKcpSharp/DanhengKcpSharp.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable DanhengKcpSharp @@ -9,9 +9,9 @@ - - - + + + diff --git a/GameServer/GameServer.csproj b/GameServer/GameServer.csproj index 170a78f2..9bc4d105 100644 --- a/GameServer/GameServer.csproj +++ b/GameServer/GameServer.csproj @@ -2,7 +2,7 @@ Library - net8.0 + net9.0 enable enable EggLink.DanhengServer.GameServer @@ -21,11 +21,11 @@ - - - - - + + + + + diff --git a/Program/Program.csproj b/Program/Program.csproj index 0a963cb6..437523f9 100644 --- a/Program/Program.csproj +++ b/Program/Program.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable EggLink.DanhengServer.Program @@ -15,8 +15,8 @@ - - + + diff --git a/Program/Program/EntryPoint.cs b/Program/Program/EntryPoint.cs index cbe7c5ec..a28a7211 100644 --- a/Program/Program/EntryPoint.cs +++ b/Program/Program/EntryPoint.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.IO.Compression; +using EggLink.DanhengServer.Command; using EggLink.DanhengServer.Command.Command; using EggLink.DanhengServer.Configuration; using EggLink.DanhengServer.Data; @@ -19,6 +18,8 @@ using EggLink.DanhengServer.Program.Handbook; using EggLink.DanhengServer.Util; using EggLink.DanhengServer.WebServer; using EggLink.DanhengServer.WebServer.Server; +using System.Globalization; +using System.IO.Compression; namespace EggLink.DanhengServer.Program.Program; @@ -31,6 +32,8 @@ public class EntryPoint public static async Task Main(string[] args) { + IConsole.InitConsole(); + IConsole.RedrawInput(IConsole.Input); AppDomain.CurrentDomain.ProcessExit += (_, _) => { Logger.Info(I18NManager.Translate("Server.ServerInfo.Shutdown")); @@ -417,7 +420,13 @@ public class EntryPoint ResourceManager.IsLoaded = true; - CommandManager.Start(); + IConsole.OnConsoleExcuteCommand += command => + { + CommandManager.HandleCommand(command, new ConsoleCommandSender(Logger)); + IConsole.RedrawInput(IConsole.Input); + }; + + IConsole.ListenConsole(); } public static ConfigContainer GetConfig() diff --git a/Proto/Proto.csproj b/Proto/Proto.csproj index e4ee3a6a..88992a11 100644 --- a/Proto/Proto.csproj +++ b/Proto/Proto.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable DanhengProto @@ -9,7 +9,7 @@ - + diff --git a/ServerSideProto/ServerSideProto.csproj b/ServerSideProto/ServerSideProto.csproj index bc563847..703fe162 100644 --- a/ServerSideProto/ServerSideProto.csproj +++ b/ServerSideProto/ServerSideProto.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable EggLink.DanhengServer.Proto.ServerSide @@ -9,7 +9,7 @@ - + diff --git a/WebServer/WebServer.csproj b/WebServer/WebServer.csproj index 48506dab..07942e21 100644 --- a/WebServer/WebServer.csproj +++ b/WebServer/WebServer.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable EggLink.DanhengServer.WebServer @@ -10,16 +10,16 @@ - - - + + + - - - - - - + + + + + +