Stuck bodies are placed on top instead of being reset into the same spot (no fling loop); reset message shown in-game before reconnecting; server: backups / restore-save
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+38
-1
@@ -603,6 +603,13 @@ public sealed class GameServer
|
||||
SendSaveToWaiting();
|
||||
}
|
||||
|
||||
/// <summary>Vorhandene Spielstand-Backups, neueste zuerst.</summary>
|
||||
List<string> SaveBackups()
|
||||
{
|
||||
string backups = Path.Combine(Path.GetDirectoryName(savePath)!, "save_backups");
|
||||
return Directory.Exists(backups) ? Directory.GetDirectories(backups).OrderByDescending(d => d).ToList() : new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>Bisherigen Spielstand nach data/save_backups/Zeitstempel kopieren, die letzten Stände behalten.</summary>
|
||||
void BackupSave()
|
||||
{
|
||||
@@ -669,7 +676,7 @@ public sealed class GameServer
|
||||
switch (args[0].ToLowerInvariant())
|
||||
{
|
||||
case "help":
|
||||
Log("status | players | kick <id> [reason] | ban <id> [reason] | bans | unban <SteamID|name:x> | say <text> | op <id> | deop <id> | admins | save | reset-world | reload-save | stop");
|
||||
Log("status | players | kick <id> [reason] | ban <id> [reason] | bans | unban <SteamID|name:x> | backups | restore-save <n> | say <text> | op <id> | deop <id> | admins | save | reset-world | reload-save | stop");
|
||||
break;
|
||||
case "say":
|
||||
if (args.Length < 2) { Log("say <text>"); break; }
|
||||
@@ -752,6 +759,36 @@ public sealed class GameServer
|
||||
Log("World state reset - new players get the plain save game again.");
|
||||
ReconnectAll("The world is being reset - reconnecting...");
|
||||
break;
|
||||
case "backups":
|
||||
{
|
||||
var list = SaveBackups();
|
||||
if (list.Count == 0) { Log("No save backups yet (they are created when the server takes over a save game)"); break; }
|
||||
Log("Save backups (newest first) - restore with: restore-save <number>");
|
||||
for (int i = 0; i < list.Count; i++) Log($" [{i + 1}] {Path.GetFileName(list[i])}");
|
||||
break;
|
||||
}
|
||||
case "restore-save":
|
||||
{
|
||||
var list = SaveBackups();
|
||||
string arg = args.Length > 1 ? args[1].Trim() : "";
|
||||
string chosen = int.TryParse(arg, out int n) && n >= 1 && n <= list.Count ? list[n - 1]
|
||||
: list.FirstOrDefault(d => Path.GetFileName(d) == arg);
|
||||
if (chosen == null) { Log("restore-save <number> (see 'backups')"); break; }
|
||||
try
|
||||
{
|
||||
BackupSave(); // aktuellen Stand ebenfalls sichern, falls man zurück will
|
||||
foreach (string file in Directory.GetFiles(chosen)) File.Copy(file, Path.Combine(savePath, Path.GetFileName(file)), true);
|
||||
if (LoadSave())
|
||||
{
|
||||
world.ResetForNewSave();
|
||||
SaveWorld();
|
||||
Log($"Restored save game {Path.GetFileName(chosen)}");
|
||||
ReconnectAll("The server restored an older save game - reconnecting...");
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Log("Could not restore: " + e.Message); }
|
||||
break;
|
||||
}
|
||||
case "reload-save":
|
||||
if (LoadSave()) ReconnectAll("The server loaded a new save game - reconnecting...");
|
||||
break;
|
||||
|
||||
@@ -132,6 +132,7 @@ Fehlende Einstellungen ergänzt der Server beim Start automatisch. Umgebungsvari
|
||||
| `save` | Weltzustand jetzt speichern |
|
||||
| `reset-world` | alle Änderungen seit dem Spielstand verwerfen – verbundene Spieler bekommen eine Meldung und verbinden sich automatisch neu |
|
||||
| `reload-save` | Spielstand-Dateien neu einlesen – verbundene Spieler verbinden sich automatisch neu |
|
||||
| `backups`, `restore-save <nr>` | gesicherte Spielstände anzeigen / einen davon zurückholen (z.B. wenn der aktuelle kaputt ist) – alle verbinden sich neu |
|
||||
| `stop` | speichern und beenden |
|
||||
|
||||
Im Spiel öffnen Admins mit `/admin` (Chat, Taste T) oder `admin` (F7-Konsole) das Admin-Menü: Kick/Ban,
|
||||
|
||||
Reference in New Issue
Block a user