using UnityEngine; using System.Collections; namespace Fungus { /// /// Manages the Save History (a list of Save Points). /// public class SaveManager : MonoBehaviour { protected static SaveHistory saveHistory = new SaveHistory(); protected virtual bool ReadSaveHistory(string saveDataKey) { var historyData = PlayerPrefs.GetString(saveDataKey); if (!string.IsNullOrEmpty(historyData)) { var tempSaveHistory = JsonUtility.FromJson(historyData); if (tempSaveHistory != null) { saveHistory = tempSaveHistory; return true; } } return false; } protected virtual bool WriteSaveHistory(string saveDataKey) { var historyData = JsonUtility.ToJson(saveHistory, true); if (!string.IsNullOrEmpty(historyData)) { PlayerPrefs.SetString(saveDataKey, historyData); PlayerPrefs.Save(); return true; } return false; } protected virtual void OnEnable() { SaveManagerSignals.OnSavePointLoaded += OnSavePointLoaded; } protected virtual void OnDisable() { SaveManagerSignals.OnSavePointLoaded -= OnSavePointLoaded; } protected virtual void OnSavePointLoaded(string savePointKey) { // Flag that a save point was loaded. // The flag remains set for 1 frame to give other components enough time to poll it in their Start method. HasLoadedSavePoint = true; StartCoroutine(ResetHasLoadedSavePoint()); } protected virtual IEnumerator ResetHasLoadedSavePoint() { yield return new WaitForEndOfFrame(); HasLoadedSavePoint = false; } #region Public members /// /// The default key used for storing save game data in PlayerPrefs. /// public const string DefaultSaveDataKey = "save_data"; /// /// Returns the number of Save Points in the Save History. /// public virtual int NumSavePoints { get { return saveHistory.NumSavePoints; } } /// /// Returns the current number of rewound Save Points in the Save History. /// public virtual int NumRewoundSavePoints { get { return saveHistory.NumRewoundSavePoints; } } public virtual bool HasLoadedSavePoint { get; private set; } /// /// Writes the Save History to persistent storage. /// public virtual void Save(string saveDataKey = DefaultSaveDataKey) { WriteSaveHistory(saveDataKey); } /// /// Loads the Save History from persistent storage. /// public void Load(string saveDataKey = DefaultSaveDataKey) { if (ReadSaveHistory(saveDataKey)) { saveHistory.ClearRewoundSavePoints(); saveHistory.LoadLatestSavePoint(); } } /// /// Deletes a previously stored Save History from persistent storage. /// public void Delete(string saveDataKey = DefaultSaveDataKey) { PlayerPrefs.DeleteKey(saveDataKey); PlayerPrefs.Save(); } /// /// Returns true if save data has previously been stored using this key. /// public bool SaveDataExists(string saveDataKey = DefaultSaveDataKey) { return PlayerPrefs.HasKey(saveDataKey); } /// /// Creates a new Save Point using a key and description, and adds it to the Save History. /// public virtual void AddSavePoint(string savePointKey, string savePointDescription) { saveHistory.AddSavePoint(savePointKey, savePointDescription); SaveManagerSignals.DoSavePointAdded(savePointKey, savePointDescription); } /// /// Rewinds to the previous Save Point in the Save History and loads that Save Point. /// public virtual void Rewind() { if (saveHistory.NumSavePoints > 0) { // Rewinding the first save point is not permitted if (saveHistory.NumSavePoints > 1) { saveHistory.Rewind(); } saveHistory.LoadLatestSavePoint(); } } /// /// Fast forwards to the next rewound Save Point in the Save History and loads that Save Point. /// public virtual void FastForward() { if (saveHistory.NumRewoundSavePoints > 0) { saveHistory.FastForward(); saveHistory.LoadLatestSavePoint(); } } /// /// Deletes all Save Points in the Save History. /// public virtual void ClearHistory() { saveHistory.Clear(); } /// /// Starts Block execution based on a Save Point Key /// The execution order is: /// 1. Save Point Loaded event handlers with a matching key. /// 2. First Save Point command (in any Block) with matching key. Execution starts at the following command. /// 3. Any label in any block with name matching the key. Execution starts at the following command. /// public static void ExecuteBlocks(string savePointKey) { // Execute Save Point Loaded event handlers with matching key. SavePointLoaded.NotifyEventHandlers(savePointKey); // Execute any block containing a SavePoint command matching the save key, with Resume From Here enabled var savePoints = Object.FindObjectsOfType(); for (int i = 0; i < savePoints.Length; i++) { var savePoint = savePoints[i]; if (savePoint.ResumeFromHere && string.Compare(savePoint.SavePointKey, savePointKey, true) == 0) { int index = savePoint.CommandIndex; var block = savePoint.ParentBlock; var flowchart = savePoint.GetFlowchart(); flowchart.ExecuteBlock(block, index + 1); // Assume there's only one SavePoint using this key break; } } // Execute any block containing a Label matching the save key var labels = Object.FindObjectsOfType