namespace Aeshnidae.DatBackup;
///
/// Per-mod configuration, read from Settings.json in the deployed mod folder
/// (next to the dll, not in source). Written with defaults on first run, and
/// openable in-game with "/mod settings Aeshnidae.DatBackup".
///
public class Settings
{
public const string FileName = "Settings.json";
/// Take a snapshot when the server starts.
public bool SnapshotOnStartup { get; set; } = true;
///
/// Where snapshots live. Empty means "DatBackup" beside this mod, which keeps a
/// fresh install self-contained; point it at another drive if you would rather
/// the backups not share a disk with the thing they are backing up.
///
public string BackupDirectory { get; set; } = "";
///
/// Folder of dats to snapshot. Empty means the server's own DatFilesDirectory
/// from Config.js, which is the answer you want unless you are testing.
///
public string DatDirectory { get; set; } = "";
///
/// How many snapshots to keep. Because identical files are stored once, twenty
/// snapshots of an unchanged dat set cost one copy plus twenty small manifests -
/// so this can be generous without costing disk.
///
public int KeepSnapshots { get; set; } = 20;
///
/// Hash and re-check every blob of the newest snapshot at startup. Off by
/// default: it reads the whole store, which is a second or two per gigabyte and
/// not something to do on every restart. "/datbackup verify" runs it on demand.
///
public bool VerifyOnStartup { get; set; } = false;
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};
/// The store path, with the "beside the mod" default resolved.
public string ResolvedBackupDirectory =>
string.IsNullOrWhiteSpace(BackupDirectory)
? Path.Combine(Mod.ModPath, "DatBackup")
: BackupDirectory;
/// The dat folder, with the "ask ACE" default resolved.
public string ResolvedDatDirectory =>
string.IsNullOrWhiteSpace(DatDirectory)
? ConfigManager.Config?.Server?.DatFilesDirectory ?? ""
: DatDirectory;
public static Settings Load(string modPath)
{
var path = Path.Combine(modPath, FileName);
try
{
if (File.Exists(path))
return JsonSerializer.Deserialize(File.ReadAllText(path), JsonOptions) ?? new Settings();
var defaults = new Settings();
defaults.Save(modPath);
ModManager.Log($"[{Mod.Name}] wrote default settings to {path}");
return defaults;
}
catch (Exception ex)
{
ModManager.Log($"[{Mod.Name}] could not read {path}, using defaults: {ex.Message}", ModManager.LogLevel.Warn);
return new Settings();
}
}
public void Save(string modPath)
{
try
{
File.WriteAllText(Path.Combine(modPath, FileName), JsonSerializer.Serialize(this, JsonOptions));
}
catch (Exception ex)
{
ModManager.Log($"[{Mod.Name}] could not save settings: {ex.Message}", ModManager.LogLevel.Error);
}
}
}