emo-client/Saradomin/Utilities/Singleplayer/SingleplayerManagement.cs

160 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Saradomin.Utilities
{
public static class SingleplayerManagement
{
private static readonly string[] DirsToBackup =
{
"game/data/players",
"game/data/serverstore",
"game/worldprops"
};
private static readonly string[] FilesToBackup =
{
"game/data/eco/grandexchange.db"
};
public static void MakeBackup(Action<string> log)
{
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string newBackupDir = Path.Combine(
CrossPlatform.GetSingleplayerBackupsHome(),
timestamp
);
foreach (string dir in DirsToBackup)
{
string sourcePath = Path.Combine(CrossPlatform.GetSingleplayerHome(), dir);
if (!Directory.Exists(sourcePath))
{
log($" Skipping backup of {dir} because it doesn't exist (Full path attempted: {sourcePath})");
continue;
}
string destPath = Path.Combine(newBackupDir, dir);
CopyDirectory(sourcePath, destPath);
}
foreach (string file in FilesToBackup)
{
string sourceFilePath = Path.Combine(CrossPlatform.GetSingleplayerHome(), file);
if (!File.Exists(sourceFilePath))
{
log($" Skipping backup of {file} because it doesn't exist (Full path attempted: {sourceFilePath})");
continue;
}
string destFilePath = Path.Combine(newBackupDir, file);
string directoryForFile = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(directoryForFile))
Directory.CreateDirectory(directoryForFile);
File.Copy(sourceFilePath, destFilePath, true);
}
}
private static void CopyDirectory(string sourceDir, string destinationDir)
{
if (!Directory.Exists(destinationDir))
Directory.CreateDirectory(destinationDir);
foreach (string filePath in Directory.GetFiles(sourceDir))
{
string fileName = Path.GetFileName(filePath);
string destFilePath = Path.Combine(destinationDir, fileName);
File.Copy(filePath, destFilePath, true);
}
foreach (string subDirPath in Directory.GetDirectories(sourceDir))
{
string subDirName = Path.GetFileName(subDirPath);
string destSubDirPath = Path.Combine(destinationDir, subDirName);
// Recurse!
CopyDirectory(subDirPath, destSubDirPath);
}
}
public static string FindMostRecentBackupDirectory(IEnumerable<string> directories)
{
return directories.Select(Path.GetFileName).MaxBy(name => name);
}
public static void ApplyLatestBackup(Action<string> log)
{
var backupHome = CrossPlatform.GetSingleplayerBackupsHome();
var singleplayerHome = CrossPlatform.GetSingleplayerHome();
// Get all backup directories
string[] backupDirectories = Directory.Exists(backupHome) ? Directory.GetDirectories(backupHome) : Array.Empty<string>();
string mostRecentBackupDirName = FindMostRecentBackupDirectory(backupDirectories);
if (mostRecentBackupDirName == null)
{
log(" No backups found.");
return;
}
string mostRecentBackupFullPath = Path.Combine(backupHome, mostRecentBackupDirName);
// Get the list of files in the most recent backup
var filesInBackup = Directory.GetFiles(
mostRecentBackupFullPath,
"*",
SearchOption.AllDirectories
);
foreach (var file in filesInBackup)
{
// Calculate the file's destination path in the singleplayer home directory
var relativePath = file.Substring(mostRecentBackupFullPath.Length)
.TrimStart(Path.DirectorySeparatorChar);
var destFilePath = Path.Combine(singleplayerHome, relativePath);
// Ensure the destination directory exists
var destDirectory = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(destDirectory))
{
Directory.CreateDirectory(destDirectory);
}
// Copy the file to the destination, overwriting any existing file
File.Copy(file, destFilePath, true);
}
log($" Backup from {mostRecentBackupDirName} has been successfully applied.");
}
private static Dictionary<string, string> _confCache;
private static string ConfPath => Path.Combine(CrossPlatform.GetSingleplayerHome(), "game", "worldprops", "default.conf");
public static Dictionary<string, string> GrabConfCache()
{
return File.ReadLines(ConfPath)
.Where(line => line.Contains('=') && !line.TrimStart().StartsWith("#"))
.Select(l => l.Split(new[] { '#', '=' }, 3))
.ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim());
}
public static T ParseConf<T>(string key, T defaultValue = default)
{
if (!File.Exists(ConfPath)) return defaultValue;
_confCache ??= GrabConfCache();
if (!_confCache.TryGetValue(key, out var value)) return defaultValue;
return (T)Convert.ChangeType(value, typeof(T));
}
public static void WriteConf(string key, object value)
{
_confCache[key] = value.ToString().ToLowerInvariant(); // Update cache
var lines = File.ReadAllLines(ConfPath).Select(l =>
l.StartsWith(key + " =")
? $"{key} = {_confCache[key]}" + (l.Contains("#") ? " " + l.Substring(l.IndexOf('#')) : "")
: l);
File.WriteAllLines(ConfPath, lines);
}
}
}