ProjectDDD/Assets/Plugins/Easy Save 3/Scripts/Auto Save/ES3AutoSaveMgr.cs

223 lines
6.8 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Linq;
#if UNITY_VISUAL_SCRIPTING
[Unity.VisualScripting.IncludeInSettings(true)]
#elif BOLT_VISUAL_SCRIPTING
[Ludiq.IncludeInSettings(true)]
#endif
public class ES3AutoSaveMgr : MonoBehaviour
{
public static ES3AutoSaveMgr _current = null;
public static ES3AutoSaveMgr Current
{
get
{
if (_current == null /*|| _current.gameObject.scene != SceneManager.GetActiveScene()*/)
{
var scene = SceneManager.GetActiveScene();
var roots = scene.GetRootGameObjects();
// First, look for Easy Save 3 Manager in the top-level.
foreach (var root in roots)
if (root.name == "Easy Save 3 Manager")
return _current = root.GetComponent<ES3AutoSaveMgr>();
// If the user has moved or renamed the Easy Save 3 Manager, we need to perform a deep search.
foreach (var root in roots)
if ((_current = root.GetComponentInChildren<ES3AutoSaveMgr>()) != null)
return _current;
}
return _current;
}
}
public static Dictionary<Scene, ES3AutoSaveMgr> managers = new Dictionary<Scene, ES3AutoSaveMgr>();
// Included for backwards compatibility.
public static ES3AutoSaveMgr Instance
{
get { return Current; }
}
public enum LoadEvent { None, Awake, Start }
public enum SaveEvent { None, OnApplicationQuit, OnApplicationPause }
public string key = System.Guid.NewGuid().ToString();
public bool immediatelyCommitToFile = true;
public SaveEvent saveEvent = SaveEvent.OnApplicationQuit;
public LoadEvent loadEvent = LoadEvent.Start;
public ES3SerializableSettings settings = new ES3SerializableSettings("SaveFile.es3", ES3.Location.Cache);
public HashSet<ES3AutoSave> autoSaves = new HashSet<ES3AutoSave>();
List<long> destroyedIds = new List<long>();
public void Save()
{
if (autoSaves == null || autoSaves.Count == 0)
return;
ManageSlots();
// If we're using caching and we've not already cached this file, cache it.
if (settings.location == ES3.Location.Cache && !ES3.FileExists(settings))
ES3.CacheFile(settings);
if (autoSaves == null || autoSaves.Count == 0)
{
ES3.DeleteKey(key, settings);
}
else
{
var gameObjects = new List<GameObject>();
foreach (var autoSave in autoSaves)
{
// If the ES3AutoSave component is disabled, don't save it.
if (autoSave != null && autoSave.enabled)
gameObjects.Add(autoSave.gameObject);
}
// Save in the same order as their depth in the hierarchy.
ES3.Save(key, gameObjects.OrderBy(x => GetDepth(x.transform)).ToArray(), settings);
if(destroyedIds != null && destroyedIds.Count > 0)
ES3.Save($"{key}_destroyed", destroyedIds, settings);
}
if(immediatelyCommitToFile && settings.location == ES3.Location.Cache && ES3.FileExists(settings))
ES3.StoreCachedFile(settings);
}
public void Load()
{
ManageSlots();
try
{
// If we're using caching and we've not already cached this file, cache it.
if (settings.location == ES3.Location.Cache && !ES3.FileExists(settings))
ES3.CacheFile(settings);
}
catch { }
// Ensure that the reference manager for this scene has been initialised.
var mgr = ES3ReferenceMgr.GetManagerFromScene(this.gameObject.scene, false);
mgr.Awake();
ES3.Load<GameObject[]>(key, new GameObject[0], settings);
// Destroy any objects for which the destroyed state was saved.
foreach(var id in ES3.Load($"{key}_destroyed", new List<long>(), settings))
{
var go = mgr.Get(id, true);
if(go != null)
{
var autoSave = ((GameObject)go).GetComponent<ES3AutoSave>();
if(autoSave != null)
DestroyAutoSave(autoSave);
Destroy(go);
}
}
}
void Start()
{
if(loadEvent == LoadEvent.Start)
Load();
}
public void Awake()
{
managers[this.gameObject.scene] = this;
GetAutoSaves();
if (loadEvent == LoadEvent.Awake)
Load();
}
void OnApplicationQuit()
{
if(saveEvent == SaveEvent.OnApplicationQuit)
Save();
}
void OnApplicationPause(bool paused)
{
if( (saveEvent == SaveEvent.OnApplicationPause ||
(Application.isMobilePlatform && saveEvent == SaveEvent.OnApplicationQuit)) && paused)
Save();
}
/* Register an ES3AutoSave with the ES3AutoSaveMgr, if there is one */
public static void AddAutoSave(ES3AutoSave autoSave)
{
if (autoSave == null)
return;
ES3AutoSaveMgr mgr;
if (managers.TryGetValue(autoSave.gameObject.scene, out mgr))
mgr.autoSaves.Add(autoSave);
}
/* Remove an ES3AutoSave from the ES3AutoSaveMgr, for example if it's GameObject has been destroyed */
public static void DestroyAutoSave(ES3AutoSave autoSave)
{
if (autoSave == null)
return;
ES3AutoSaveMgr mgr;
if (managers.TryGetValue(autoSave.gameObject.scene, out mgr))
{
mgr.autoSaves.Remove(autoSave);
// Get the reference ID of the GameObject and add it to the destroyed list if it's not a prefab instance.
if (autoSave.saveDestroyed)
{
var refMgr = ES3ReferenceMgr.GetManagerFromScene(autoSave.gameObject.scene, true);
if (refMgr != null)
{
var id = refMgr.Add(autoSave.gameObject);
if (id != -1)
mgr.destroyedIds.Add(id);
}
}
}
}
/* Gathers all of the ES3AutoSave Components in the scene and registers them with the manager */
public void GetAutoSaves()
{
autoSaves = new HashSet<ES3AutoSave>();
foreach (var go in this.gameObject.scene.GetRootGameObjects())
autoSaves.UnionWith(go.GetComponentsInChildren<ES3AutoSave>(true));
}
// Gets the depth of a Transform in the hierarchy.
static int GetDepth(Transform t)
{
int depth = 0;
while (t.parent != null)
{
t = t.parent;
depth++;
}
return depth;
}
// Changes the path for this ES3AutoSave if we're using save slots.
void ManageSlots()
{
#if ES3_TMPRO && ES3_UGUI
if (ES3SlotManager.selectedSlotPath != null)
settings.path = ES3SlotManager.selectedSlotPath;
#endif
}
}