Penumbra/Penumbra/Util/SaveService.cs
2023-03-17 17:51:05 +01:00

99 lines
2.9 KiB
C#

using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using OtterGui.Classes;
using OtterGui.Log;
using Penumbra.Api;
using Penumbra.Services;
namespace Penumbra.Util;
/// <summary>
/// Any file type that we want to save via SaveService.
/// </summary>
public interface ISaveable
{
/// <summary> The full file name of a given object. </summary>
public string ToFilename(FilenameService fileNames);
/// <summary> Write the objects data to the given stream writer. </summary>
public void Save(StreamWriter writer);
/// <summary> An arbitrary message printed to Debug before saving. </summary>
public string LogName(string fileName)
=> fileName;
public string TypeName
=> GetType().Name;
}
public class SaveService
{
private readonly Logger _log;
private readonly FilenameService _fileNames;
private readonly FrameworkManager _framework;
public SaveService(Logger log, FilenameService fileNames, FrameworkManager framework)
{
_log = log;
_fileNames = fileNames;
_framework = framework;
}
/// <summary> Queue a save for the next framework tick. </summary>
public void QueueSave(ISaveable value)
{
var file = value.ToFilename(_fileNames);
_framework.RegisterDelayed(value.GetType().Name + file, () =>
{
ImmediateSave(value);
});
}
/// <summary> Immediately trigger a save. </summary>
public void ImmediateSave(ISaveable value)
{
var name = value.ToFilename(_fileNames);
try
{
if (name.Length == 0)
{
throw new Exception("Invalid object returned empty filename.");
}
_log.Debug($"Saving {value.TypeName} {value.LogName(name)}...");
var file = new FileInfo(name);
file.Directory?.Create();
using var s = file.Exists ? file.Open(FileMode.Truncate) : file.Open(FileMode.CreateNew);
using var w = new StreamWriter(s, Encoding.UTF8);
value.Save(w);
}
catch (Exception ex)
{
_log.Error($"Could not save {value.GetType().Name} {value.LogName(name)}:\n{ex}");
}
}
public void ImmediateDelete(ISaveable value)
{
var name = value.ToFilename(_fileNames);
try
{
if (name.Length == 0)
{
throw new Exception("Invalid object returned empty filename.");
}
if (!File.Exists(name))
return;
_log.Information($"Deleting {value.GetType().Name} {value.LogName(name)}...");
File.Delete(name);
}
catch (Exception ex)
{
_log.Error($"Could not delete {value.GetType().Name} {value.LogName(name)}:\n{ex}");
}
}
}