160 lines
6.2 KiB
C#
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);
|
|
}
|
|
}
|
|
} |