diff --git a/src/DiIiS-NA/BGS-Server/AccountsSystem/AccountManager.cs b/src/DiIiS-NA/BGS-Server/AccountsSystem/AccountManager.cs index b841007..bc57e00 100644 --- a/src/DiIiS-NA/BGS-Server/AccountsSystem/AccountManager.cs +++ b/src/DiIiS-NA/BGS-Server/AccountsSystem/AccountManager.cs @@ -154,7 +154,7 @@ namespace DiIiS_NA.LoginServer.AccountsSystem return null; } else - Logger.Debug("GetAccountByEmail id - \"{0}\"", dbAcc.First().Id); + Logger.MethodTrace("GetAccountByEmail id - \"{0}\"", dbAcc.First().Id); return GetAccountByDBAccount(dbAcc.First()); } } diff --git a/src/DiIiS-NA/BGS-Server/Battle/BattleBackend.cs b/src/DiIiS-NA/BGS-Server/Battle/BattleBackend.cs index 5e58205..9c7e554 100644 --- a/src/DiIiS-NA/BGS-Server/Battle/BattleBackend.cs +++ b/src/DiIiS-NA/BGS-Server/Battle/BattleBackend.cs @@ -42,27 +42,27 @@ namespace DiIiS_NA.LoginServer.Battle public Dictionary PvPGameServers = new Dictionary(); - public BattleBackend(string BattletHost, int BackPort) + public BattleBackend(string battleHost, int port) { - this.GameServerSocket = new WatsonTcpServer(BattletHost, BackPort, this._receiverClientConnected, this._receiverClientDisconnected, this._receiverMessageReceived, false); + GameServerSocket = new WatsonTcpServer(battleHost, port, ReceiverClientConnected, ReceiverClientDisconnected, ReceiverMessageReceived, false); System.Threading.Thread.Sleep(3000); } - private bool _receiverClientConnected(string ipPort) + private bool ReceiverClientConnected(string ipPort) { - Logger.Info("Game server loaded {0} connecting to BlizzLess.Net...", ipPort); + Logger.Info($"Blizzless server loaded {ipPort} - connecting..."); return true; } - private bool _receiverClientDisconnected(string ipPort) + private bool ReceiverClientDisconnected(string ipPort) { - Logger.Warn("GameServer at {0} was disconnected!", ipPort); - if (this.GameServers.ContainsKey(ipPort)) this.GameServers.Remove(ipPort); - if (this.PvPGameServers.ContainsKey(ipPort)) this.PvPGameServers.Remove(ipPort); + Logger.Warn("Blizzless server at {0} was disconnected!", ipPort); + if (GameServers.ContainsKey(ipPort)) GameServers.Remove(ipPort); + if (PvPGameServers.ContainsKey(ipPort)) PvPGameServers.Remove(ipPort); - if (this.GameServers.Count == 0) + if (GameServers.Count == 0) Logger.Warn("GameServers list is empty! Unable to use PvE game activities atm."); - if (this.PvPGameServers.Count == 0) + if (PvPGameServers.Count == 0) Logger.Warn("PvPGameServers list is empty! Unable to use PvP game activities atm."); return true; } @@ -72,7 +72,7 @@ namespace DiIiS_NA.LoginServer.Battle GameServerSocket.Send(ipPort, Encoding.UTF8.GetBytes(string.Format("diiiscg|{0}/{1}/{2}/{3}/{4}/{5}/{6}/{7}/{8}", GameId, level, act, difficulty, questId, questStepId, isHardcore, gamemode, iSseasoned, perftest_id))); } - private bool _receiverMessageReceived(string ipPort, byte[] data) + private bool ReceiverMessageReceived(string ipPort, byte[] data) { string msg = ""; if (data != null && data.Length > 0) msg = Encoding.UTF8.GetString(data); @@ -83,17 +83,17 @@ namespace DiIiS_NA.LoginServer.Battle switch (message[0]) { case "rngsr": - if (this.GameServers.ContainsKey(ipPort)) this.GameServers.Remove(ipPort); + if (GameServers.ContainsKey(ipPort)) GameServers.Remove(ipPort); string rgs_ip = args[0]; int rgs_port = int.Parse(args[1].Trim()); - this.GameServers.Add(ipPort, new ServerDescriptor { GameIP = rgs_ip, GamePort = rgs_port }); - Logger.Info("Game server was registred for BlizzLess.Net {0}:{1}.", rgs_ip, rgs_port); + GameServers.Add(ipPort, new ServerDescriptor { GameIP = rgs_ip, GamePort = rgs_port }); + Logger.Info("Game server was registered for Blizzless {0}:{1}.", rgs_ip, rgs_port); break; case "rnpvpgsr": - if (this.PvPGameServers.ContainsKey(ipPort)) this.PvPGameServers.Remove(ipPort); + if (PvPGameServers.ContainsKey(ipPort)) PvPGameServers.Remove(ipPort); string rpgs_ip = args[0]; int rpgs_port = int.Parse(args[1].Trim()); - this.PvPGameServers.Add(ipPort, new ServerDescriptor { GameIP = rpgs_ip, GamePort = rpgs_port }); + PvPGameServers.Add(ipPort, new ServerDescriptor { GameIP = rpgs_ip, GamePort = rpgs_port }); Logger.Info("PvP GameServer at {0}:{1} successfully signed and ready to work.", rpgs_ip, rpgs_port); break; case "grachi": @@ -292,7 +292,7 @@ namespace DiIiS_NA.LoginServer.Battle System.Threading.Tasks.Task.Delay(1).ContinueWith((a) => { try { - LoginServer.Toons.ToonManager.GetToonByLowID((ulong)tsc_toonId).StateChanged(); + Toons.ToonManager.GetToonByLowID((ulong)tsc_toonId).StateChanged(); } catch { } }); diff --git a/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/ConnectionSerivce.cs b/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/ConnectionSerivce.cs index a280328..c28dfb3 100644 --- a/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/ConnectionSerivce.cs +++ b/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/ConnectionSerivce.cs @@ -19,7 +19,7 @@ using DiIiS_NA.Core.Extensions; namespace DiIiS_NA.LoginServer.ServicesSystem.Services { [Service(serviceID: 0x0, serviceHash: 1698982289)] - public class ConnectionSerivce : ConnectionService, IServerService + public class ConnectionSvc : ConnectionService, IServerService { private static readonly Logger Logger = LogManager.CreateLogger(); public override void Bind(IRpcController controller, BindRequest request, Action done) @@ -35,9 +35,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services .SetClientId(ProcessId.CreateBuilder().SetLabel(1).SetEpoch(DateTime.Now.ToUnixTime())); if (request.HasUseBindlessRpc) builder.SetUseBindlessRpc(true); - - - + (controller as HandlerController).Client.Services.Add(0x54DFDA17, 0x01); (controller as HandlerController).Client.Services.Add(0xD4DCD093, 0x02); (controller as HandlerController).Client.Services.Add(0x71240E35, 0x03); @@ -60,7 +58,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services (controller as HandlerController).Client.Services.Add(2119327385, 0x26); done(builder.Build()); - Logger.Info("Connect with BlizzLess.Net established. Client - {0}", (controller as HandlerController).Client.SocketConnection.RemoteAddress); + Logger.Info("Connect with $[dodgerblue1]$Blizz$[/]$$[deepskyblue2]$less$[/]$ established. Client - {0}", (controller as HandlerController).Client.SocketConnection.RemoteAddress); } public override void Echo(IRpcController controller, EchoRequest request, Action done) @@ -84,7 +82,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services public override void RequestDisconnect(IRpcController controller, DisconnectRequest request, Action done) { - Console.WriteLine("Клиент - {0} , отключен", (controller as HandlerController).Client.SocketConnection.RemoteAddress); + Logger.Info("Client - {0} , disconnected", (controller as HandlerController).Client.SocketConnection.RemoteAddress); this.DisconnectClient(controller as HandlerController); if ((controller as HandlerController).Client.Account != null) (controller as HandlerController).Client.Account.GameAccount.Logined = false; diff --git a/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/PresenceService.cs b/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/PresenceService.cs index f38b8a5..a9961da 100644 --- a/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/PresenceService.cs +++ b/src/DiIiS-NA/BGS-Server/ServicesSystem/Services/PresenceService.cs @@ -43,7 +43,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services var account = AccountManager.GetAccountByPersistentID(req.Low); if (account != null) { - Logger.Debug("Subscribe() {0} {1}", (((HandlerController)controller).Client), account); + Logger.MethodTrace("Subscribe() {0} {1}", (((HandlerController)controller).Client), account); account.AddSubscriber((((HandlerController)controller).Client), request.ObjectId); response.AddSubscribeFailed(SubscribeResult.CreateBuilder().SetEntityId(req) .SetResult(0)); @@ -55,7 +55,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services var gameAccount = GameAccountManager.GetAccountByPersistentID(req.Low); if (gameAccount != null) { - Logger.Debug("Subscribe() {0} {1}", (((HandlerController)controller).Client), + Logger.MethodTrace("Subscribe() {0} {1}", (((HandlerController)controller).Client), gameAccount); gameAccount.AddSubscriber((((HandlerController)controller).Client), request.ObjectId); response.AddSubscribeFailed(SubscribeResult.CreateBuilder().SetEntityId(req) @@ -64,7 +64,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services } break; default: - Logger.Warn("Recieved an unhandled Presence.Subscribe request with type {0} (0x{1})", req.GetHighIdType(), req.High.ToString("X16")); + Logger.Warn("Received an unhandled Presence.Subscribe request with type {0} (0x{1})", req.GetHighIdType(), req.High.ToString("X16")); break; } } @@ -133,7 +133,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services var gameAccount = AccountManager.GetAccountByPersistentID(request.EntityId.Low); if (gameAccount != null) { - Logger.Trace("Subscribe() {0} {1}", (((HandlerController)controller).Client), gameAccount); + Logger.MethodTrace("Subscribe() {0} {1}", (((HandlerController)controller).Client), gameAccount); gameAccount.AddSubscriber((((HandlerController)controller).Client), request.ObjectId); } } @@ -143,7 +143,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services var gameaccount = GameAccountManager.GetAccountByPersistentID(request.EntityId.Low); if (gameaccount != null) { - Logger.Debug("Subscribe() {0} {1}", (((HandlerController)controller).Client), gameaccount); + Logger.MethodTrace("Subscribe() {0} {1}", (((HandlerController)controller).Client), gameaccount); gameaccount.AddSubscriber((((HandlerController)controller).Client), request.ObjectId); } } @@ -170,7 +170,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services if (gameAccount != null) { gameAccount.RemoveSubscriber((((HandlerController) controller).Client)); - Logger.Debug("Unsubscribe() {0} {1}", (((HandlerController) controller).Client), gameAccount); + Logger.MethodTrace("Unsubscribe() {0} {1}", (((HandlerController) controller).Client), gameAccount); } } break; @@ -180,7 +180,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services if (gameAccount != null) { gameAccount.RemoveSubscriber((((HandlerController) controller).Client)); - Logger.Debug("Unsubscribe() {0} {1}", (((HandlerController) controller).Client), gameAccount); + Logger.MethodTrace("Unsubscribe() {0} {1}", (((HandlerController) controller).Client), gameAccount); } } break; @@ -212,7 +212,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services } gameAccount.Update(request.FieldOperationList); - Logger.Debug(traceData); + Logger.MethodTrace(traceData); } break; case EntityIdHelper.HighIdType.GameAccountId: @@ -229,7 +229,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services } gameAccount.Update(request.FieldOperationList); - Logger.Debug(traceData); + Logger.MethodTrace(traceData); break; } default: diff --git a/src/DiIiS-NA/Core/Logging/AnsiTarget.cs b/src/DiIiS-NA/Core/Logging/AnsiTarget.cs new file mode 100644 index 0000000..63edd80 --- /dev/null +++ b/src/DiIiS-NA/Core/Logging/AnsiTarget.cs @@ -0,0 +1,139 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Spectre.Console; + +namespace DiIiS_NA.Core.Logging; + +public class AnsiTarget : LogTarget +{ + private readonly Table _table; + private static CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource(); + private static bool _shutdown = true; + + public AnsiTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTimeStamps) + { + _shutdown = false; + MinimumLevel = minLevel; + MaximumLevel = maxLevel; + IncludeTimeStamps = includeTimeStamps; + + _table = new Table().Expand().ShowFooters().ShowHeaders().Border(TableBorder.Rounded); + + if (IncludeTimeStamps) + _table.AddColumn("Time"); + _table + .AddColumn("Level") + .AddColumn("Logger") + .AddColumn("Message") + .AddColumn("Error"); + + AnsiConsole.Live(_table).StartAsync(async ctx => + { + int lastCount = 0; + int consoleSize = 0; + while (!CancellationTokenSource.Token.IsCancellationRequested) + { + int currentConsoleSize = 0; + try + { + currentConsoleSize = Console.WindowHeight * Console.WindowWidth; + } + catch {} + if (lastCount != _table.Rows.Count || consoleSize != currentConsoleSize) + { + lastCount = _table.Rows.Count; + consoleSize = currentConsoleSize; + ctx.UpdateTarget(_table); + } + await Task.Delay(100); + } + + }); + } + + public static void StopIfRunning() + { + CancellationTokenSource.Cancel(); + } + + + public static string Filter(string text) + { + return text + .Replace("Blizzless", "[dodgerblue1]Blizz[/][deepskyblue2]less[/]") + .Replace("Diablo III", "[red3_1]Diablo[/] [red]III[/]") + .Replace("MPQ", "[underline yellow4]MPQ[/]"); + } + + + /// + /// Performs a cleanup on the target. + /// All [ becomes [[, and ] becomes ]] (for ignoring ANSI codes) + /// To use a style, use $[..]$abc$[/]$. + /// Example: + /// Logger.Warn("This is a $[red]$red$[/]$ message"); + /// instead of + /// Logger.Warn("This is a [red]red[/] message"); + /// + /// + /// + string Cleanup(string x) => Filter(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]")); + + public override void LogMessage(Logger.Level level, string logger, string message) + { + if (CancellationTokenSource.IsCancellationRequested) + return; + if (IncludeTimeStamps) + _table.AddRow( + new Markup(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff"), GetStyleByLevel(level)), + new Markup(level.ToString(), GetStyleByLevel(level)), + new Markup(logger, GetStyleByLevel(level)), + new Markup(Cleanup(message), GetStyleByLevel(level)), + new Markup("N/A")); + else + _table.AddRow( + new Markup(level.ToString()), + new Markup(logger, GetStyleByLevel(level)), + new Markup(Cleanup(message), GetStyleByLevel(level)), + new Markup("N/A")); + } + + public override void LogException(Logger.Level level, string logger, string message, Exception exception) + { + if (CancellationTokenSource.IsCancellationRequested) + return; + if (IncludeTimeStamps) + _table.AddRow( + new Markup(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff"), GetStyleByLevel(level)), + new Markup(level.ToString(), GetStyleByLevel(level)), + new Markup(logger, GetStyleByLevel(level)), + new Markup(Cleanup(message), GetStyleByLevel(level)), + new Markup($"[underline red3_1 on white]{exception.GetType().Name}[/]\n" + Cleanup(exception.Message), new Style(foreground: Color.Red3_1))); + else + _table.AddRow( + new Markup(level.ToString()), + new Markup(logger, GetStyleByLevel(level)), + new Markup(message, GetStyleByLevel(level)), + new Markup($"[underline red3_1 on white]{exception.GetType().Name}[/]\n" + Cleanup(exception.Message), new Style(foreground: Color.Red3_1))); + } + + private static Style GetStyleByLevel(Logger.Level level) + { + return level switch + { + Logger.Level.RenameAccountLog => new Style(Color.DarkSlateGray3),// + Logger.Level.ChatMessage => new Style(Color.DarkSlateGray2),// + Logger.Level.Debug => new Style(Color.Purple4),// + Logger.Level.MethodTrace => new Style(Color.Purple4_1),// + Logger.Level.Trace => new Style(Color.Purple),// + Logger.Level.Info => new Style(Color.White), + Logger.Level.Success => new Style(Color.Green3_1), + Logger.Level.Warn => new Style(Color.Yellow),// + Logger.Level.Error => new Style(Color.IndianRed1),// + Logger.Level.Fatal => new Style(Color.Red3_1),// + Logger.Level.PacketDump => new Style(Color.Maroon),// + _ => new Style(Color.White) + }; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs b/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs index c1d3c0e..a5935ba 100644 --- a/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs +++ b/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Spectre.Console; namespace DiIiS_NA.Core.Logging { @@ -17,14 +18,14 @@ namespace DiIiS_NA.Core.Logging IncludeTimeStamps = includeTimeStamps; } + /// Log level. /// Source of the log message. /// Log message. public override void LogMessage(Logger.Level level, string logger, string message) { - var timeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : ""; - SetConsoleForegroundColor(level); - Console.WriteLine($"{timeStamp}[{level.ToString(),8}] [{logger,20}]: {message}"); + var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff") + "]] " : ""; + AnsiConsole.MarkupLine($"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {Cleanup(message)}[/]"); } /// Log level. @@ -33,43 +34,50 @@ namespace DiIiS_NA.Core.Logging /// Exception to be included with log message. public override void LogException(Logger.Level level, string logger, string message, Exception exception) { - var timeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : ""; - SetConsoleForegroundColor(level); - Console.WriteLine( - $"{timeStamp}[{level.ToString(),8}] [{logger,20}]: {message} - [Exception] {exception}"); + var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff") + "]] " : ""; + + AnsiConsole.MarkupLine( + $"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {Cleanup(message)}[/] - [underline red on white][[{exception.GetType().Name}]][/][red] {Cleanup(exception.Message)}[/]"); } + + + /// + /// Performs a cleanup on the target. + /// All [ becomes [[, and ] becomes ]] (for ignoring ANSI codes) + /// To use a style, use $[..]$abc$[/]$. + /// Example: + /// Logger.Warn("This is a $[red]$red$[/]$ message"); + /// instead of + /// Logger.Warn("This is a [red]red[/] message"); + /// + /// + /// + string Cleanup(string x) => AnsiTarget.Filter(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]")); /// - private static void SetConsoleForegroundColor(Logger.Level level) + private static string SetColor(Logger.Level level, bool withBackground = false) { + string postfix = withBackground ? " on grey19" : ""; switch (level) { case Logger.Level.PacketDump: - Console.ForegroundColor = ConsoleColor.DarkGray; - break; + return $"[grey30{postfix}]"; case Logger.Level.Debug: - Console.ForegroundColor = ConsoleColor.DarkCyan; - break; + return $"[grey39{postfix}]"; case Logger.Level.Trace: - Console.ForegroundColor = ConsoleColor.Cyan; - break; + return $"[purple{postfix}]"; case Logger.Level.Info: - Console.ForegroundColor = ConsoleColor.White; - break; + return $"[white{postfix}]"; case Logger.Level.Success: - Console.ForegroundColor = ConsoleColor.DarkGreen; - break; + return $"[green3_1{postfix}]"; case Logger.Level.Warn: - Console.ForegroundColor = ConsoleColor.Yellow; - break; + return $"[darkorange3_1{postfix}]"; case Logger.Level.Error: - Console.ForegroundColor = ConsoleColor.Magenta; - break; + return "[indianred1{postfix}]"; case Logger.Level.Fatal: - Console.ForegroundColor = ConsoleColor.Red; - break; + return $"[red3{postfix}]"; default: - break; + return $"[navajowhite3{postfix}]"; } } } diff --git a/src/DiIiS-NA/Core/Logging/LogConfig.cs b/src/DiIiS-NA/Core/Logging/LogConfig.cs index d5e4e4e..08cc892 100644 --- a/src/DiIiS-NA/Core/Logging/LogConfig.cs +++ b/src/DiIiS-NA/Core/Logging/LogConfig.cs @@ -12,6 +12,7 @@ namespace DiIiS_NA.Core.Logging public LogTargetConfig[] Targets = new[] { new LogTargetConfig("ConsoleLog"), + new LogTargetConfig("AnsiLog") //new LogTargetConfig("ServerLog"), //new LogTargetConfig("ChatLog"), //new LogTargetConfig("RenameAccountLog"), diff --git a/src/DiIiS-NA/Core/MPQ/MPQStorage.cs b/src/DiIiS-NA/Core/MPQ/MPQStorage.cs index 01e508e..aa566e2 100644 --- a/src/DiIiS-NA/Core/MPQ/MPQStorage.cs +++ b/src/DiIiS-NA/Core/MPQ/MPQStorage.cs @@ -36,7 +36,7 @@ namespace DiIiS_NA.Core.MPQ return; } - Logger.Info("Initializing of data.."); + Logger.Info("Initializing MPQ archives..."); MPQList = FileHelpers.GetFilesByExtensionRecursive(MpqRoot, ".mpq"); Data = new Data(); diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/GameSystem/GSBackend.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/GameSystem/GSBackend.cs index e3073ac..63e95ae 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/GameSystem/GSBackend.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/GameSystem/GSBackend.cs @@ -23,9 +23,9 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem public WatsonTcpClient BattleNetSocket; - public GsBackend(string battletHost, int battlePort) + public GsBackend(string battleHost, int battlePort) { - BattleNetSocket = new WatsonTcpClient(battletHost, battlePort, SenderServerConnected, SenderServerDisconnected, SenderMessageReceived, false); + BattleNetSocket = new WatsonTcpClient(battleHost, battlePort, SenderServerConnected, SenderServerDisconnected, SenderMessageReceived, false); } @@ -56,6 +56,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem game.SetQuestProgress(int.Parse(args[4].Trim()), int.Parse(args[5].Trim())); if (args.Length > 9) if (int.Parse(args[9].Trim()) > 0) game.EnablePerfTest(int.Parse(args[9].Trim())); + //Good job, you reverse God, AiDIEvE =) } } diff --git a/src/DiIiS-NA/Program.cs b/src/DiIiS-NA/Program.cs index 585e74a..8d387d2 100644 --- a/src/DiIiS-NA/Program.cs +++ b/src/DiIiS-NA/Program.cs @@ -62,6 +62,8 @@ using System.Security.Permissions; using System.Threading; //Blizzless Project 2022 using System.Threading.Tasks; +using Spectre.Console; +using Environment = System.Environment; namespace DiIiS_NA { @@ -86,11 +88,23 @@ namespace DiIiS_NA public static string RESTSERVERIP = DiIiS_NA.REST.Config.Instance.IP; public static string PUBLICGAMESERVERIP = DiIiS_NA.GameServer.NATConfig.Instance.PublicIP; - public static int Build = 29; - public static int Stage = 4; - public static string TypeBuild = "Beta"; - public static bool D3CoreEnabled = DiIiS_NA.GameServer.Config.Instance.CoreActive; + public static int Build = 30; + private static readonly int Stage = 1; + private static readonly string TypeBuild = "BETA"; + private static bool D3CoreEnabled = DiIiS_NA.GameServer.Config.Instance.CoreActive; + static bool SetTitle(string text) + { + try + { + Console.Title = text; + return true; + } + catch (PlatformNotSupportedException) + { + return false; + } + } static async Task LoginServer() { #if DEBUG @@ -101,10 +115,15 @@ namespace DiIiS_NA Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string name = $"Blizzless: Build {Build}, Stage: {Stage} - {TypeBuild}"; - Console.WriteLine(" " + name); - Console.WriteLine("Connected Module: 0x00 - Diablo 3 RoS 2.7.4.84161"); - Console.WriteLine("------------------------------------------------------------------------"); - Console.ResetColor(); + SetTitle(name); + AnsiConsole.Write(new Rule("[dodgerblue1]Blizz[/][deepskyblue2]less[/]").RuleStyle("steelblue1")); + AnsiConsole.Write(new Rule($"[dodgerblue3]Build [/][deepskyblue3]{Build}[/]").RightJustified().RuleStyle("steelblue1_1")); + AnsiConsole.Write(new Rule($"[dodgerblue3]Stage [/][deepskyblue3]{Stage}[/]").RightJustified().RuleStyle("steelblue1_1")); + AnsiConsole.Write(new Rule($"[deepskyblue3]{TypeBuild}[/]").RightJustified().RuleStyle("steelblue1_1")); + AnsiConsole.Write(new Rule($"[red3_1]Diablo III[/] [red]RoS 2.7.4.84161[/] - [link=https://github.com/blizzless/blizzless-diiis]https://github.com/blizzless/blizzless-diiis[/]").RuleStyle("red")); + + AnsiConsole.MarkupLine(""); + Console.WriteLine(); Console.Title = name; InitLoggers(); @@ -113,12 +132,11 @@ namespace DiIiS_NA Task.Run(async () => #pragma warning restore CS4014 { - Logger.Info("Started Background Monitor!"); while (true) { try { - var uptime = (DateTime.Now - StartupTime).ToSmallText(); + var uptime = (DateTime.Now - StartupTime); // get total memory from process var totalMemory = (double)((double)Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024 / 1024); @@ -126,16 +144,17 @@ namespace DiIiS_NA using var proc = Process.GetCurrentProcess(); var cpuTime = proc.TotalProcessorTime; var text = - $"{name} | {PlayerManager.OnlinePlayers.Count()} onlines in {PlayerManager.OnlinePlayers.Count(s => s.InGameClient?.Player?.World != null)} worlds | Memory: {totalMemory:0.000} GB | CPU Time: {cpuTime.ToSmallText()} | Uptime: {uptime}"; - try - { - Console.Title = text; + $"{name} | " + + $"{PlayerManager.OnlinePlayers.Count()} onlines in {PlayerManager.OnlinePlayers.Count(s => s.InGameClient?.Player?.World != null)} worlds | " + + $"Memory: {totalMemory:0.000} GB | " + + $"CPU Time: {cpuTime.ToSmallText()} | " + + $"Uptime: {uptime.ToSmallText()}"; + if (SetTitle(text)) await Task.Delay(1000); - } - catch (Exception e) + else { Logger.Info(text); - await Task.Delay(60000); + await Task.Delay(TimeSpan.FromMinutes(1)); } } catch (Exception e) @@ -146,32 +165,46 @@ namespace DiIiS_NA AchievementManager.Initialize(); Core.Storage.AccountDataBase.SessionProvider.RebuildSchema(); + + string GeneratePassword(int size) => new string(Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", size) + .Select(s => s[new Random().Next(s.Length)]).ToArray()); + void LogAccountCreated(string username, string password) + => Logger.Success($"Created account: $[springgreen4]${username}$[/]$ with password: $[springgreen4]${password}$[/]$"); #if DEBUG - if (!Enumerable.Any(DBSessions.SessionQuery())) + if (!DBSessions.SessionQuery().Any()) { - Logger.Info("Initing new database, creating (test@,123456), (test1@,123456), (test2@,123456),(test3@,123456),(test4@,123456)"); - var account = AccountManager.CreateAccount("test@", "123456", "test", Account.UserLevels.Owner); + var password1 = GeneratePassword(6); + var password2 = GeneratePassword(6); + var password3 = GeneratePassword(6); + var password4 = GeneratePassword(6); + Logger.Info($"Initializing account database..."); + var account = AccountManager.CreateAccount("owner@", password1, "owner", Account.UserLevels.Owner); var gameAccount = GameAccountManager.CreateGameAccount(account); - var account1 = AccountManager.CreateAccount("test1@", "123456", "test1", Account.UserLevels.Owner); + LogAccountCreated("owner@", password1); + var account1 = AccountManager.CreateAccount("gm@", password2, "gm", Account.UserLevels.GM); var gameAccount1 = GameAccountManager.CreateGameAccount(account1); - var account2 = AccountManager.CreateAccount("test2@", "123456", "test2", Account.UserLevels.Owner); + LogAccountCreated("gm@", password2); + var account2 = AccountManager.CreateAccount("tester@", password3, "tester", Account.UserLevels.Tester); var gameAccount2 = GameAccountManager.CreateGameAccount(account2); - var account3 = AccountManager.CreateAccount("test3@", "123456", "test3", Account.UserLevels.Owner); + LogAccountCreated("tester@", password3); + var account3 = AccountManager.CreateAccount("user@", password4, "test3", Account.UserLevels.User); var gameAccount3 = GameAccountManager.CreateGameAccount(account3); - var account4 = AccountManager.CreateAccount("test4@", "123456", "test4", Account.UserLevels.Owner); - var gameAccount4 = GameAccountManager.CreateGameAccount(account4); + LogAccountCreated("user@", password4); } #else if (!Enumerable.Any(DBSessions.SessionQuery())) { - var account = AccountManager.CreateAccount("iwannatry@", "iJustWannaTry", "iwannatry", Account.UserLevels.User); + var password = GeneratePassword(6); + var account = AccountManager.CreateAccount("iwannatry@", password, "iwannatry", Account.UserLevels.User); var gameAccount = GameAccountManager.CreateGameAccount(account); + LogAccountCreated("iwannatry@", password); } - if (DBSessions.SessionQuery().Any()) - { - Logger.Info("Connect with base established."); - } #endif + + if (DBSessions.SessionQuery().Any()) + { + Logger.Success("Connection with database established."); + } //*/ StartWatchdog(); @@ -180,28 +213,33 @@ namespace DiIiS_NA ToonManager.PreLoadToons(); GuildManager.PreLoadGuilds(); - Logger.Info("Loading Diablo 3 - Core..."); + Logger.Info("Loading Diablo III - Core..."); if (D3CoreEnabled) { if (!MPQStorage.Initialized) { - Logger.Fatal("MPQ archives not founded..."); - Console.ReadLine(); + Logger.Fatal("MPQ archives not found..."); + Shutdown(); return; } - Logger.Info("Loaded - {0} items.", ItemGenerator.TotalItems); Logger.Info("Diablo 3 Core - Loaded"); + Logger.Info("Loaded - {0} items.", ItemGenerator.TotalItems); + Logger.Info("Diablo III Core - Loaded"); + } + else + { + Logger.Fatal("Diablo III Core - Disabled"); + Shutdown(); + return; } - else Logger.Info("Diablo 3 Core - Disabled"); var restSocketServer = new SocketManager(); if (!restSocketServer.StartNetwork(RESTSERVERIP, REST.Config.Instance.PORT)) { - Logger.Error("REST Socket server can't start."); - } - else - { - Logger.Info("REST server started - " + REST.Config.Instance.IP + ":{0}", REST.Config.Instance.PORT); + Logger.Fatal("REST socket server can't start."); + Shutdown(); + return; } + Logger.Success($"REST server started - {REST.Config.Instance.IP}:{REST.Config.Instance.PORT}"); //BGS @@ -209,11 +247,13 @@ namespace DiIiS_NA IEventLoopGroup boss = new MultithreadEventLoopGroup(1); IEventLoopGroup worker = new MultithreadEventLoopGroup(); b.LocalAddress(DiIiS_NA.LoginServer.Config.Instance.BindIP, DiIiS_NA.LoginServer.Config.Instance.Port); - Logger.Info("Server BlizzLess.Net started - " + DiIiS_NA.LoginServer.Config.Instance.BindIP + ":{0}", DiIiS_NA.LoginServer.Config.Instance.Port); + Logger.Info( + $"Blizzless server started - {DiIiS_NA.LoginServer.Config.Instance.BindIP}:{DiIiS_NA.LoginServer.Config.Instance.Port}"); BattleBackend = new BattleBackend(DiIiS_NA.LoginServer.Config.Instance.BindIP, DiIiS_NA.LoginServer.Config.Instance.WebPort); //Diablo 3 Game-Server - if (D3CoreEnabled) StartGS(); + if (D3CoreEnabled) + StartGS(); try { @@ -224,11 +264,22 @@ namespace DiIiS_NA IChannel boundChannel = await b.BindAsync(DiIiS_NA.LoginServer.Config.Instance.Port); + Logger.Info("$[bold red3_1]$Tip:$[/]$ graceful shutdown with $[red3_1]$CTRL+C$[/]$ or $[red3_1]$!q[uit]$[/]$ or $[red3_1]$!exit$[/]$."); while (true) { var line = Console.ReadLine(); + if (line is null or "!q" or "!quit" or "!exit") + break; CommandManager.Parse(line); } + + if (PlayerManager.OnlinePlayers.Count > 0) + { + PlayerManager.SendWhisper("Server is shutting down in 1 minute."); + await Task.Delay(TimeSpan.FromMinutes(1)); + } + + Shutdown(delay: 25); } catch (Exception e) { @@ -237,11 +288,28 @@ namespace DiIiS_NA finally { await Task.WhenAll( - boss.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), - worker.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); + boss.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), + worker.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } } + public static void Shutdown(int delay = 50) + { + if (!IsTargetEnabled("ansi")) + { + AnsiConsole.Progress().Start(ctx => + { + var task = ctx.AddTask("[red]Shutting down...[/]"); + for (int i = 0; i < 100; i++) + { + task.Increment(1); + Thread.Sleep(delay); + } + }); + } + Environment.Exit(-1); + } + [HandleProcessCorruptedStateExceptions] [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)] static void Main() @@ -259,18 +327,32 @@ namespace DiIiS_NA { Logger.Error(ex.StackTrace); Logger.FatalException(ex, "A root error of the server was detected, disconnection."); + Shutdown(); } else Logger.ErrorException(ex, "A root error of the server was detected but was handled."); - - Console.ReadLine(); } - + static bool IsTargetEnabled(string target) => LogConfig.Instance.Targets.Any(t => t.Target.ToLower() == target && t.Enabled); private static void InitLoggers() { LogManager.Enabled = true; + + if (IsTargetEnabled("ansi") && IsTargetEnabled("console")) + { + AnsiConsole.MarkupLine("[underline red on white]Fatal:[/] [red]You can't use both ansi and console targets at the same time.[/]"); + AnsiConsole.Progress().Start(ctx => + { + var sd = ctx.AddTask("[red3_1]Shutting down[/]"); + for (int i = 0; i < 100; i++) + { + sd.Increment(1); + Thread.Sleep(25); + } + }); + Environment.Exit(-1); + } foreach (var targetConfig in LogConfig.Instance.Targets) { if (!targetConfig.Enabled) @@ -279,6 +361,9 @@ namespace DiIiS_NA LogTarget target = null; switch (targetConfig.Target.ToLower()) { + case "ansi": + target = new AnsiTarget(targetConfig.MinimumLevel, targetConfig.MaximumLevel, targetConfig.IncludeTimeStamps); + break; case "console": target = new ConsoleTarget(targetConfig.MinimumLevel, targetConfig.MaximumLevel, targetConfig.IncludeTimeStamps); diff --git a/src/DiIiSNet/BZNET.csproj b/src/DiIiSNet/BZNET.csproj index 431c226..e329dd0 100644 --- a/src/DiIiSNet/BZNET.csproj +++ b/src/DiIiSNet/BZNET.csproj @@ -11,4 +11,8 @@ + + + +