using System.Collections.Concurrent; using System.Diagnostics; using System.Net.Sockets; using BSO.Net; using BSO.Server; // BSO.Server [--port 7777] [--name "Mein Server"] [--max 8] [--bot] // BSO.Server --probe host[:port] (Test: verbindet sich wie die Mod und zeigt, was ankommt) int port = Protocol.DefaultPort, max = 8; string name = "BSO Server", probe = null; bool bot = false; for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "--port": port = int.Parse(args[++i]); break; case "--name": name = args[++i]; break; case "--max": max = int.Parse(args[++i]); break; case "--bot": bot = true; break; case "--probe": probe = args[++i]; break; default: Console.WriteLine("BSO.Server [--port 7777] [--name \"Name\"] [--max 8] [--bot] | --probe host[:port]"); return 1; } } if (probe != null) return Probe(probe); var server = new GameServer(port, name, max); if (bot) server.AddBot(); GameServer.Log("Befehle: help, status, bot, kick , stop"); var commands = new ConcurrentQueue(); new Thread(() => { string line; while ((line = Console.ReadLine()) != null) commands.Enqueue(line); }) { IsBackground = true, Name = "Konsole" }.Start(); bool running = true; Console.CancelKeyPress += (_, e) => { e.Cancel = true; running = false; }; while (running) { server.Tick(); while (commands.TryDequeue(out string cmd)) { if (cmd.Trim().Equals("stop", StringComparison.OrdinalIgnoreCase)) running = false; else server.Command(cmd); } Thread.Sleep(5); } server.Stop(); GameServer.Log("Server beendet"); return 0; /// Verbindet sich wie die Mod (Info, dann Hello als "Probe") und zeigt 5 s lang alles, was ankommt. static int Probe(string target) { string[] hp = target.Split(':'); int p = hp.Length > 1 ? int.Parse(hp[1]) : Protocol.DefaultPort; var tcp = new TcpClient(); if (!tcp.ConnectAsync(hp[0], p).Wait(5000)) { Console.WriteLine("Keine Verbindung zu " + target); return 2; } var conn = new Connection(tcp); conn.Send(MsgType.Info, null); conn.Send(MsgType.Hello, Wire.Build(w => { w.Write(Protocol.Version); w.Write("probe"); w.Write("Probe"); })); conn.Send(MsgType.Ping, Wire.Build(w => w.Write(Stopwatch.GetTimestamp()))); // Eigene Position, damit der Testbot losfaehrt var me = new PlayerState { Mode = PlayerMode.InBus, X = 70000, Y = 30000, Z = 760 }; var watch = Stopwatch.StartNew(); int states = 0; while (watch.Elapsed.TotalSeconds < 5 && !conn.IsClosed) { conn.Send(MsgType.PlayerState, Wire.Build(w => me.Write(w))); foreach (Message m in conn.Poll()) { BinaryReader r = m.Reader(); switch (m.Type) { case MsgType.InfoReply: Console.WriteLine($"Info: \"{r.ReadString()}\" Version {r.ReadString()}, {r.ReadInt32()}/{r.ReadInt32()} Spieler"); break; case MsgType.Welcome: int id = r.ReadInt32(); string server = r.ReadString(); int n = r.ReadInt32(); var list = Enumerable.Range(0, n).Select(_ => $"#{r.ReadInt32()} {r.ReadString()}").ToList(); Console.WriteLine($"Welcome: ich bin #{id} auf \"{server}\", andere: {(n == 0 ? "-" : string.Join(", ", list))}"); break; case MsgType.Reject: Console.WriteLine("Abgelehnt: " + r.ReadString()); break; case MsgType.Pong: Console.WriteLine($"Ping: {Stopwatch.GetElapsedTime(r.ReadInt64()).TotalMilliseconds:0.0} ms"); break; case MsgType.PlayerJoined: Console.WriteLine($"Beigetreten: #{r.ReadInt32()} {r.ReadString()}"); break; case MsgType.PlayerLeft: Console.WriteLine($"Gegangen: #{r.ReadInt32()}"); break; case MsgType.PlayerState: int who = r.ReadInt32(); PlayerState s = PlayerState.Read(r); if (states++ % 10 == 0) Console.WriteLine($"Zustand #{who}: {s.Mode} {s.X / 100:0.0} / {s.Y / 100:0.0} / {s.Z / 100:0.0} m, {s.Speed * 0.036f:0} km/h, {s.DistanceTo(me) / 100:0.0} m entfernt"); break; } } Thread.Sleep(100); } Console.WriteLine($"{states} Zustaende in 5 s" + (conn.IsClosed ? " - getrennt: " + conn.CloseReason : "")); conn.Close("Probe fertig"); return 0; }