Improved console logging with Ansi. A new logger target has been introduced: AnsiTarget.cs (which is a table).

Sample config:
```
[AnsiLog]
Enabled = true
Target = Ansi
IncludeTimeStamps = true
MinimumLevel = Trace
MaximumLevel = Fatal
```
This commit is contained in:
Lucca Faria Ferri 2023-01-27 08:30:47 -08:00
parent f9f9dace6d
commit 4027254dd0
11 changed files with 344 additions and 108 deletions

View File

@ -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());
}
}

View File

@ -42,27 +42,27 @@ namespace DiIiS_NA.LoginServer.Battle
public Dictionary<string, ServerDescriptor> PvPGameServers = new Dictionary<string, ServerDescriptor>();
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 { }
});

View File

@ -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<BindResponse> done)
@ -36,8 +36,6 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
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<EchoResponse> done)
@ -84,7 +82,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
public override void RequestDisconnect(IRpcController controller, DisconnectRequest request, Action<NO_RESPONSE> 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;

View File

@ -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:

View File

@ -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[/]");
}
/// <summary>
/// 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");
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
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)
};
}
}

View File

@ -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;
}
/// <param name="level">Log level.</param>
/// <param name="logger">Source of the log message.</param>
/// <param name="message">Log message.</param>
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)}[/]");
}
/// <param name="level">Log level.</param>
@ -33,43 +34,50 @@ namespace DiIiS_NA.Core.Logging
/// <param name="exception">Exception to be included with log message.</param>
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)}[/]");
}
/// <summary>
/// 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");
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
string Cleanup(string x) => AnsiTarget.Filter(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
/// <param name="level"></param>
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}]";
}
}
}

View File

@ -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"),

View File

@ -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();

View File

@ -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 =)
}
}

View File

@ -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<DBAccount>()))
if (!DBSessions.SessionQuery<DBAccount>().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<DBAccount>()))
{
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);
}
if (DBSessions.SessionQuery<DBAccount>().Any())
{
Logger.Info("Connect with base established.");
LogAccountCreated("iwannatry@", password);
}
#endif
if (DBSessions.SessionQuery<DBAccount>().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<RestSession>();
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)
{
@ -242,6 +293,23 @@ namespace DiIiS_NA
}
}
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);

View File

@ -11,4 +11,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.46.0" />
</ItemGroup>
</Project>