using System; using System.IO; using System.Runtime.InteropServices; namespace Theriapolis.GodotHost.Platform; /// /// OS-aware save directory resolution. Direct port of /// Theriapolis.Game/Platform/SavePaths.cs; deliberately uses the /// same directories as the MonoGame build so saves are interoperable /// across the two ports. /// /// Locations: /// Windows: %LOCALAPPDATA%\Theriapolis\Saves\ /// macOS: ~/Library/Application Support/Theriapolis/Saves/ /// Linux: $XDG_DATA_HOME/Theriapolis/saves/ (default /// ~/.local/share/Theriapolis/saves/) /// public static class SavePaths { /// Top-level Theriapolis save directory. Created on first /// call if missing. public static string SavesDir { get { string dir = ResolveBase(); Directory.CreateDirectory(dir); return dir; } } public static string SlotPath(int slot) => Path.Combine(SavesDir, $"slot_{slot:D2}.trps"); public static string AutosavePath() => Path.Combine(SavesDir, "autosave.trps"); private static string ResolveBase() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Theriapolis", "Saves"); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Theriapolis", "Saves"); // Linux + others: respect XDG_DATA_HOME, fall back to ~/.local/share. string xdg = Environment.GetEnvironmentVariable("XDG_DATA_HOME") ?? ""; if (string.IsNullOrEmpty(xdg)) xdg = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); return Path.Combine(xdg, "Theriapolis", "saves"); } /// Atomic-rename file write so a crash mid-save can't /// corrupt the slot. public static void WriteAtomic(string path, byte[] bytes) { string dir = Path.GetDirectoryName(path)!; Directory.CreateDirectory(dir); string tmp = path + ".tmp"; File.WriteAllBytes(tmp, bytes); if (File.Exists(path)) File.Replace(tmp, path, destinationBackupFileName: null); else File.Move(tmp, path); } }