using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using BayatGames.SaveGameFree.Encoders; using BayatGames.SaveGameFree.Serializers; using UnityEngine; using UnityEngine.Networking; namespace BayatGames.SaveGameFree { /// /// Save game path. base paths for your save games. /// public enum SaveGamePath { /// /// The persistent data path. Application.persistentDataPath /// PersistentDataPath, /// /// The data path. Application.dataPath /// DataPath } /// /// Save Game. /// Use these APIs to Save & Load game data. /// If you are looking for Web saving and loading use SaveGameWeb. /// public static class SaveGame { /// /// Save handler. /// public delegate void SaveHandler(object obj, string identifier, bool encode, string password, ISaveGameSerializer serializer, ISaveGameEncoder encoder, Encoding encoding, SaveGamePath path); /// /// Load handler. /// public delegate void LoadHandler(object loadedObj, string identifier, bool encode, string password, ISaveGameSerializer serializer, ISaveGameEncoder encoder, Encoding encoding, SaveGamePath path); /// /// Occurs when on saved. /// public static event SaveHandler OnSaved; /// /// Occurs when on loaded. /// public static event LoadHandler OnLoaded; /// /// The save callback. /// public static SaveHandler SaveCallback; /// /// The load callback. /// public static LoadHandler LoadCallback; private static ISaveGameSerializer m_Serializer = new SaveGameJsonSerializer(); private static ISaveGameEncoder m_Encoder = new SaveGameSimpleEncoder(); private static Encoding m_Encoding = Encoding.UTF8; private static bool m_Encode = false; private static SaveGamePath m_SavePath = SaveGamePath.PersistentDataPath; private static string m_EncodePassword = "h@e#ll$o%^"; private static bool m_LogError = false; /// /// Gets or sets the serializer. /// /// The serializer. public static ISaveGameSerializer Serializer { get { if (m_Serializer == null) { m_Serializer = new SaveGameJsonSerializer(); } return m_Serializer; } set { m_Serializer = value; } } /// /// Gets or sets the encoder. /// /// The encoder. public static ISaveGameEncoder Encoder { get { if (m_Encoder == null) { m_Encoder = new SaveGameSimpleEncoder(); } return m_Encoder; } set { m_Encoder = value; } } /// /// Gets or sets the encoding. /// /// The encoding. public static Encoding DefaultEncoding { get { if (m_Encoding == null) { m_Encoding = Encoding.UTF8; } return m_Encoding; } set { m_Encoding = value; } } /// /// Gets or sets a value indicating whether this encrypt data by default. /// /// true if encode; otherwise, false. public static bool Encode { get { return m_Encode; } set { m_Encode = value; } } /// /// Gets or sets the save path. /// /// The save path. public static SaveGamePath SavePath { get { return m_SavePath; } set { m_SavePath = value; } } /// /// Gets or sets the encryption password. /// /// The encryption password. public static string EncodePassword { get { return m_EncodePassword; } set { m_EncodePassword = value; } } /// /// Gets or sets a value indicating whether this log error. /// /// true if log error; otherwise, false. public static bool LogError { get { return m_LogError; } set { m_LogError = value; } } /// /// Saves data using the identifier. /// /// Identifier. /// Object to save. /// The 1st type parameter. public static void Save(string identifier, T obj) { Save(identifier, obj, Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Save the specified identifier, obj, encode and encodePassword. /// /// Identifier. /// Object. /// If set to true encode. /// The 1st type parameter. public static void Save(string identifier, T obj, bool encode) { Save(identifier, obj, encode, EncodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Save the specified identifier, obj and encodePassword. /// /// Identifier. /// Object. /// Encode password. /// The 1st type parameter. public static void Save(string identifier, T obj, string encodePassword) { Save(identifier, obj, Encode, encodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Save the specified identifier, obj and serializer. /// /// Identifier. /// Object. /// Serializer. /// The 1st type parameter. public static void Save(string identifier, T obj, ISaveGameSerializer serializer) { Save(identifier, obj, Encode, EncodePassword, serializer, Encoder, DefaultEncoding, SavePath); } /// /// Save the specified identifier, obj and encoder. /// /// Identifier. /// Object. /// Encoder. /// The 1st type parameter. public static void Save(string identifier, T obj, ISaveGameEncoder encoder) { Save(identifier, obj, Encode, EncodePassword, Serializer, encoder, DefaultEncoding, SavePath); } /// /// Save the specified identifier, obj and encoding. /// /// Identifier. /// Object. /// Encoding. /// The 1st type parameter. public static void Save(string identifier, T obj, Encoding encoding) { Save(identifier, obj, Encode, EncodePassword, Serializer, Encoder, encoding, SavePath); } /// /// Save the specified identifier, obj and savePath. /// /// Identifier. /// Object. /// Save path. /// The 1st type parameter. public static void Save(string identifier, T obj, SaveGamePath savePath) { Save(identifier, obj, Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, savePath); } /// /// Saves data using the identifier. /// /// Identifier. /// Object to save. /// Encrypt the data? /// Encryption Password. /// Serializer. /// Encoder. /// Encoding. /// Path. /// The 1st type parameter. public static void Save(string identifier, T obj, bool encode, string password, ISaveGameSerializer serializer, ISaveGameEncoder encoder, Encoding encoding, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { throw new System.ArgumentNullException("identifier"); } if (serializer == null) { serializer = SaveGame.Serializer; } if (encoding == null) { encoding = SaveGame.DefaultEncoding; } string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } if (obj == null) { obj = default(T); } Stream stream = null; #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL #if UNITY_WSA || UNITY_WINRT UnityEngine.Windows.Directory.CreateDirectory ( filePath ); #else Directory.CreateDirectory(Path.GetDirectoryName(filePath)); #endif #endif if (encode) { stream = new MemoryStream(); } else { #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT stream = new MemoryStream (); #else stream = File.Create(filePath); #endif } else { stream = new MemoryStream(); } #else stream = new MemoryStream (); #endif } serializer.Serialize(obj, stream, encoding); if (encode) { string data = System.Convert.ToBase64String(((MemoryStream)stream).ToArray()); string encoded = encoder.Encode(data, password); #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT UnityEngine.Windows.File.WriteAllBytes ( filePath, encoding.GetBytes ( encoded ) ); #else File.WriteAllText(filePath, encoded, encoding); #endif } else { PlayerPrefs.SetString(filePath, encoded); PlayerPrefs.Save(); } #else PlayerPrefs.SetString ( filePath, encoded ); PlayerPrefs.Save (); #endif } else if (!IOSupported()) { string data = encoding.GetString(((MemoryStream)stream).ToArray()); PlayerPrefs.SetString(filePath, data); PlayerPrefs.Save(); } stream.Dispose(); if (SaveCallback != null) { SaveCallback.Invoke( obj, identifier, encode, password, serializer, encoder, encoding, path); } if (OnSaved != null) { OnSaved( obj, identifier, encode, password, serializer, encoder, encoding, path); } } /// /// Loads data using identifier. /// /// Identifier. /// The 1st type parameter. public static T Load(string identifier) { return Load(identifier, default(T), Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier and defaultValue. /// /// Identifier. /// Default value. /// The 1st type parameter. public static T Load(string identifier, T defaultValue) { return Load(identifier, defaultValue, Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier and encodePassword. /// /// Identifier. /// Encode password. /// The 1st type parameter. public static T Load(string identifier, bool encode, string encodePassword) { return Load(identifier, default(T), encode, encodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier and serializer. /// /// Identifier. /// Serializer. /// The 1st type parameter. public static T Load(string identifier, ISaveGameSerializer serializer) { return Load(identifier, default(T), Encode, EncodePassword, serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier and encoder. /// /// Identifier. /// Encoder. /// The 1st type parameter. public static T Load(string identifier, ISaveGameEncoder encoder) { return Load(identifier, default(T), Encode, EncodePassword, Serializer, encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier and encoding. /// /// Identifier. /// Encoding. /// The 1st type parameter. public static T Load(string identifier, Encoding encoding) { return Load(identifier, default(T), Encode, EncodePassword, Serializer, Encoder, encoding, SavePath); } /// /// Load the specified identifier and savePath. /// /// Identifier. /// Save path. /// The 1st type parameter. public static T Load(string identifier, SaveGamePath savePath) { return Load(identifier, default(T), Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, savePath); } /// /// Load the specified identifier, defaultValue and encode. /// /// Identifier. /// Default value. /// If set to true encode. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, bool encode) { return Load(identifier, defaultValue, encode, EncodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier, defaultValue and encodePassword. /// /// Identifier. /// Default value. /// Encode password. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, string encodePassword) { return Load(identifier, defaultValue, Encode, encodePassword, Serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier, defaultValue and serializer. /// /// Identifier. /// Default value. /// Serializer. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, ISaveGameSerializer serializer) { return Load(identifier, defaultValue, Encode, EncodePassword, serializer, Encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier, defaultValue and encoder. /// /// Identifier. /// Default value. /// Encoder. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, ISaveGameEncoder encoder) { return Load(identifier, defaultValue, Encode, EncodePassword, Serializer, encoder, DefaultEncoding, SavePath); } /// /// Load the specified identifier, defaultValue and encoding. /// /// Identifier. /// Default value. /// Encoding. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, Encoding encoding) { return Load(identifier, defaultValue, Encode, EncodePassword, Serializer, Encoder, encoding, SavePath); } /// /// Load the specified identifier, defaultValue and savePath. /// /// Identifier. /// Default value. /// Save path. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, SaveGamePath savePath) { return Load(identifier, defaultValue, Encode, EncodePassword, Serializer, Encoder, DefaultEncoding, savePath); } /// /// Loads data using identifier. /// /// Identifier. /// Default Value. /// Load encrypted data? (set it to true if you have used encryption in save) /// Encryption Password. /// Serializer. /// Encoder. /// Encoding. /// Path. /// The 1st type parameter. public static T Load(string identifier, T defaultValue, bool encode, string password, ISaveGameSerializer serializer, ISaveGameEncoder encoder, Encoding encoding, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { throw new System.ArgumentNullException("identifier"); } if (serializer == null) { serializer = SaveGame.Serializer; } if (encoding == null) { encoding = SaveGame.DefaultEncoding; } if (defaultValue == null) { defaultValue = default(T); } T result = defaultValue; string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (!Exists(filePath, path)) #else if ( !Exists ( filePath, path ) ) #endif { Debug.LogWarningFormat( "The specified identifier ({1}) does not exists. please use Exists () to check for existent before calling Load.\n" + "returning the default(T) instance.", filePath, identifier); return result; } Stream stream = null; if (encode) { string data = ""; #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT data = encoding.GetString ( UnityEngine.Windows.File.ReadAllBytes ( filePath ) ); #else data = File.ReadAllText(filePath, encoding); #endif } else { data = PlayerPrefs.GetString(filePath); } #else data = PlayerPrefs.GetString ( filePath ); #endif string decoded = encoder.Decode(data, password); stream = new MemoryStream(System.Convert.FromBase64String(decoded), true); } else { #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT stream = new MemoryStream ( UnityEngine.Windows.File.ReadAllBytes ( filePath ) ); #else stream = File.OpenRead(filePath); #endif } else { string data = PlayerPrefs.GetString(filePath); stream = new MemoryStream(encoding.GetBytes(data)); } #else string data = PlayerPrefs.GetString ( filePath ); stream = new MemoryStream ( encoding.GetBytes ( data ) ); #endif } result = serializer.Deserialize(stream, encoding); stream.Dispose(); if (result == null) { result = defaultValue; } if (LoadCallback != null) { LoadCallback.Invoke( result, identifier, encode, password, serializer, encoder, encoding, path); } if (OnLoaded != null) { OnLoaded( result, identifier, encode, password, serializer, encoder, encoding, path); } return result; } /// /// Checks whether the specified identifier exists or not. /// /// Identifier. public static bool Exists(string identifier) { return Exists(identifier, SavePath); } /// /// Checks whether the specified identifier exists or not. /// /// Identifier. /// Path. /// Check in Web? /// Web username. /// Web password. /// Web URL. public static bool Exists(string identifier, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { throw new System.ArgumentNullException("identifier"); } string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { bool exists = false; #if UNITY_WSA || UNITY_WINRT exists = UnityEngine.Windows.Directory.Exists ( filePath ); #else exists = Directory.Exists(filePath); #endif if (!exists) { #if UNITY_WSA || UNITY_WINRT exists = UnityEngine.Windows.File.Exists ( filePath ); #else exists = File.Exists(filePath); #endif } return exists; } else { return PlayerPrefs.HasKey(filePath); } #else return PlayerPrefs.HasKey ( filePath ); #endif } /// /// Delete the specified identifier. /// /// Identifier. public static void Delete(string identifier) { Delete(identifier, SavePath); } /// /// Delete the specified identifier and path. /// /// Identifier. /// Path. public static void Delete(string identifier, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { throw new System.ArgumentNullException("identifier"); } string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } if (!Exists(filePath, path)) { return; } #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT if (UnityEngine.Windows.File.Exists(filePath)) UnityEngine.Windows.File.Delete(filePath); else if (UnityEngine.Windows.Directory.Exists(filePath)) UnityEngine.Windows.Directory.Delete(filePath, true); #else if (File.Exists(filePath)) File.Delete(filePath); else if (Directory.Exists(filePath)) Directory.Delete(filePath, true); #endif } else { PlayerPrefs.DeleteKey(filePath); } #else PlayerPrefs.DeleteKey ( filePath ); #endif } /// /// Clear this instance. /// Alias of DeleteAll /// public static void Clear() { DeleteAll(SavePath); } /// /// Clear the specified path. /// Alias of DeleteAll /// /// Path. public static void Clear(SaveGamePath path) { DeleteAll(path); } /// /// Deletes all. /// public static void DeleteAll() { DeleteAll(SavePath); } /// /// Deletes all. /// /// Path. public static void DeleteAll(SaveGamePath path) { string dirPath = ""; switch (path) { case SaveGamePath.PersistentDataPath: dirPath = Application.persistentDataPath; break; case SaveGamePath.DataPath: dirPath = Application.dataPath; break; } #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (IOSupported()) { #if UNITY_WSA || UNITY_WINRT UnityEngine.Windows.Directory.Delete ( dirPath ); #else DirectoryInfo info = new DirectoryInfo(dirPath); FileInfo[] files = info.GetFiles(); for (int i = 0; i < files.Length; i++) { files[i].Delete(); } DirectoryInfo[] dirs = info.GetDirectories(); for (int i = 0; i < dirs.Length; i++) { dirs[i].Delete(true); } #endif } else { PlayerPrefs.DeleteAll(); } #else PlayerPrefs.DeleteAll (); #endif } /// /// Retrieves files from the save path home. /// /// public static FileInfo[] GetFiles() { return GetFiles(string.Empty, SavePath); } /// /// Retrieves files from the given directory path. /// /// /// public static FileInfo[] GetFiles(string identifier) { return GetFiles(identifier, SavePath); } /// /// Retrieves files from the given directory path. /// /// /// /// public static FileInfo[] GetFiles(string identifier, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { identifier = string.Empty; } string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } FileInfo[] files = new FileInfo[0]; if (!Exists(filePath, path)) { return files; } if (Directory.Exists(filePath)) { DirectoryInfo info = new DirectoryInfo(filePath); files = info.GetFiles(); } return files; } /// /// Retrieves directories from the save path home. /// /// public static DirectoryInfo[] GetDirectories() { return GetDirectories(string.Empty, SavePath); } /// /// Retrieves directories from the given directory path. /// /// /// public static DirectoryInfo[] GetDirectories(string identifier) { return GetDirectories(identifier, SavePath); } /// /// Retrieves directories from the given directory path. /// /// /// /// public static DirectoryInfo[] GetDirectories(string identifier, SaveGamePath path) { if (string.IsNullOrEmpty(identifier)) { identifier = string.Empty; } string filePath = ""; if (!IsFilePath(identifier)) { switch (path) { default: case SaveGamePath.PersistentDataPath: filePath = string.Format("{0}/{1}", Application.persistentDataPath, identifier); break; case SaveGamePath.DataPath: filePath = string.Format("{0}/{1}", Application.dataPath, identifier); break; } } else { filePath = identifier; } DirectoryInfo[] directories = new DirectoryInfo[0]; if (!Exists(filePath, path)) { return directories; } if (Directory.Exists(filePath)) { DirectoryInfo info = new DirectoryInfo(filePath); directories = info.GetDirectories(); } return directories; } /// /// Checks if the IO is supported on current platform or not. /// /// true, if supported was IOed, false otherwise. public static bool IOSupported() { return Application.platform != RuntimePlatform.WebGLPlayer && Application.platform != RuntimePlatform.WSAPlayerARM && Application.platform != RuntimePlatform.WSAPlayerX64 && Application.platform != RuntimePlatform.WSAPlayerX86 && #if !UNITY_2017_3_OR_NEWER Application.platform != RuntimePlatform.SamsungTVPlayer && #endif Application.platform != RuntimePlatform.tvOS && Application.platform != RuntimePlatform.PS4; } /// /// Determines if the string is file path. /// /// true if is file path the specified str; otherwise, false. /// String. public static bool IsFilePath(string str) { bool result = false; #if !UNITY_SAMSUNGTV && !UNITY_TVOS && !UNITY_WEBGL if (Path.IsPathRooted(str)) { try { Path.GetFullPath(str); result = true; } catch (System.Exception) { result = false; } } #endif return result; } } }