## Summary Phase 3.1 of the message-interpolation optimization series. Fixes 9 of the 28 sites flagged in the Phase 2 audit (PR #2435): | File | Fix | |---|---| | `Commands/StaffAccess.cs:88,99` | Drop redundant `.ToString()` on enum holes | | `Commands/Handlers.cs:102` | `builder.ToString()` -> `builder.AsSpan()` | | `World Saves/SaveCommands.cs:71-75` | Merge 3 concatenated `$"..."` into one literal | | `Server/Items/Item.cs:4213` | Hoist nested ternary `$"..."` to if/else | | `Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs:140-150` | Convert switch expression to switch statement | | `Mobiles/Monsters/LBR/Jukas/JukaLord.cs:85` | Restructure `string.Format(toSay.RandomElement(), ...)` into switch | | `Misc/AttackMessage.cs:30-41` | Inline `AggressorFormat`/`AggressedFormat` constants | No functional changes. Each site emits identical text; the only difference is that the message string is now built into a pooled char buffer instead of being allocated as a `string` first.
102 lines
4 KiB
C#
102 lines
4 KiB
C#
using Server.Saves;
|
|
|
|
namespace Server.Commands;
|
|
|
|
public static class SaveCommands
|
|
{
|
|
public static void Configure()
|
|
{
|
|
CommandSystem.Register("Save", AccessLevel.Administrator, Save_OnCommand);
|
|
CommandSystem.Register("SetSaves", AccessLevel.Administrator, SetAutoSaves_OnCommand);
|
|
CommandSystem.Register("AutoSave", AccessLevel.Administrator, SetAutoSaves_OnCommand);
|
|
CommandSystem.Register("SaveFrequency", AccessLevel.Administrator, SetSaveFrequency_OnCommand);
|
|
CommandSystem.Register("PruneArchives", AccessLevel.Administrator, PruneArchives_OnCommand);
|
|
CommandSystem.Register("ArchiveStatus", AccessLevel.Administrator, ArchiveStatus_OnCommand);
|
|
CommandSystem.Register("ArchiveNow", AccessLevel.Administrator, ArchiveNow_OnCommand);
|
|
}
|
|
|
|
[Usage("PruneArchives"), Description("Prunes archives folder.")]
|
|
private static void PruneArchives_OnCommand(CommandEventArgs e) => AutoArchive.PruneBackups();
|
|
|
|
[Usage("Save"), Description("Saves the world.")]
|
|
private static void Save_OnCommand(CommandEventArgs e) => AutoSave.Save();
|
|
|
|
[Usage("AutoSave <on | off>"), Description("Enables or disables automatic shard saving.")]
|
|
public static void SetAutoSaves_OnCommand(CommandEventArgs e)
|
|
{
|
|
if (e.Length == 1)
|
|
{
|
|
var enabled = AutoSave.SavesEnabled = e.GetBoolean(0);
|
|
|
|
e.Mobile.SendMessage(enabled ? "Saves have been enabled." : "Saves have been disabled.");
|
|
}
|
|
else
|
|
{
|
|
e.Mobile.SendMessage("Format: AutoSave <on | off>");
|
|
}
|
|
}
|
|
|
|
[Usage("SaveFrequency <duration> [warning duration]"), Description("Sets the save frequency starting at midnight local to the server.")]
|
|
public static void SetSaveFrequency_OnCommand(CommandEventArgs e)
|
|
{
|
|
if (e.Length < 1)
|
|
{
|
|
e.Mobile.SendMessage("Format: SaveFrequency <duration> [warning duration]");
|
|
return;
|
|
}
|
|
|
|
var saveDelay = e.GetTimeSpan(0);
|
|
var warningDelay = e.Length >= 2 ? e.GetTimeSpan(1) : AutoSave.Warning;
|
|
|
|
AutoSave.ResetAutoSave(saveDelay, warningDelay);
|
|
|
|
e.Mobile.SendMessage("Save frequency has been updated.");
|
|
}
|
|
|
|
[Usage("ArchiveStatus")]
|
|
[Description("Shows archive system status, journal state, and registered destinations.")]
|
|
private static void ArchiveStatus_OnCommand(CommandEventArgs e)
|
|
{
|
|
var mobile = e.Mobile;
|
|
|
|
mobile.SendMessage("--- Archive Status ---");
|
|
mobile.SendMessage($"Next hourly: {AutoArchive.NextHourlyArchive:yyyy-MM-dd HH:mm}");
|
|
mobile.SendMessage($"Next daily: {AutoArchive.NextDailyArchive:yyyy-MM-dd}");
|
|
mobile.SendMessage($"Next monthly: {AutoArchive.NextMonthlyArchive:yyyy-MM}");
|
|
|
|
var destinations = ArchiveDestinationRegistry.Destinations;
|
|
mobile.SendMessage($"Registered destinations: {destinations.Count}");
|
|
foreach (var dest in destinations)
|
|
{
|
|
mobile.SendMessage(
|
|
$" - {dest.Name} (retention: {dest.GetRetentionCount(ArchivePeriod.Hourly)}h/{dest.GetRetentionCount(ArchivePeriod.Daily)}d/{dest.GetRetentionCount(ArchivePeriod.Monthly)}m)"
|
|
);
|
|
}
|
|
|
|
var operations = ArchiveJournal.Operations;
|
|
var pending = 0;
|
|
var failed = 0;
|
|
for (var i = 0; i < operations.Count; i++)
|
|
{
|
|
var op = operations[i];
|
|
if (op.State is ArchiveOperationState.Started or ArchiveOperationState.Archived
|
|
or ArchiveOperationState.Distributed)
|
|
{
|
|
pending++;
|
|
}
|
|
else if (op.State == ArchiveOperationState.Failed)
|
|
{
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
mobile.SendMessage($"Journal entries: {operations.Count} ({pending} pending, {failed} failed)");
|
|
}
|
|
|
|
[Usage("ArchiveNow"), Description("Forces an immediate archive rollup regardless of schedule.")]
|
|
private static void ArchiveNow_OnCommand(CommandEventArgs e)
|
|
{
|
|
e.Mobile.SendMessage("Forcing immediate archive rollup...");
|
|
AutoArchive.ForceRollup();
|
|
}
|
|
}
|