using System.Collections.Generic; using UnityEngine; namespace Ubisoft { /// /// Class responsible for managing all IHtPlayerPrefs objects. /// /// In order to keep preferences from getting accidentally overriden consumers are allowed to have only one IHtPlayerPrefs object /// per channel. This can be guaranteed by allowing consumers to get an IHtPlayerPrefs instance only via this class. /// /// Please, call Destroy() once you are done with this class, typically right before restarting your app, in order to make sure that /// all IHtPlayerPrefs are saved and destroyed properly so you can restart your app clean. /// public class HtPlayerPrefsService : HtSingletonHolder.IConsumer { public enum EError { None, PlayerPrefsForChannelAlreadyExist } public delegate void OnCreateDelegate(string channel, EError error, IHtPlayerPrefs playerPrefs); private HtPlayerPrefsFactory Factory { get; set; } private List Catalog { get; } private HtPlayerPrefsMonoBehaviour MonoBehaviour { get; set; } public HtPlayerPrefsService(HtPlayerPrefsFactory factory) { Factory = factory; Catalog = new List(); // MonoBehaviour is created to take care of key Unity events. MonoBehaviour = HtSingletonHolder.AddMainComponent(this); MonoBehaviour.Init(this); } ~HtPlayerPrefsService() { InternalDestroy(false); } /// /// Save and destroy all IHtPlayePrefs objects. Please, call this method right before restarting your app. /// public void Destroy() { InternalDestroy(true); } private void InternalDestroy(bool destroyMonoBehaviour) { if (MonoBehaviour != null) { HtSingletonHolder.RemoveMainComponent(destroyMonoBehaviour); MonoBehaviour = null; } if (Catalog != null) { int count = Catalog.Count; for (int i = 0; i < count; ++i) { // Save it before destroying it if (Catalog[i].NeedsToSave) { Catalog[i].Save(); } } Catalog.Clear(); } Factory = null; } /// /// Create an IHtPlayerPrefs> instance by using the config associated to the requested channel. /// This task is asynchronous as some IHtPlayerPrefs implementations may need to communicate with Server. /// /// PlayePrefs channel to save preferences to. /// Delegate to call once the object is ready. public void CreatePlayerPrefs(string channel, OnCreateDelegate onCreateDelegate) { EError error = EError.None; IHtPlayerPrefs returnValue = null; // Only an instance per channel is allowed to keep this channel preferences from getting accidentally overriden. if (GetPlayerPrefs(channel) == null) { returnValue = Factory.Create(channel); Catalog.Add(returnValue); } else { error = EError.PlayerPrefsForChannelAlreadyExist; Factory.Logger.LogError($"An instance for channel {Debug.FormatTextInUserContext(channel)} already exists."); } onCreateDelegate?.Invoke(channel, error, returnValue); } /// /// Destroy the instance used for the channel passed in, if it exists. /// /// PlayePrefs channel to destroy. public void DestroyPlayerPrefs(string channel) { IHtPlayerPrefs prefs = GetPlayerPrefs(channel); if (prefs != null) { // Save it before destroying it if (prefs.NeedsToSave) { prefs.Save(); } _ = Catalog.Remove(prefs); } } /// /// Retrieve the IHtPlayerPrefs object used for the channel passed in, if it exists. /// You need to have called CreatePlayerPrefs() before calling this method. /// /// PlayerPrefs channel to retrieve. /// The instance of IHtPlayerPrefs responsible for saving this channel preferences, if it exists", otherwise null. public IHtPlayerPrefs GetPlayerPrefs(string channel) { IHtPlayerPrefs returnValue = null; int count = Catalog.Count; for (int i = 0; i < count && returnValue == null; ++i) { if (Catalog[i].Channel.Equals(channel)) { returnValue = Catalog[i]; } } return returnValue; } /// /// Delete preferences for all channels that are currently in memory. /// public void DeleteAllPlayerPrefs() { int count = Catalog.Count; for (int i = 0; i < count; ++i) { Catalog[i].DeleteAll(); } } /// /// Save all channel preferences that are currently in memory. /// public void SaveAllPlayerPrefs() { InternalSave(true); } /// /// Callbak called when HtSingletonHolder is destroyed. /// /// Consumers shouldn't call this method. /// /// Component that is about to be destroyed. public void DestroySingleton(Component singleton) { if (singleton == MonoBehaviour) { MonoBehaviour = null; } } internal void Update() { InternalSave(false); } private void InternalSave(bool force) { // Make sure that all IHtPlayerPref objects save their preferences if AutomaticSave is enabled. int count = Catalog.Count; for (int i = 0; i < count; ++i) { Catalog[i].Update(); if ((force || Catalog[i].AutomaticSave) && Catalog[i].NeedsToSave) { Catalog[i].Save(); } } } } }