From 1bd77d9628ecbbf8f6e5ed397d54023bd6b3d4d5 Mon Sep 17 00:00:00 2001 From: LubieKakao1212 Date: Mon, 2 Jan 2023 16:13:04 +0100 Subject: [PATCH] Abstracified achievment types, removed achievment loading (will be restored in future commits) --- Achivments.meta => Achievments.meta | 0 Achievments/AchievmentManager.cs | 341 ++++++++++++++++++ .../AchievmentManager.cs.meta | 2 +- .../AchievmentTypes.meta | 2 +- Achievments/AchievmentTypes/AchievmentData.cs | 21 ++ .../AchievmentTypes/AchievmentData.cs.meta | 2 +- .../AchievmentTypes/AchievmentDefinition.cs | 15 + .../AchievmentDefinition.cs.meta | 2 +- .../AchievmentTypes/FloatAchievmentData.cs | 35 ++ .../FloatAchievmentData.cs.meta | 11 + .../FloatAchievmentDefinition.cs | 29 ++ .../FloatAchievmentDefinition.cs.meta | 11 + .../AchievmentTypes/IntAchievmentData.cs | 36 ++ .../AchievmentTypes/IntAchievmentData.cs.meta | 11 + .../IntAchievmentDefinition.cs | 27 ++ .../IntAchievmentDefinition.cs.meta | 11 + .../AchievmentTypes/ToggleAchievmentData.cs | 18 + .../ToggleAchievmentData.cs.meta | 11 + .../ToggleAchievmentDefinition.cs | 15 + .../ToggleAchievmentDefinition.cs.meta | 11 + .../AchivmentDefinitionCollection.cs | 6 +- .../AchivmentDefinitionCollection.cs.meta | 0 .../AchivmentManagerConfig.cs | 6 +- .../AchivmentManagerConfig.cs.meta | 0 Achievments/IAchievmentCallbackReciever.cs | 23 ++ .../IAchievmentCallbackReciever.cs.meta | 0 .../IAchivmentManagerConfig.cs | 8 +- .../IAchivmentManagerConfig.cs.meta | 0 .../IAchivmentStorage.cs | 2 +- .../IAchivmentStorage.cs.meta | 0 .../NEG.Utils.Achivments.asmdef | 0 .../NEG.Utils.Achivments.asmdef.meta | 0 Achivments/AchivmentData.cs | 22 -- Achivments/AchivmentDefinition.cs | 34 -- Achivments/AchivmentManager.cs | 193 ---------- Achivments/IAchivmentCallbackReciever.cs | 23 -- 36 files changed, 642 insertions(+), 286 deletions(-) rename Achivments.meta => Achievments.meta (100%) create mode 100644 Achievments/AchievmentManager.cs rename Achivments/AchivmentManager.cs.meta => Achievments/AchievmentManager.cs.meta (83%) rename Achivments/Backend.meta => Achievments/AchievmentTypes.meta (77%) create mode 100644 Achievments/AchievmentTypes/AchievmentData.cs rename Achivments/AchivmentData.cs.meta => Achievments/AchievmentTypes/AchievmentData.cs.meta (83%) create mode 100644 Achievments/AchievmentTypes/AchievmentDefinition.cs rename Achivments/AchivmentDefinition.cs.meta => Achievments/AchievmentTypes/AchievmentDefinition.cs.meta (83%) create mode 100644 Achievments/AchievmentTypes/FloatAchievmentData.cs create mode 100644 Achievments/AchievmentTypes/FloatAchievmentData.cs.meta create mode 100644 Achievments/AchievmentTypes/FloatAchievmentDefinition.cs create mode 100644 Achievments/AchievmentTypes/FloatAchievmentDefinition.cs.meta create mode 100644 Achievments/AchievmentTypes/IntAchievmentData.cs create mode 100644 Achievments/AchievmentTypes/IntAchievmentData.cs.meta create mode 100644 Achievments/AchievmentTypes/IntAchievmentDefinition.cs create mode 100644 Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta create mode 100644 Achievments/AchievmentTypes/ToggleAchievmentData.cs create mode 100644 Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta create mode 100644 Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs create mode 100644 Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs.meta rename {Achivments => Achievments}/AchivmentDefinitionCollection.cs (59%) rename {Achivments => Achievments}/AchivmentDefinitionCollection.cs.meta (100%) rename {Achivments => Achievments}/AchivmentManagerConfig.cs (79%) rename {Achivments => Achievments}/AchivmentManagerConfig.cs.meta (100%) create mode 100644 Achievments/IAchievmentCallbackReciever.cs rename Achivments/IAchivmentCallbackReciever.cs.meta => Achievments/IAchievmentCallbackReciever.cs.meta (100%) rename {Achivments => Achievments}/IAchivmentManagerConfig.cs (58%) rename {Achivments => Achievments}/IAchivmentManagerConfig.cs.meta (100%) rename {Achivments => Achievments}/IAchivmentStorage.cs (85%) rename {Achivments => Achievments}/IAchivmentStorage.cs.meta (100%) rename {Achivments => Achievments}/NEG.Utils.Achivments.asmdef (100%) rename {Achivments => Achievments}/NEG.Utils.Achivments.asmdef.meta (100%) delete mode 100644 Achivments/AchivmentData.cs delete mode 100644 Achivments/AchivmentDefinition.cs delete mode 100644 Achivments/AchivmentManager.cs delete mode 100644 Achivments/IAchivmentCallbackReciever.cs diff --git a/Achivments.meta b/Achievments.meta similarity index 100% rename from Achivments.meta rename to Achievments.meta diff --git a/Achievments/AchievmentManager.cs b/Achievments/AchievmentManager.cs new file mode 100644 index 0000000..64f26cd --- /dev/null +++ b/Achievments/AchievmentManager.cs @@ -0,0 +1,341 @@ +using System.Collections; +using System.Collections.Generic; +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.AddressableAssets; +using System.Runtime.CompilerServices; +using UnityEditor; + +namespace NEG.Utils.Achievments +{ + using AchievmentTypes; + + public class AchievmentManager + { + public class Builder + { + public const string DefaultAchivmentsConfigLabel = "Achivments"; + + private AchievmentManager manager = new AchievmentManager(); + private IAchivmentStorage storage; + + public static Builder FromDefaultConfig() + { + return FromLabeledConfig(DefaultAchivmentsConfigLabel); + } + + public static Builder FromLabeledConfig(string label) + { + var builder = new Builder(); + + var handle = Addressables.LoadAssetsAsync((IEnumerable)new string[] { label }, delegate { }, Addressables.MergeMode.Union, false); + + var configs = handle.WaitForCompletion(); + + foreach (var config in configs) + { + config.Apply(builder); + } + + foreach (var config in configs) + { + config.ApplyLast(builder); + } + + Addressables.Release(handle); + + return builder; + } + + public Builder WithLabeledDefinitions(string label) + { + var handle = Addressables.LoadAssetsAsync((IEnumerable)new string[] { label }, delegate { }, Addressables.MergeMode.Union, false); + + var achivmentCollections = handle.WaitForCompletion(); + + foreach (var achivmentCollection in achivmentCollections) + WithDefinitionsFrom(achivmentCollection); + + return this; + } + + public Builder WithDefinitionsFrom(AchivmentDefinitionCollection collection) + { + foreach (var def in collection.Achivments) + { + manager.RegisterAchivment(def); + } + + return this; + } + + public Builder LoadedFrom(IAchivmentStorage storageIn) + { + if (storage != null) + { + throw new ApplicationException("Cannot Load achivment data from multiple storage instances"); + } + + this.storage = storageIn; + + return this; + } + + public Builder WithCallbackReciever(IAchievmentCallbackReciever callbackReciever) + { + manager.AddCallbackReciever(callbackReciever); + return this; + } + + public AchievmentManager Build() + { + //TODO + /*if (storage != null) + { + manager.LoadFrom(storage); + }*/ + return manager; + } + } + + public delegate void AchievmentCompletedCallback(AchievmentData achivment); + public delegate void AchievmentStateChangedCallback(AchievmentData achivment); + + public event AchievmentCompletedCallback AchievmentCompleted; + public event AchievmentStateChangedCallback AchievmentStateChanged; + + private Dictionary definitionCache; + private Dictionary dataCache; + + private AchievmentManager() + { + definitionCache = new Dictionary(); + dataCache = new Dictionary(); + } + + private void RegisterAchivment(AchievmentDefinition definition) + { + if (!definitionCache.ContainsKey(definition.Id)) + { + definitionCache.Add(definition.Id, definition); + dataCache.Add(definition, definition.Construct()); + } + else + { + Debug.LogWarning($"Duplicate Achivment with ID: {definition.Id}"); + } + } + + /*private void LoadFrom(IAchivmentStorage achivmentStorage) + { + foreach (var entry in definitionCache) + { + var storedProgress = achivmentStorage.GetStoredAchivmentProgress(entry.Key); + + dataCache[entry.Value].ProgressLeft = storedProgress; + } + }*/ + + public void AddCallbackRecievers(IEnumerable initialCallbacks) + { + foreach (var callback in initialCallbacks) + { + AddCallbackReciever(callback); + } + } + + public void AddCallbackReciever(IAchievmentCallbackReciever callback) + { + AchievmentCompleted += callback.AchievmentCompleted; + AchievmentStateChanged += callback.AchievmentStateChanged; + } + + public void RemoveCallbackReciever(IAchievmentCallbackReciever callback) + { + AchievmentCompleted -= callback.AchievmentCompleted; + AchievmentStateChanged -= callback.AchievmentStateChanged; + } + + #region Achievment Manipulation (Sets, Gets) + + /// + /// Returns if an achivment at a given id is completed + /// + /// + /// + public bool IsCompleted(string id) + { + return GetAchievmentForId(id).IsCompleted; + } + + #region Toggle + /// + /// Sets a as completed, after which sends , also if the achievment is completed sends a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public void SetToggleAchivment(string id) + { + ManipulateAchievment(id, (achievment) => achievment.CompletionState = true); + } + + /// + /// Gets a completion state from a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public bool GetToggleState(string id) + { + return GetAchievmentForId(id).CompletionState; + } + #endregion + + #region Int + /// + /// Sets progress of a given to , after which sends , also if the achievment is completed sends a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an . + ///
+ /// + public void SetIntProgress(string id, int progress) + { + ManipulateAchievment(id, (achievment) => achievment.CurrentProgress = progress); + } + + /// + /// Changes progress of a given by , after which sends , also if the achievment is completed sends a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public void CangeIntProgress(string id, int delta) + { + ManipulateAchievment(id, (achievment) => achievment.CurrentProgress += delta); + } + + /// + /// Gets current progress from a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public int GetIntProgress(string id) + { + return GetAchievmentForId(id).CurrentProgress; + } + #endregion + + #region Float + /// + /// Sets progress of a given to , after which sends , also if the achievment is completed sends a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public void SetFloatProgress(string id, float progress) + { + ManipulateAchievment(id, (achievment) => achievment.CurrentProgress = progress); + } + + /// + /// Changes progress of a given by , after which sends , also if the achievment is completed sends a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public void CangeFloatProgress(string id, float delta) + { + ManipulateAchievment(id, (achievment) => achievment.CurrentProgress += delta); + } + + /// + /// Gets current progress from a .
+ /// If there is no achievment at a given id throws an . If achievment at a given id is of a wrong tupe throws an + ///
+ /// + public float GetFloatProgress(string id) + { + return GetAchievmentForId(id).CurrentProgress; + } + #endregion + #endregion + + /// + /// Returns an achievment of type under + /// + /// Type of the achievment + /// Id of requested achievment + /// throws an if either there is no achievment under id or achievment under id is of a different type + public T GetAchievmentForId(string id) where T : AchievmentData + { + return CheckAchievmentType(GetAchievmentForId(id)); + } + + /// + /// Returns an achievment under + /// + /// Id of requested achievment + /// throws an if there is no achievment under id + public AchievmentData GetAchievmentForId(string id) + { + var def = definitionCache.GetValueOrDefault(id); + if (def != null) + { + return dataCache[def]; + } + else + { + throw new ApplicationException($"Invalid achivment id {id}"); + } + } + + private T CheckAchievmentType(AchievmentData data) where T : AchievmentData + { + if (data is not T convetred) + { + throw new ApplicationException($"Attempting to perform an operation on an invalid achievment type. Expected {typeof(T)} got {data.GetType()}"); + } + return convetred; + } + + /// + /// + /// + /// + /// + /// Action to perform on the achievment + private void ManipulateAchievment(string id, Action manipulation) where T : AchievmentData + { + var data = GetAchievmentForId(id); + + if (CheckNotCompleted(data)) + { + return; + } + + manipulation(data); + + SendUpdateCallbacks(data); + } + + /// + /// Helper method to print a warning if an achievment is already completed + /// + /// + /// Completion state + private bool CheckNotCompleted(AchievmentData data) + { + if (data.IsCompleted) + { + Debug.LogWarning($"Achievment already completed: {data.Achivment.Id}"); + } + return data.IsCompleted; + } + + private void SendUpdateCallbacks(AchievmentData data) + { + AchievmentStateChanged?.Invoke(data); + + if (data.IsCompleted) + { + AchievmentCompleted?.Invoke(data); + } + } + } +} \ No newline at end of file diff --git a/Achivments/AchivmentManager.cs.meta b/Achievments/AchievmentManager.cs.meta similarity index 83% rename from Achivments/AchivmentManager.cs.meta rename to Achievments/AchievmentManager.cs.meta index fc0282b..64e574c 100644 --- a/Achivments/AchivmentManager.cs.meta +++ b/Achievments/AchievmentManager.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 841f326ebfd59e646835bf81432d3ae4 +guid: 7339f725e382e4b4bab7db6d7cc14b30 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Achivments/Backend.meta b/Achievments/AchievmentTypes.meta similarity index 77% rename from Achivments/Backend.meta rename to Achievments/AchievmentTypes.meta index 4ba2000..bb52672 100644 --- a/Achivments/Backend.meta +++ b/Achievments/AchievmentTypes.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 48ec3460d89c2f144827761002d7f4d9 +guid: 79e626bf8b94e5f4d813912f9b1d304e folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Achievments/AchievmentTypes/AchievmentData.cs b/Achievments/AchievmentTypes/AchievmentData.cs new file mode 100644 index 0000000..86a154d --- /dev/null +++ b/Achievments/AchievmentTypes/AchievmentData.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + public abstract class AchievmentData + { + public AchievmentDefinition Achivment { get; private set; } + + public abstract bool IsCompleted { get; } + + public AchievmentData(AchievmentDefinition achivment) + { + Achivment = achivment; + } + } +} \ No newline at end of file diff --git a/Achivments/AchivmentData.cs.meta b/Achievments/AchievmentTypes/AchievmentData.cs.meta similarity index 83% rename from Achivments/AchivmentData.cs.meta rename to Achievments/AchievmentTypes/AchievmentData.cs.meta index b67c171..5fb4884 100644 --- a/Achivments/AchivmentData.cs.meta +++ b/Achievments/AchievmentTypes/AchievmentData.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: fad96d35cce2d3e469d300e6e48a048a +guid: 1f39500a9deabad43b87bc76122646fc MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Achievments/AchievmentTypes/AchievmentDefinition.cs b/Achievments/AchievmentTypes/AchievmentDefinition.cs new file mode 100644 index 0000000..b43c4d3 --- /dev/null +++ b/Achievments/AchievmentTypes/AchievmentDefinition.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json.Linq; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + public abstract class AchievmentDefinition : ScriptableObject + { + [field: SerializeField] + public string Id { get; private set; } + + public abstract AchievmentData Construct(); + } +} \ No newline at end of file diff --git a/Achivments/AchivmentDefinition.cs.meta b/Achievments/AchievmentTypes/AchievmentDefinition.cs.meta similarity index 83% rename from Achivments/AchivmentDefinition.cs.meta rename to Achievments/AchievmentTypes/AchievmentDefinition.cs.meta index aaaa367..1d52a8a 100644 --- a/Achivments/AchivmentDefinition.cs.meta +++ b/Achievments/AchievmentTypes/AchievmentDefinition.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f9bd42dd58472044b8ecc0d69caa7da8 +guid: 4aef60a6b4e41e243845a476862049e1 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Achievments/AchievmentTypes/FloatAchievmentData.cs b/Achievments/AchievmentTypes/FloatAchievmentData.cs new file mode 100644 index 0000000..27a43ed --- /dev/null +++ b/Achievments/AchievmentTypes/FloatAchievmentData.cs @@ -0,0 +1,35 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + public class FloatAchievmentData : AchievmentData + { + public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired; + + public float CurrentProgress + { + get => currentProgress; + internal set + { + if (Def.Clamped) + { + value = Mathf.Max(value, Def.LowerBound); + } + currentProgress = Mathf.Min(value, Def.ProgressRequired); + } + } + + public float ProgressLeft => Def.ProgressRequired - CurrentProgress; + + private FloatAchievmentDefinition Def => (FloatAchievmentDefinition)Achivment; + + private float currentProgress; + + public FloatAchievmentData(FloatAchievmentDefinition def) : base(def) + { + currentProgress = def.InitialProgress; + } + } +} \ No newline at end of file diff --git a/Achievments/AchievmentTypes/FloatAchievmentData.cs.meta b/Achievments/AchievmentTypes/FloatAchievmentData.cs.meta new file mode 100644 index 0000000..8d1afc2 --- /dev/null +++ b/Achievments/AchievmentTypes/FloatAchievmentData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32572809c0644434d8e64878a3c22f0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs b/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs new file mode 100644 index 0000000..19dac84 --- /dev/null +++ b/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + [CreateAssetMenu(menuName = "Achievments/Float Achievment")] + public class FloatAchievmentDefinition : AchievmentDefinition + { + [field: Tooltip("Amount of progress required for completion, required to be at leas 1, otherwise would be considered completed from the beginning")] + [field: Min(0)] + [field: SerializeField] + public float ProgressRequired { get; private set; } = 1; + + [field: SerializeField] + public float InitialProgress { get; private set; } = 0; + + [field: SerializeField] + public bool Clamped { get; private set; } = false; + + public float LowerBound { get; private set; } = 0; + + + public override AchievmentData Construct() + { + return new FloatAchievmentData(this); + } + } +} \ No newline at end of file diff --git a/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs.meta b/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs.meta new file mode 100644 index 0000000..4a7def5 --- /dev/null +++ b/Achievments/AchievmentTypes/FloatAchievmentDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d7270d5452c9b04ca07ef43a491a18d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achievments/AchievmentTypes/IntAchievmentData.cs b/Achievments/AchievmentTypes/IntAchievmentData.cs new file mode 100644 index 0000000..94e900a --- /dev/null +++ b/Achievments/AchievmentTypes/IntAchievmentData.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization.Formatters; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + public class IntAchievmentData : AchievmentData + { + public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired; + + public int CurrentProgress + { + get => currentProgress; + internal set + { + if (Def.Clamped) + { + value = Mathf.Max(value, Def.LowerBound); + } + currentProgress = Mathf.Min(value, Def.ProgressRequired); + } + } + + public int ProgressLeft => Def.ProgressRequired - CurrentProgress; + + private IntAchievmentDefinition Def => (IntAchievmentDefinition)Achivment; + + private int currentProgress; + + public IntAchievmentData(IntAchievmentDefinition def) : base(def) + { + currentProgress = def.InitialProgress; + } + } +} \ No newline at end of file diff --git a/Achievments/AchievmentTypes/IntAchievmentData.cs.meta b/Achievments/AchievmentTypes/IntAchievmentData.cs.meta new file mode 100644 index 0000000..52c3e80 --- /dev/null +++ b/Achievments/AchievmentTypes/IntAchievmentData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0a121b6e6fa8ecc45ab4506c15e5f46e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achievments/AchievmentTypes/IntAchievmentDefinition.cs b/Achievments/AchievmentTypes/IntAchievmentDefinition.cs new file mode 100644 index 0000000..aa87274 --- /dev/null +++ b/Achievments/AchievmentTypes/IntAchievmentDefinition.cs @@ -0,0 +1,27 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + [CreateAssetMenu(menuName = "Achievments/Int Achievment")] + public class IntAchievmentDefinition : AchievmentDefinition + { + [field: Tooltip("Amount of progress required for completion, required to be at leas 1, otherwise would be considered completed from the beginning")] + [field: SerializeField] + public int ProgressRequired { get; private set; } = 1; + + [field: SerializeField] + public int InitialProgress { get; private set; } = 0; + + [field: SerializeField] + public bool Clamped { get; private set; } = false; + + public int LowerBound { get; private set; } = 0; + + public override AchievmentData Construct() + { + return new IntAchievmentData(this); + } + } +} \ No newline at end of file diff --git a/Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta b/Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta new file mode 100644 index 0000000..16c6c30 --- /dev/null +++ b/Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5318fea685aa56646a3310c38a9a9bac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achievments/AchievmentTypes/ToggleAchievmentData.cs b/Achievments/AchievmentTypes/ToggleAchievmentData.cs new file mode 100644 index 0000000..c0b9dfa --- /dev/null +++ b/Achievments/AchievmentTypes/ToggleAchievmentData.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + public class ToggleAchievmentData : AchievmentData + { + public override bool IsCompleted => CompletionState; + + public bool CompletionState { get; internal set; } = false; + + public ToggleAchievmentData(ToggleAchievmentDefinition def) : base(def) + { + + } + } +} diff --git a/Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta b/Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta new file mode 100644 index 0000000..84bacbf --- /dev/null +++ b/Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e0806da00902994f9aeb26d295956f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs b/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs new file mode 100644 index 0000000..25fd6f0 --- /dev/null +++ b/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments.AchievmentTypes +{ + [CreateAssetMenu(menuName = "Achievments/Toggle Achievment")] + public class ToggleAchievmentDefinition : AchievmentDefinition + { + public override AchievmentData Construct() + { + return new ToggleAchievmentData(this); + } + } +} diff --git a/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs.meta b/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs.meta new file mode 100644 index 0000000..c10231a --- /dev/null +++ b/Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 608c7e921b8b16b42919fc6f55b67fcb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Achivments/AchivmentDefinitionCollection.cs b/Achievments/AchivmentDefinitionCollection.cs similarity index 59% rename from Achivments/AchivmentDefinitionCollection.cs rename to Achievments/AchivmentDefinitionCollection.cs index 9feb592..fb804d6 100644 --- a/Achivments/AchivmentDefinitionCollection.cs +++ b/Achievments/AchivmentDefinitionCollection.cs @@ -2,12 +2,14 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -namespace NEG.Utils.Achivments +namespace NEG.Utils.Achievments { + using AchievmentTypes; + [CreateAssetMenu(menuName = "Achivments/Collection")] public class AchivmentDefinitionCollection : ScriptableObject { [field: SerializeField] - public List Achivments { get; private set; } = new List(); + public List Achivments { get; private set; } = new List(); } } \ No newline at end of file diff --git a/Achivments/AchivmentDefinitionCollection.cs.meta b/Achievments/AchivmentDefinitionCollection.cs.meta similarity index 100% rename from Achivments/AchivmentDefinitionCollection.cs.meta rename to Achievments/AchivmentDefinitionCollection.cs.meta diff --git a/Achivments/AchivmentManagerConfig.cs b/Achievments/AchivmentManagerConfig.cs similarity index 79% rename from Achivments/AchivmentManagerConfig.cs rename to Achievments/AchivmentManagerConfig.cs index 19402d8..4815d84 100644 --- a/Achivments/AchivmentManagerConfig.cs +++ b/Achievments/AchivmentManagerConfig.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -namespace NEG.Utils.Achivments +namespace NEG.Utils.Achievments { [CreateAssetMenu(menuName = "Achivments/BaseConfig")] public class AchivmentManagerConfig : ScriptableObject, IAchivmentManagerConfig @@ -12,12 +12,12 @@ namespace NEG.Utils.Achivments [field: SerializeField] public string AchivmentCollectionAssetLabel { get; private set; } = DefaultAchivmentsCollectionLabel; - public void Apply(AchivmentManager.Builder builder) + public void Apply(AchievmentManager.Builder builder) { builder.WithLabeledDefinitions(AchivmentCollectionAssetLabel); } - public void ApplyLast(AchivmentManager.Builder builder) + public void ApplyLast(AchievmentManager.Builder builder) { } diff --git a/Achivments/AchivmentManagerConfig.cs.meta b/Achievments/AchivmentManagerConfig.cs.meta similarity index 100% rename from Achivments/AchivmentManagerConfig.cs.meta rename to Achievments/AchivmentManagerConfig.cs.meta diff --git a/Achievments/IAchievmentCallbackReciever.cs b/Achievments/IAchievmentCallbackReciever.cs new file mode 100644 index 0000000..6c6a87d --- /dev/null +++ b/Achievments/IAchievmentCallbackReciever.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace NEG.Utils.Achievments +{ + using AchievmentTypes; + + public interface IAchievmentCallbackReciever + { + /// + /// Called when an achivment is completed + /// + /// + void AchievmentCompleted(AchievmentData achivment); + + /// + /// Called when achivment progress changes + /// + /// + void AchievmentStateChanged(AchievmentData achivment); + } +} \ No newline at end of file diff --git a/Achivments/IAchivmentCallbackReciever.cs.meta b/Achievments/IAchievmentCallbackReciever.cs.meta similarity index 100% rename from Achivments/IAchivmentCallbackReciever.cs.meta rename to Achievments/IAchievmentCallbackReciever.cs.meta diff --git a/Achivments/IAchivmentManagerConfig.cs b/Achievments/IAchivmentManagerConfig.cs similarity index 58% rename from Achivments/IAchivmentManagerConfig.cs rename to Achievments/IAchivmentManagerConfig.cs index 10351e1..15628c9 100644 --- a/Achivments/IAchivmentManagerConfig.cs +++ b/Achievments/IAchivmentManagerConfig.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -namespace NEG.Utils.Achivments +namespace NEG.Utils.Achievments { public interface IAchivmentManagerConfig { @@ -10,12 +10,12 @@ namespace NEG.Utils.Achivments /// Used to Apply config data /// /// - void Apply(AchivmentManager.Builder builder); + void Apply(AchievmentManager.Builder builder); /// - /// Called after was called on every other config + /// Called after was called on every other config /// /// - void ApplyLast(AchivmentManager.Builder builder); + void ApplyLast(AchievmentManager.Builder builder); } } \ No newline at end of file diff --git a/Achivments/IAchivmentManagerConfig.cs.meta b/Achievments/IAchivmentManagerConfig.cs.meta similarity index 100% rename from Achivments/IAchivmentManagerConfig.cs.meta rename to Achievments/IAchivmentManagerConfig.cs.meta diff --git a/Achivments/IAchivmentStorage.cs b/Achievments/IAchivmentStorage.cs similarity index 85% rename from Achivments/IAchivmentStorage.cs rename to Achievments/IAchivmentStorage.cs index eade987..00f0799 100644 --- a/Achivments/IAchivmentStorage.cs +++ b/Achievments/IAchivmentStorage.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -namespace NEG.Utils.Achivments +namespace NEG.Utils.Achievments { public interface IAchivmentStorage { diff --git a/Achivments/IAchivmentStorage.cs.meta b/Achievments/IAchivmentStorage.cs.meta similarity index 100% rename from Achivments/IAchivmentStorage.cs.meta rename to Achievments/IAchivmentStorage.cs.meta diff --git a/Achivments/NEG.Utils.Achivments.asmdef b/Achievments/NEG.Utils.Achivments.asmdef similarity index 100% rename from Achivments/NEG.Utils.Achivments.asmdef rename to Achievments/NEG.Utils.Achivments.asmdef diff --git a/Achivments/NEG.Utils.Achivments.asmdef.meta b/Achievments/NEG.Utils.Achivments.asmdef.meta similarity index 100% rename from Achivments/NEG.Utils.Achivments.asmdef.meta rename to Achievments/NEG.Utils.Achivments.asmdef.meta diff --git a/Achivments/AchivmentData.cs b/Achivments/AchivmentData.cs deleted file mode 100644 index 274abbd..0000000 --- a/Achivments/AchivmentData.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Newtonsoft.Json.Linq; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace NEG.Utils.Achivments -{ - public class AchivmentData - { - public AchivmentDefinition Achivment { get; private set; } - - public int ProgressLeft { get; internal set; } - - public bool IsCompleted => ProgressLeft <= 0; - - public AchivmentData(AchivmentDefinition achivment, int progressLeft) - { - Achivment = achivment; - ProgressLeft = progressLeft; - } - } -} \ No newline at end of file diff --git a/Achivments/AchivmentDefinition.cs b/Achivments/AchivmentDefinition.cs deleted file mode 100644 index 703d34d..0000000 --- a/Achivments/AchivmentDefinition.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Newtonsoft.Json.Linq; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace NEG.Utils.Achivments -{ - [CreateAssetMenu(menuName = "Achivments/AchivmentDefinition")] - public class AchivmentDefinition : ScriptableObject - { - public JToken AdditionalData - { - get - { - additionalData ??= JObject.Parse(additionalDataInitializer); - return additionalData; - } - } - - [field: SerializeField] - public string Id { get; private set; } - - [field: Tooltip("Amount of progress required for completion, required to be at leas 1, otherwise would be considered completed from the beginning")] - [field: Min(1)] - [field: SerializeField] - public int ProgressRequired { get; private set; } = 1; - - [SerializeField] - [Tooltip("Temporary until json editor is a thing")] - private string additionalDataInitializer; - - private JToken additionalData; - } -} \ No newline at end of file diff --git a/Achivments/AchivmentManager.cs b/Achivments/AchivmentManager.cs deleted file mode 100644 index 0367b35..0000000 --- a/Achivments/AchivmentManager.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System; -using System.Linq; -using UnityEngine; -using UnityEngine.AddressableAssets; -using System.Runtime.CompilerServices; -using UnityEditor; - -namespace NEG.Utils.Achivments -{ - public class AchivmentManager - { - public class Builder - { - public const string DefaultAchivmentsConfigLabel = "Achivments"; - - private AchivmentManager manager = new AchivmentManager(); - private IAchivmentStorage storage; - - public static Builder FromDefaultConfig() - { - return FromLabeledConfig(DefaultAchivmentsConfigLabel); - } - - public static Builder FromLabeledConfig(string label) - { - var builder = new Builder(); - - var handle = Addressables.LoadAssetsAsync((IEnumerable)new string[] { label }, delegate { }, Addressables.MergeMode.Union, false); - - var configs = handle.WaitForCompletion(); - - foreach (var config in configs) - { - config.Apply(builder); - } - - foreach (var config in configs) - { - config.ApplyLast(builder); - } - - Addressables.Release(handle); - - return builder; - } - - public Builder WithLabeledDefinitions(string label) - { - var handle = Addressables.LoadAssetsAsync((IEnumerable)new string[] { label }, delegate { }, Addressables.MergeMode.Union, false); - - var achivmentCollections = handle.WaitForCompletion(); - - foreach (var achivmentCollection in achivmentCollections) - WithDefinitionsFrom(achivmentCollection); - - return this; - } - - public Builder WithDefinitionsFrom(AchivmentDefinitionCollection collection) - { - foreach (var def in collection.Achivments) - { - manager.RegisterAchivment(def); - } - - return this; - } - - public Builder LoadedFrom(IAchivmentStorage storageIn) - { - if (storage != null) - { - throw new ApplicationException("Cannot Load achivment data from multiple storage instances"); - } - - this.storage = storageIn; - - return this; - } - - public Builder WithCallbackReciever(IAchivmentCallbackReciever callbackReciever) - { - manager.AddCallbackReciever(callbackReciever); - return this; - } - - public AchivmentManager Build() - { - if (storage != null) - { - manager.LoadFrom(storage); - } - return manager; - } - } - - public delegate void AchivmentSetCallback(AchivmentData achivment); - public delegate void AchivmentProgressSetCallback(AchivmentData achivment, int progressLeft); - - public event AchivmentSetCallback AchivmentSet; - public event AchivmentProgressSetCallback AchivmentProgressSet; - - private Dictionary definitionCache; - private Dictionary dataCache; - - private AchivmentManager() - { - definitionCache = new Dictionary(); - dataCache = new Dictionary(); - } - - private void RegisterAchivment(AchivmentDefinition definition) - { - if (!definitionCache.ContainsKey(definition.Id)) - { - definitionCache.Add(definition.Id, definition); - dataCache.Add(definition, new AchivmentData(definition, definition.ProgressRequired)); - } - else - { - Debug.LogWarning($"Duplicate Achivment with ID: {definition.Id}"); - } - } - - private void LoadFrom(IAchivmentStorage achivmentStorage) - { - foreach (var entry in definitionCache) - { - var storedProgress = achivmentStorage.GetStoredAchivmentProgress(entry.Key); - - dataCache[entry.Value].ProgressLeft = storedProgress; - } - } - - public void AddCallbackRecievers(IEnumerable initialCallbacks) - { - foreach (var callback in initialCallbacks) - { - AddCallbackReciever(callback); - } - } - - public void AddCallbackReciever(IAchivmentCallbackReciever callback) - { - AchivmentSet += callback.SetAchivment; - AchivmentProgressSet += callback.SetAchivmentProgress; - } - - public void RemoveCallbackReciever(IAchivmentCallbackReciever callback) - { - AchivmentSet -= callback.SetAchivment; - AchivmentProgressSet -= callback.SetAchivmentProgress; - } - - public void SetAchivment(string id) - { - var data = GetAchivmentForId(id); - data.ProgressLeft = 0; - AchivmentSet?.Invoke(data); - } - - public void AddProgress(string id, int amount) - { - var data = GetAchivmentForId(id); - if (data.IsCompleted) - { - return; - } - data.ProgressLeft = Mathf.Max(data.ProgressLeft - amount, 0); - AchivmentProgressSet?.Invoke(data, data.Achivment.ProgressRequired - data.ProgressLeft); - - if (data.IsCompleted) - { - AchivmentSet?.Invoke(data); - } - } - - private AchivmentData GetAchivmentForId(string id) - { - var def = definitionCache.GetValueOrDefault(id); - if (def != null) - { - return dataCache[def]; - } - else - { - throw new ApplicationException($"Invalid achivment id {id}"); - } - } - } -} \ No newline at end of file diff --git a/Achivments/IAchivmentCallbackReciever.cs b/Achivments/IAchivmentCallbackReciever.cs deleted file mode 100644 index e57defb..0000000 --- a/Achivments/IAchivmentCallbackReciever.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace NEG.Utils.Achivments -{ - public interface IAchivmentCallbackReciever - { - /// - /// Called when an achivment is completed - /// - /// - /// - void SetAchivment(AchivmentData achivment); - - /// - /// Called when achivment progress changes - /// - /// - /// Current achivment progress, equal to - - void SetAchivmentProgress(AchivmentData achivment, int progress); - } -} \ No newline at end of file