Files
BSO-Server/Program.cs
T
MrMahoandClaude Opus 5.5 cda31cd070 Erste Version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:26:24 +01:00

117 lines
4.6 KiB
C#

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 <id>, stop");
var commands = new ConcurrentQueue<string>();
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;
/// <summary>Verbindet sich wie die Mod (Info, dann Hello als "Probe") und zeigt 5 s lang alles, was ankommt.</summary>
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;
}