using System.Collections.Generic; using System.IO; using UnityEngine; namespace MSCO { /// /// Liest den Spielstand des Hosts und ersetzt beim Client den eigenen Spielstand /// vorübergehend. Der Spielstand des Clients wird vorher gesichert und beim /// nächsten Hauptmenü automatisch wiederhergestellt. /// public static class SaveSync { // Nur diese Dateien werden übertragen (options.txt etc. bleiben beim Spieler) public static readonly string[] Files = { "defaultES2File.txt", "items.txt", "meshsave.txt", "graveyard.txt", "notepad.txt" }; static string SaveDir { get { return Application.persistentDataPath; } } static string BackupDir { get { return Path.Combine(SaveDir, "MSCO_Backup"); } } static string Marker { get { return Path.Combine(BackupDir, "backup_active"); } } public static bool HasBackup { get { return File.Exists(Marker); } } static string ArchiveDir { get { return Path.Combine(SaveDir, "MSCO_Saves"); } } const int KeepArchives = 10; /// Gibt es einen eigenen Spielstand zum Weiterspielen? public static bool HasLocalSave { get { return File.Exists(Path.Combine(SaveDir, "defaultES2File.txt")); } } /// Wann der eigene Spielstand zuletzt gespeichert wurde (null = keiner). public static System.DateTime? LocalSaveTime { get { string file = Path.Combine(SaveDir, "defaultES2File.txt"); return File.Exists(file) ? File.GetLastWriteTime(file) : (System.DateTime?)null; } } /// Ordner mit den Spielständen, die vor einem neuen Spiel gesichert wurden. public static string ArchiveFolder { get { return ArchiveDir; } } /// /// Neues Spiel: den bisherigen Spielstand nach MSCO_Saves/Datum kopieren (nichts geht verloren) und die /// Spielstand-Dateien leeren, damit das Spiel eine frische Welt anlegt. Gibt den Sicherungsordner zurück (oder null). /// public static string ArchiveForNewGame() { // War noch der Spielstand eines anderen Hosts aktiv, erst den eigenen zurückholen if (HasBackup) RestoreBackup(); string target = null; if (HasLocalSave) { target = Path.Combine(ArchiveDir, System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")); Directory.CreateDirectory(target); foreach (string name in Files) { string path = Path.Combine(SaveDir, name); if (File.Exists(path)) File.Copy(path, Path.Combine(target, name), true); } MscoLog.Info("[MSCO] Your previous save game was backed up to " + target); // Nur die letzten Sicherungen behalten string[] all = Directory.GetDirectories(ArchiveDir); System.Array.Sort(all); for (int i = 0; i < all.Length - KeepArchives; i++) try { Directory.Delete(all[i], true); } catch { } } DeleteSaveFiles(); return target; } public static List> ReadLocalSave() { var result = new List>(); foreach (string name in Files) { string path = Path.Combine(SaveDir, name); if (File.Exists(path)) result.Add(new KeyValuePair(name, File.ReadAllBytes(path))); } return result; } /// Eigenen Spielstand sichern (nur einmal) und die Spielstand-Dateien leeren. public static void BeginReceive() { if (!HasBackup) { Directory.CreateDirectory(BackupDir); foreach (string name in Files) { string path = Path.Combine(SaveDir, name); if (File.Exists(path)) File.Copy(path, Path.Combine(BackupDir, name), true); } File.WriteAllText(Marker, "MSCO backup of the client's own save. Restored automatically."); MscoLog.Info("[MSCO] Own save backed up to " + BackupDir); } DeleteSaveFiles(); } public static void WriteFile(string name, byte[] data) { // Nur bekannte Dateinamen erlauben, damit der Host nichts anderes überschreiben kann if (System.Array.IndexOf(Files, name) < 0) { MscoLog.Warning("[MSCO] Ignored unexpected save file: " + name); return; } File.WriteAllBytes(Path.Combine(SaveDir, name), data); } public static void RestoreBackup() { if (!HasBackup) return; DeleteSaveFiles(); foreach (string name in Files) { string backup = Path.Combine(BackupDir, name); if (File.Exists(backup)) File.Copy(backup, Path.Combine(SaveDir, name), true); } Directory.Delete(BackupDir, true); MscoLog.Info("[MSCO] Own save restored."); } static void DeleteSaveFiles() { foreach (string name in Files) { string path = Path.Combine(SaveDir, name); if (File.Exists(path)) File.Delete(path); } } } }