Files
MSCO/SaveSync.cs
T
MrMahoandClaude Opus 5.5 461d94c5fc MSCO 2.9.0: standalone without MSCLoader (Unity Doorstop)
- Bootstrap: Doorstop entry point, loads Harmony/Newtonsoft from the MSCO folder, hooks
  PlayMakerArrayListProxy.Awake and starts MSCO in the main menu; skips the news screen
- No MSCLoader reference anymore; key bindings in PlayerPrefs, bind console command
- Harmony 1.2 and Newtonsoft.Json in lib/ (MIT notices); build copies to <game>\MSCO
- README/CHANGELOG updated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:36:28 +02:00

137 lines
5.5 KiB
C#

using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace MSCO
{
/// <summary>
/// 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.
/// </summary>
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;
/// <summary>Gibt es einen eigenen Spielstand zum Weiterspielen?</summary>
public static bool HasLocalSave { get { return File.Exists(Path.Combine(SaveDir, "defaultES2File.txt")); } }
/// <summary>Wann der eigene Spielstand zuletzt gespeichert wurde (null = keiner).</summary>
public static System.DateTime? LocalSaveTime
{
get
{
string file = Path.Combine(SaveDir, "defaultES2File.txt");
return File.Exists(file) ? File.GetLastWriteTime(file) : (System.DateTime?)null;
}
}
/// <summary>Ordner mit den Spielständen, die vor einem neuen Spiel gesichert wurden.</summary>
public static string ArchiveFolder { get { return ArchiveDir; } }
/// <summary>
/// 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).
/// </summary>
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<KeyValuePair<string, byte[]>> ReadLocalSave()
{
var result = new List<KeyValuePair<string, byte[]>>();
foreach (string name in Files)
{
string path = Path.Combine(SaveDir, name);
if (File.Exists(path))
result.Add(new KeyValuePair<string, byte[]>(name, File.ReadAllBytes(path)));
}
return result;
}
/// <summary>Eigenen Spielstand sichern (nur einmal) und die Spielstand-Dateien leeren.</summary>
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);
}
}
}
}