diff --git a/BLHX.Server.Common/BLHX.Server.Common.csproj b/BLHX.Server.Common/BLHX.Server.Common.csproj
new file mode 100644
index 0000000..fa71b7a
--- /dev/null
+++ b/BLHX.Server.Common/BLHX.Server.Common.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/BLHX.Server.Common/Utils/Logger.cs b/BLHX.Server.Common/Utils/Logger.cs
new file mode 100644
index 0000000..b659e8c
--- /dev/null
+++ b/BLHX.Server.Common/Utils/Logger.cs
@@ -0,0 +1,99 @@
+using System.Diagnostics;
+
+namespace BLHX.Server.Common.Utils
+{
+ public class Logger
+ {
+ public static readonly Logger c = new("BLHX.Server", ConsoleColor.Blue);
+ private readonly string _name;
+ private readonly bool TraceOnError;
+ private readonly ConsoleColor _color;
+
+ public Logger(string name, ConsoleColor color = ConsoleColor.Cyan, bool traceOnError = true)
+ {
+ _name = name;
+ _color = color;
+ TraceOnError = traceOnError;
+ }
+
+ public void Log(params string[] message)
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write(DateTime.Now.ToString("HH:mm:ss "));
+ Console.ResetColor();
+ Console.Write("<");
+ Console.ForegroundColor = _color;
+ Console.Write(_name);
+ Console.ResetColor();
+ Console.Write("> ");
+ Console.WriteLine(string.Join("\t", message));
+ Console.ResetColor();
+ }
+
+ public void Warn(params string[] message)
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write(DateTime.Now.ToString("HH:mm:ss "));
+ Console.ResetColor();
+ Console.Write("<");
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.Write(_name);
+ Console.ResetColor();
+ Console.Write("> ");
+ Console.WriteLine(string.Join("\t", message));
+ Console.ResetColor();
+ }
+
+ public void Trail(params string[] msg)
+ {
+ Console.ForegroundColor = ConsoleColor.DarkGray;
+ Console.WriteLine($"\t└── {string.Join(' ', msg)}");
+ Console.ResetColor();
+ }
+
+ public void Error(params string[] message)
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write(DateTime.Now.ToString("HH:mm:ss "));
+ Console.ResetColor();
+ Console.Write("<");
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.Write(_name);
+ Console.ResetColor();
+ Console.Write("> ");
+ Console.ForegroundColor = ConsoleColor.White;
+ if (TraceOnError)
+ Console.BackgroundColor = ConsoleColor.DarkRed;
+ Console.WriteLine(string.Join("\t", message));
+ Console.ResetColor();
+#if DEBUG
+ StackTrace trace = new(true);
+ if (TraceOnError)
+ Trail(trace.ToString());
+#endif
+ }
+
+ public void Debug(params string[] message)
+ {
+#if DEBUG
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write(DateTime.Now.ToString("HH:mm:ss "));
+ Console.ResetColor();
+ Console.Write("<");
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.Write(_name);
+ Console.ResetColor();
+ Console.Write("> ");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.BackgroundColor = ConsoleColor.DarkMagenta;
+ Console.WriteLine(string.Join("\t", message));
+ Console.ResetColor();
+ Console.BackgroundColor = ConsoleColor.Black;
+
+ StackTrace trace = new(true);
+ if (TraceOnError)
+ Trail(trace.ToString());
+#endif
+ }
+ }
+}
diff --git a/BLHX.Server.Game/BLHX.Server.Game.csproj b/BLHX.Server.Game/BLHX.Server.Game.csproj
new file mode 100644
index 0000000..0342417
--- /dev/null
+++ b/BLHX.Server.Game/BLHX.Server.Game.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/BLHX.Server.Game/Connection.cs b/BLHX.Server.Game/Connection.cs
new file mode 100644
index 0000000..1402a78
--- /dev/null
+++ b/BLHX.Server.Game/Connection.cs
@@ -0,0 +1,49 @@
+using BLHX.Server.Common.Utils;
+using System.Net;
+using System.Net.Sockets;
+
+namespace BLHX.Server.Game
+{
+ public class Connection
+ {
+ readonly TcpClient tcpClient;
+ readonly Logger c;
+ readonly CancellationTokenSource cts = new();
+ readonly Task loopTask;
+ public IPEndPoint EndPoint => (IPEndPoint)tcpClient.Client.RemoteEndPoint!;
+
+ public Connection(TcpClient tcpClient)
+ {
+ this.tcpClient = tcpClient;
+ c = new(EndPoint.ToString());
+ loopTask = Task.Run(ClientLoop, cts.Token);
+ }
+
+ private async Task ClientLoop()
+ {
+ var ns = tcpClient.GetStream();
+ var buf = GC.AllocateUninitializedArray(8 << 13);
+ var pos = 0;
+
+ while (!cts.Token.IsCancellationRequested)
+ {
+ await Task.Delay(1);
+ int len = ns.Read(buf, pos, buf.Length - pos);
+ len += pos;
+ if (len == 0)
+ continue;
+
+ c.Debug(BitConverter.ToString(buf[..len]).Replace("-", ""));
+ }
+ }
+
+ public void EndProtocol()
+ {
+ cts.Cancel();
+ loopTask.Wait();
+ loopTask.Dispose();
+
+ tcpClient.Dispose();
+ }
+ }
+}
diff --git a/BLHX.Server.Game/GameServer.cs b/BLHX.Server.Game/GameServer.cs
new file mode 100644
index 0000000..1d4927c
--- /dev/null
+++ b/BLHX.Server.Game/GameServer.cs
@@ -0,0 +1,47 @@
+using System.Net;
+using System.Net.Sockets;
+using BLHX.Server.Common.Utils;
+
+namespace BLHX.Server.Game
+{
+ public static class GameServer
+ {
+ static readonly TcpListener listener;
+ public static readonly Dictionary connections = new();
+ public static readonly Logger c = new(nameof(GameServer), ConsoleColor.Magenta);
+ public static IPEndPoint EndPoint { get; }
+
+ static GameServer()
+ {
+ EndPoint = new(IPAddress.Any, 20000);
+ listener = new TcpListener(EndPoint);
+ }
+
+ public static async Task Start()
+ {
+ listener.Start();
+ c.Log($"{nameof(GameServer)} started on {EndPoint}");
+
+ while (true)
+ {
+ try
+ {
+ TcpClient client = await listener.AcceptTcpClientAsync();
+ if (client.Client.RemoteEndPoint is not null and IPEndPoint)
+ {
+ if (connections.ContainsKey((IPEndPoint)client.Client.RemoteEndPoint))
+ connections[(IPEndPoint)client.Client.RemoteEndPoint].EndProtocol();
+
+ connections[(IPEndPoint)client.Client.RemoteEndPoint] = new Connection(client);
+ continue;
+ }
+ client.Dispose();
+ }
+ catch (Exception ex)
+ {
+ c.Error($"{nameof(GameServer)} listener error {ex}");
+ }
+ }
+ }
+ }
+}
diff --git a/BLHX.Server.sln b/BLHX.Server.sln
new file mode 100644
index 0000000..bd867ba
--- /dev/null
+++ b/BLHX.Server.sln
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34309.116
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLHX.Server", "BLHX.Server\BLHX.Server.csproj", "{C67D2B44-EFF0-4325-9C90-9D8BA4799E02}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLHX.Server.Game", "BLHX.Server.Game\BLHX.Server.Game.csproj", "{33059688-36C1-43D1-BEE6-3A5C5C7DA4E6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLHX.Server.Common", "BLHX.Server.Common\BLHX.Server.Common.csproj", "{BA896C61-5025-4CBB-B56C-18A59D3D0D7D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C67D2B44-EFF0-4325-9C90-9D8BA4799E02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C67D2B44-EFF0-4325-9C90-9D8BA4799E02}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C67D2B44-EFF0-4325-9C90-9D8BA4799E02}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C67D2B44-EFF0-4325-9C90-9D8BA4799E02}.Release|Any CPU.Build.0 = Release|Any CPU
+ {33059688-36C1-43D1-BEE6-3A5C5C7DA4E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {33059688-36C1-43D1-BEE6-3A5C5C7DA4E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {33059688-36C1-43D1-BEE6-3A5C5C7DA4E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {33059688-36C1-43D1-BEE6-3A5C5C7DA4E6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BA896C61-5025-4CBB-B56C-18A59D3D0D7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BA896C61-5025-4CBB-B56C-18A59D3D0D7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BA896C61-5025-4CBB-B56C-18A59D3D0D7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BA896C61-5025-4CBB-B56C-18A59D3D0D7D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {23C7FC14-F3E9-4AA5-8FE0-0E08FF97E4BA}
+ EndGlobalSection
+EndGlobal
diff --git a/BLHX.Server/BLHX.Server.csproj b/BLHX.Server/BLHX.Server.csproj
new file mode 100644
index 0000000..623e668
--- /dev/null
+++ b/BLHX.Server/BLHX.Server.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ true
+
+
+
+
+
+
+
diff --git a/BLHX.Server/Program.cs b/BLHX.Server/Program.cs
new file mode 100644
index 0000000..eda4102
--- /dev/null
+++ b/BLHX.Server/Program.cs
@@ -0,0 +1,14 @@
+using BLHX.Server.Common.Utils;
+using BLHX.Server.Game;
+
+namespace BLHX.Server
+{
+ internal class Program
+ {
+ static void Main()
+ {
+ Logger.c.Log("Starting...");
+ Task.Run(GameServer.Start).Wait();
+ }
+ }
+}