Server 2.10.1: remote management from the MSCO Launcher
- Polls the keymaster every 5 s for commands from the owner's launcher, runs only allowed commands (say, kick, ban, save, backup, restart, mods reload, status, players), sends results and the player list back - RemoteManagement in server.json / web panel settings (on by default) to turn it off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -317,10 +317,45 @@ public sealed class GameServer
|
||||
/// <summary>Spielerzahl hat sich geändert: gleich beim Master melden statt erst in 30 s.</summary>
|
||||
void HeartbeatSoon() => nextHeartbeat = Math.Min(nextHeartbeat, clock.Elapsed.TotalSeconds + 1);
|
||||
|
||||
// ---------------------------------------------------------------- Verwalten aus dem Launcher (über den Keymaster)
|
||||
const double RemotePollSeconds = 5;
|
||||
double nextRemotePoll;
|
||||
Task<List<MasterClient.RemoteCommand>> remotePoll;
|
||||
readonly List<MasterClient.RemoteResult> remoteResults = new();
|
||||
/// <summary>Befehle, die der Besitzer aus dem Launcher schicken darf (gleiche Liste wie im Keymaster).</summary>
|
||||
static readonly System.Text.RegularExpressions.Regex RemoteAllowed =
|
||||
new(@"^(say .{1,150}|kick \d{1,6}( .{0,100})?|ban \d{1,6}( .{0,100})?|save|backup|restart|mods reload|status|players)$");
|
||||
|
||||
void RemoteManagementTick(double now)
|
||||
{
|
||||
if (offline || !config.RemoteManagement) return;
|
||||
if (remotePoll != null)
|
||||
{
|
||||
if (!remotePoll.IsCompleted) return;
|
||||
var commands = remotePoll.IsCompletedSuccessfully ? remotePoll.Result : null;
|
||||
remotePoll = null;
|
||||
if (commands == null) return; // Master nicht erreichbar: Ergebnisse beim nächsten Mal nochmal schicken
|
||||
remoteResults.Clear();
|
||||
foreach (var cmd in commands.Take(10))
|
||||
{
|
||||
string line = (cmd.Command ?? "").Trim();
|
||||
string by = "Launcher (" + (cmd.By ?? "owner") + ")";
|
||||
string output = RemoteAllowed.IsMatch(line) ? RunCommandCaptured(line, by) : "Not allowed on this server";
|
||||
remoteResults.Add(new MasterClient.RemoteResult(cmd.Id, output.Length > 2000 ? output[..2000] : output));
|
||||
}
|
||||
if (remoteResults.Count > 0) nextRemotePoll = 0; // Ergebnisse gleich abliefern
|
||||
}
|
||||
if (now < nextRemotePoll) return;
|
||||
nextRemotePoll = now + RemotePollSeconds;
|
||||
var players = clients.Values.Where(c => c.State == ClientState.Joined).Select(c => new MasterClient.RemotePlayer(c.Id, c.Name)).ToList();
|
||||
remotePoll = master.PollAsync(config.LicenseKey, remoteResults.ToList(), players);
|
||||
}
|
||||
|
||||
void Timers()
|
||||
{
|
||||
PullNewGameSave();
|
||||
double now = clock.Elapsed.TotalSeconds;
|
||||
RemoteManagementTick(now);
|
||||
if (now >= nextAutosave)
|
||||
{
|
||||
nextAutosave = now + config.AutosaveSeconds;
|
||||
|
||||
Reference in New Issue
Block a user