PersistentStorage.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. using System;
  2. using System.Globalization;
  3. using System.IO;
  4. using System.Text;
  5. using UnityEngine;
  6. namespace I2.Loc
  7. {
  8. public static class PersistentStorage
  9. {
  10. static I2CustomPersistentStorage mStorage;
  11. public enum eFileType { Raw, Persistent, Temporal, Streaming }
  12. #region PlayerPrefs
  13. public static void SetSetting_String(string key, string value)
  14. {
  15. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  16. mStorage.SetSetting_String(key, value);
  17. }
  18. public static string GetSetting_String(string key, string defaultValue)
  19. {
  20. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  21. return mStorage.GetSetting_String(key, defaultValue);
  22. }
  23. public static void DeleteSetting(string key)
  24. {
  25. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  26. mStorage.DeleteSetting(key);
  27. }
  28. public static bool HasSetting( string key )
  29. {
  30. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  31. return mStorage.HasSetting(key);
  32. }
  33. public static void ForceSaveSettings()
  34. {
  35. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  36. mStorage.ForceSaveSettings();
  37. }
  38. #endregion
  39. #region File Management
  40. public static bool CanAccessFiles()
  41. {
  42. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  43. return mStorage.CanAccessFiles();
  44. }
  45. public static bool SaveFile(eFileType fileType, string fileName, string data, bool logExceptions = true)
  46. {
  47. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  48. return mStorage.SaveFile(fileType, fileName, data, logExceptions);
  49. }
  50. public static string LoadFile(eFileType fileType, string fileName, bool logExceptions=true)
  51. {
  52. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  53. return mStorage.LoadFile(fileType, fileName, logExceptions);
  54. }
  55. public static bool DeleteFile(eFileType fileType, string fileName, bool logExceptions = true)
  56. {
  57. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  58. return mStorage.DeleteFile(fileType, fileName, logExceptions);
  59. }
  60. public static bool HasFile(eFileType fileType, string fileName, bool logExceptions = true)
  61. {
  62. if (mStorage == null) mStorage = new I2CustomPersistentStorage();
  63. return mStorage.HasFile(fileType, fileName, logExceptions);
  64. }
  65. #endregion
  66. }
  67. public abstract class I2BasePersistentStorage
  68. {
  69. #region PlayerPrefs
  70. public virtual void SetSetting_String(string key, string value)
  71. {
  72. try
  73. {
  74. // Use PlayerPrefs, but if the data is bigger than the limit, split it into multiple entries
  75. var len = value.Length;
  76. int maxLength = 8000;
  77. if (len<=maxLength)
  78. {
  79. PlayerPrefs.SetString(key, value);
  80. }
  81. else
  82. {
  83. int numSections = Mathf.CeilToInt(len / (float)maxLength);
  84. for (int i=0; i<numSections; ++i)
  85. {
  86. int iStart = maxLength * i;
  87. PlayerPrefs.SetString($"[I2split]{i}{key}", value.Substring(iStart, Mathf.Min(maxLength, len-iStart)));
  88. }
  89. PlayerPrefs.SetString(key, "[$I2#@div$]" + numSections);
  90. }
  91. }
  92. catch (Exception) { Debug.LogError("Error saving PlayerPrefs " + key); }
  93. }
  94. public virtual string GetSetting_String(string key, string defaultValue)
  95. {
  96. try
  97. {
  98. var data = PlayerPrefs.GetString(key, defaultValue);
  99. // Check if the data is splitted, if so, concat all the sections
  100. if (!string.IsNullOrEmpty(data) && data.StartsWith("[I2split]", StringComparison.Ordinal))
  101. {
  102. int nSections = int.Parse(data.Substring("[I2split]".Length), CultureInfo.InvariantCulture);
  103. data = "";
  104. for (int i=0; i<nSections; ++i)
  105. {
  106. data += PlayerPrefs.GetString($"[I2split]{i}{key}", "");
  107. }
  108. }
  109. return data;
  110. }
  111. catch (Exception)
  112. {
  113. Debug.LogError("Error loading PlayerPrefs " + key);
  114. return defaultValue;
  115. }
  116. }
  117. public virtual void DeleteSetting( string key)
  118. {
  119. try
  120. {
  121. var data = PlayerPrefs.GetString(key, null);
  122. // If the data is splitted, delete each section as well
  123. if (!string.IsNullOrEmpty(data) && data.StartsWith("[I2split]", StringComparison.Ordinal))
  124. {
  125. int nSections = int.Parse(data.Substring("[I2split]".Length), CultureInfo.InvariantCulture);
  126. for (int i = 0; i < nSections; ++i)
  127. {
  128. PlayerPrefs.DeleteKey($"[I2split]{i}{key}");
  129. }
  130. }
  131. PlayerPrefs.DeleteKey(key);
  132. }
  133. catch (Exception)
  134. {
  135. Debug.LogError("Error deleting PlayerPrefs " + key);
  136. }
  137. }
  138. public virtual void ForceSaveSettings()
  139. {
  140. PlayerPrefs.Save();
  141. }
  142. public virtual bool HasSetting(string key)
  143. {
  144. return PlayerPrefs.HasKey(key);
  145. }
  146. #endregion
  147. #region Files
  148. public virtual bool CanAccessFiles()
  149. {
  150. #if UNITY_SWITCH || UNITY_WSA
  151. return false;
  152. #else
  153. return true;
  154. #endif
  155. }
  156. string UpdateFilename(PersistentStorage.eFileType fileType, string fileName)
  157. {
  158. switch (fileType)
  159. {
  160. case PersistentStorage.eFileType.Persistent: fileName = Application.persistentDataPath + "/" + fileName; break;
  161. case PersistentStorage.eFileType.Temporal: fileName = Application.temporaryCachePath + "/" + fileName; break;
  162. case PersistentStorage.eFileType.Streaming: fileName = Application.streamingAssetsPath + "/" + fileName; break;
  163. }
  164. return fileName;
  165. }
  166. public virtual bool SaveFile(PersistentStorage.eFileType fileType, string fileName, string data, bool logExceptions = true)
  167. {
  168. if (!CanAccessFiles())
  169. return false;
  170. try
  171. {
  172. fileName = UpdateFilename(fileType, fileName);
  173. File.WriteAllText(fileName, data, Encoding.UTF8);
  174. return true;
  175. }
  176. catch (Exception e)
  177. {
  178. if (logExceptions)
  179. Debug.LogError("Error saving file '" + fileName + "'\n" + e);
  180. return false;
  181. }
  182. }
  183. public virtual string LoadFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true)
  184. {
  185. if (!CanAccessFiles())
  186. return null;
  187. try
  188. {
  189. fileName = UpdateFilename(fileType, fileName);
  190. return File.ReadAllText(fileName, Encoding.UTF8);
  191. }
  192. catch (Exception e)
  193. {
  194. if (logExceptions)
  195. Debug.LogError("Error loading file '" + fileName + "'\n" + e);
  196. return null;
  197. }
  198. }
  199. public virtual bool DeleteFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true)
  200. {
  201. if (!CanAccessFiles())
  202. return false;
  203. try
  204. {
  205. fileName = UpdateFilename(fileType, fileName);
  206. File.Delete(fileName);
  207. return true;
  208. }
  209. catch (Exception e)
  210. {
  211. if (logExceptions)
  212. Debug.LogError("Error deleting file '" + fileName + "'\n" + e);
  213. return false;
  214. }
  215. }
  216. public virtual bool HasFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true)
  217. {
  218. if (!CanAccessFiles())
  219. return false;
  220. try
  221. {
  222. fileName = UpdateFilename(fileType, fileName);
  223. return File.Exists(fileName);
  224. }
  225. catch (Exception e)
  226. {
  227. if (logExceptions) Debug.LogError("Error requesting file '" + fileName + "'\n" + e);
  228. return false;
  229. }
  230. }
  231. #endregion
  232. }
  233. public class I2CustomPersistentStorage : I2BasePersistentStorage
  234. {
  235. //public override void SetSetting_String(string key, string value)
  236. //public override string GetSetting_String(string key, string defaultValue)
  237. //public override void DeleteSetting(string key)
  238. //public override void ForceSaveSettings()
  239. //public override bool HasSetting(string key)
  240. //public virtual bool CanAccessFiles();
  241. //public override bool SaveFile(PersistentStorage.eFileType fileType, string fileName, string data, bool logExceptions = true);
  242. //public override string LoadFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true);
  243. //public override bool DeleteFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true);
  244. //public override bool HasFile(PersistentStorage.eFileType fileType, string fileName, bool logExceptions = true);
  245. }
  246. }