achivments #1
8
Achievments.meta
Normal file
8
Achievments.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff9bb206aea50d14997771b9a0cc2b04
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
190
Achievments/Achievment.cs
Normal file
190
Achievments/Achievment.cs
Normal file
@ -0,0 +1,190 @@
|
||||
using NEG.Utils.Achievments.AchievmentTypes;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
/// <summary>
|
||||
/// Static utility for achievment managment
|
||||
/// </summary>
|
||||
public static class Achievment
|
||||
{
|
||||
public static AchievmentManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = AchievmentManager.Builder.FromLabeledConfig(ConfigLabel)
|
||||
.WithLabeledBackend(BackendLabel)
|
||||
.Build();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static string BackendLabel
|
||||
{
|
||||
get => backendLabel;
|
||||
set
|
||||
{
|
||||
if(instance != null)
|
||||
{
|
||||
//Log + Quit helps debug builds
|
||||
Debug.LogError("Achievments - Cannot set backend label, Managed already created");
|
||||
Application.Quit(1);
|
||||
}
|
||||
if (backendLabel != null)
|
||||
{
|
||||
//Log + Quit helps debug builds
|
||||
Debug.LogError("Multiple AchievmentBackends enabled, this is not allowed");
|
||||
Application.Quit(1);
|
||||
}
|
||||
backendLabel = value;
|
||||
}
|
||||
}
|
||||
private static string backendLabel;
|
||||
|
||||
/// <summary>
|
||||
/// You shouldn't have any reason to change this
|
||||
/// Used for tests.
|
||||
/// </summary>
|
||||
public static string ConfigLabel
|
||||
{
|
||||
private get => configLabel;
|
||||
set => configLabel = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You shouldn't have any reason to change this
|
||||
/// Used for tests.
|
||||
/// </summary>
|
||||
private static string configLabel = "Achivments";
|
||||
|
||||
private static AchievmentManager instance;
|
||||
|
||||
#region Achievment Manipulation (Sets, Gets)
|
||||
|
||||
/// <summary>
|
||||
/// Returns if an achivment at a given id is completed
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <seealso cref="AchievmentManager.IsCompleted(string)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id</remarks>
|
||||
public static bool IsCompleted(string id)
|
||||
{
|
||||
return Instance.IsCompleted(id);
|
||||
}
|
||||
|
||||
#region Toggle
|
||||
/// <summary>
|
||||
/// Sets a <see cref="ToggleAchievmentData"/> as completed. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.SetToggleAchivment(string)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool SetToggleAchivment(string id)
|
||||
{
|
||||
return Instance.SetToggleAchivment(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a completion state from a <see cref="ToggleAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.GetToggleState(string)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool GetToggleState(string id)
|
||||
{
|
||||
return Instance.GetToggleState(id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Int
|
||||
/// <summary>
|
||||
/// Sets progress of a given <see cref="IntAchievmentData"/> to <paramref name="progress"/> <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="IntAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.SetIntProgress(string, int)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool SetIntProgress(string id, int progress)
|
||||
{
|
||||
return Instance.SetIntProgress(id, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes progress of a given <see cref="IntAchievmentData"/> by <paramref name="delta"/><br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="IntAchievmentDefinition"/>\
|
||||
/// <seealso cref="AchievmentManager.ChangeIntProgress(string, int)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool ChangeIntProgress(string id, int delta)
|
||||
{
|
||||
return Instance.ChangeIntProgress(id, delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current progress from a <see cref="IntAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.GetIntProgress(string)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static int GetIntProgress(string id)
|
||||
{
|
||||
return Instance.GetIntProgress(id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Float
|
||||
/// <summary>
|
||||
/// Sets progress of a given <see cref="FloatAchievmentData"/> to <paramref name="progress"/><br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.SetFloatProgress(string, float)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool SetFloatProgress(string id, float progress)
|
||||
{
|
||||
return Instance.SetFloatProgress(id, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes progress of a given <see cref="FloatAchievmentData"/> by <paramref name="delta"/><br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.ChangeFloatProgress(string, float)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static bool ChangeFloatProgress(string id, float delta)
|
||||
{
|
||||
return Instance.ChangeFloatProgress(id, delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current progress from a <see cref="FloatAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <seealso cref="AchievmentManager.GetFloatProgress(string)"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public static float GetFloatProgress(string id)
|
||||
{
|
||||
return Instance.GetFloatProgress(id);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Test Api
|
||||
/// <summary>
|
||||
/// You shouldn't have any reason to use this <br/>
|
||||
/// Use at your own risk, may cause unexpected behaviour <br/>
|
||||
/// Used for tests
|
||||
/// </summary>
|
||||
public static void NullifyInstance()
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
11
Achievments/Achievment.cs.meta
Normal file
11
Achievments/Achievment.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 696bafd4c06b0a8458f008103441ea7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
44
Achievments/AchievmentException.cs
Normal file
44
Achievments/AchievmentException.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
public class AchievmentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of related achievment
|
||||
/// </summary>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||
public string Id { get; private set; }
|
||||
|
||||
public AchievmentException(string message, string achievmentId) : base(message)
|
||||
{
|
||||
Id = achievmentId;
|
||||
}
|
||||
}
|
||||
|
||||
public class AchievmentTypeException : AchievmentException
|
||||
{
|
||||
/// <summary>
|
||||
/// Expected achievment type under <see cref="AchievmentException.Id"/>
|
||||
/// </summary>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||
public Type Expected { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Actual achievment type under <see cref="AchievmentException.Id"/>
|
||||
/// </summary>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||
public Type Actual { get; private set; }
|
||||
|
||||
public AchievmentTypeException(string message, string achievmentId, Type expectedType, Type actualType) : base(message, achievmentId)
|
||||
{
|
||||
Expected = expectedType;
|
||||
Actual = actualType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Achievments/AchievmentException.cs.meta
Normal file
11
Achievments/AchievmentException.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 241344322b9771049b6962e48ac98085
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
366
Achievments/AchievmentManager.cs
Normal file
366
Achievments/AchievmentManager.cs
Normal file
@ -0,0 +1,366 @@
|
||||
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 IAchievmentBackend backend;
|
||||
|
||||
public static Builder FromDefaultConfig()
|
||||
{
|
||||
return FromLabeledConfig(DefaultAchivmentsConfigLabel);
|
||||
}
|
||||
|
||||
public static Builder FromLabeledConfig(string label)
|
||||
{
|
||||
var builder = new Builder();
|
||||
|
||||
var handle = Addressables.LoadAssetsAsync<IAchivmentManagerConfig>((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 WithDefinitionsFrom(AchievmentManagerConfig collection)
|
||||
{
|
||||
foreach (var def in collection.Achivments)
|
||||
{
|
||||
manager.RegisterAchivment(def);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder WithLabeledBackend(string label)
|
||||
|
BitterSmile
commented
no check for empty label no check for empty label
Ghost
commented
empty meaning null or empty meaning label with nothing assigned? empty meaning null or empty meaning label with nothing assigned?
BitterSmile
commented
you check for nothing, why even bother questioning you check for nothing, why even bother questioning
|
||||
{
|
||||
var backendConfigHandle = Addressables.LoadAssetAsync<IAchievmentBackendConfig>(label);
|
||||
|
||||
var backendConfig = backendConfigHandle.WaitForCompletion();
|
||||
|
||||
WithBackend(backendConfig.ConstructBackend());
|
||||
|
||||
Addressables.Release(backendConfigHandle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder WithBackend(IAchievmentBackend backendIn)
|
||||
{
|
||||
if (backend != null)
|
||||
{
|
||||
throw new ApplicationException("There can only be one Achievment Backend at a time");
|
||||
}
|
||||
|
||||
this.backend = backendIn;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder WithCallbackReciever(IAchievmentCallbackReciever callbackReciever)
|
||||
{
|
||||
manager.AddCallbackReciever(callbackReciever);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AchievmentManager Build()
|
||||
{
|
||||
if (backend != null)
|
||||
{
|
||||
manager.InitBackend(backend);
|
||||
}else
|
||||
{
|
||||
Debug.LogWarning("No AchievmentBackend selected. Is this intended?");
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void AchievmentCompletedCallback(AchievmentData achivment);
|
||||
public delegate void AchievmentStateChangedCallback(AchievmentData achivment);
|
||||
|
||||
public event AchievmentCompletedCallback AchievmentCompleted;
|
||||
public event AchievmentStateChangedCallback AchievmentStateChanged;
|
||||
|
||||
private Dictionary<string, AchievmentDefinition> definitionCache;
|
||||
private Dictionary<AchievmentDefinition, AchievmentData> dataCache;
|
||||
|
||||
private IAchievmentBackend activeBackend;
|
||||
|
||||
private AchievmentManager()
|
||||
{
|
||||
definitionCache = new Dictionary<string, AchievmentDefinition>();
|
||||
dataCache = new Dictionary<AchievmentDefinition, AchievmentData>();
|
||||
}
|
||||
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a backend syncing achievments data with it and redistering it as a callback reciever
|
||||
/// </summary>
|
||||
/// <remarks>Resets all achievments data</remarks>
|
||||
private void InitBackend(IAchievmentBackend achievmentBackend)
|
||||
{
|
||||
activeBackend = achievmentBackend;
|
||||
foreach (var definition in definitionCache.Values)
|
||||
{
|
||||
var storedProgress = achievmentBackend.GetStoredAchivment(definition);
|
||||
|
||||
if (storedProgress != null)
|
||||
{
|
||||
dataCache[definition] = storedProgress;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataCache[definition] = definition.Construct();
|
||||
}
|
||||
}
|
||||
AddCallbackReciever(achievmentBackend);
|
||||
}
|
||||
|
||||
public void AddCallbackRecievers(IEnumerable<IAchievmentCallbackReciever> 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)
|
||||
|
||||
/// <summary>
|
||||
/// Returns if an achivment at a given id is completed
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id</remarks>
|
||||
public bool IsCompleted(string id)
|
||||
{
|
||||
return GetAchievmentForId(id).IsCompleted;
|
||||
}
|
||||
|
||||
#region Toggle
|
||||
/// <summary>
|
||||
/// Sets a <see cref="ToggleAchievmentData"/> as completed, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool SetToggleAchivment(string id)
|
||||
{
|
||||
return ManipulateAchievment<ToggleAchievmentData>(id, (achievment) => achievment.CompletionState = true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a completion state from a <see cref="ToggleAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool GetToggleState(string id)
|
||||
{
|
||||
return GetAchievmentForId<ToggleAchievmentData>(id).CompletionState;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Int
|
||||
/// <summary>
|
||||
/// Sets progress of a given <see cref="IntAchievmentData"/> to <paramref name="progress"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="IntAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool SetIntProgress(string id, int progress)
|
||||
{
|
||||
return ManipulateAchievment<IntAchievmentData>(id, (achievment) => achievment.CurrentProgress = progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes progress of a given <see cref="IntAchievmentData"/> by <paramref name="delta"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="IntAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool ChangeIntProgress(string id, int delta)
|
||||
{
|
||||
return ManipulateAchievment<IntAchievmentData>(id, (achievment) => achievment.CurrentProgress += delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current progress from a <see cref="IntAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public int GetIntProgress(string id)
|
||||
{
|
||||
return GetAchievmentForId<IntAchievmentData>(id).CurrentProgress;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Float
|
||||
/// <summary>
|
||||
/// Sets progress of a given <see cref="FloatAchievmentData"/> to <paramref name="progress"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool SetFloatProgress(string id, float progress)
|
||||
{
|
||||
return ManipulateAchievment<FloatAchievmentData>(id, (achievment) => achievment.CurrentProgress = progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes progress of a given <see cref="FloatAchievmentData"/> by <paramref name="delta"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public bool ChangeFloatProgress(string id, float delta)
|
||||
{
|
||||
return ManipulateAchievment<FloatAchievmentData>(id, (achievment) => achievment.CurrentProgress += delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current progress from a <see cref="FloatAchievmentData"/>.<br/>
|
||||
/// </summary>
|
||||
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public float GetFloatProgress(string id)
|
||||
{
|
||||
return GetAchievmentForId<FloatAchievmentData>(id).CurrentProgress;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns an achievment of type <typeparamref name="T"/> under <paramref name="id"/>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the achievment</typeparam>
|
||||
/// <param name="id">Id of requested achievment</param>
|
||||
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||
public T GetAchievmentForId<T>(string id) where T : AchievmentData
|
||||
{
|
||||
return ValidateAchievmentType<T>(GetAchievmentForId(id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an achievment under <paramref name="id"/>
|
||||
/// </summary>
|
||||
/// <param name="id">Id of requested achievment</param>
|
||||
/// <remarks>throws an <see cref="ApplicationException"/> if there is no achievment under id</remarks>
|
||||
public AchievmentData GetAchievmentForId(string id)
|
||||
{
|
||||
var def = definitionCache.GetValueOrDefault(id);
|
||||
if (def != null)
|
||||
{
|
||||
return dataCache[def];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AchievmentException($"Invalid achivment id {id}", id);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateBackend()
|
||||
{
|
||||
activeBackend?.Update();
|
||||
}
|
||||
|
||||
private T ValidateAchievmentType<T>(AchievmentData data) where T : AchievmentData
|
||||
{
|
||||
if (data is not T convetred)
|
||||
{
|
||||
throw new AchievmentTypeException($"Attempting to perform an operation on an invalid achievment type. Expected {typeof(T)} got {data.GetType()}", data.Achievment.Id, typeof(T), data.GetType());
|
||||
}
|
||||
return convetred;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="manipulation">Action to perform on the achievment</param>
|
||||
private bool ManipulateAchievment<T>(string id, Action<T> manipulation) where T : AchievmentData
|
||||
{
|
||||
var data = GetAchievmentForId<T>(id);
|
||||
|
||||
if (CheckNotCompleted(data))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
manipulation(data);
|
||||
|
||||
SendUpdateCallbacks(data);
|
||||
|
||||
return data.IsCompleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to print a warning if an achievment is already completed
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns>Completion state</returns>
|
||||
private bool CheckNotCompleted(AchievmentData data)
|
||||
{
|
||||
if (data.IsCompleted)
|
||||
{
|
||||
Debug.LogWarning($"Achievment already completed: {data.Achievment.Id}");
|
||||
}
|
||||
return data.IsCompleted;
|
||||
}
|
||||
|
||||
private void SendUpdateCallbacks(AchievmentData data)
|
||||
{
|
||||
AchievmentStateChanged?.Invoke(data);
|
||||
|
||||
if (data.IsCompleted)
|
||||
{
|
||||
AchievmentCompleted?.Invoke(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentManager.cs.meta
Normal file
11
Achievments/AchievmentManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7339f725e382e4b4bab7db6d7cc14b30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Achievments/AchievmentManagerConfig.cs
Normal file
24
Achievments/AchievmentManagerConfig.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using NEG.Utils.Achievments.AchievmentTypes;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Achievments/Config/BaseConfig")]
|
||||
public class AchievmentManagerConfig : ScriptableObject, IAchivmentManagerConfig
|
||||
{
|
||||
[field: SerializeField]
|
||||
public List<AchievmentDefinition> Achivments { get; private set; } = new List<AchievmentDefinition>();
|
||||
|
||||
public void Apply(AchievmentManager.Builder builder)
|
||||
{
|
||||
builder.WithDefinitionsFrom(this);
|
||||
}
|
||||
|
||||
public void ApplyLast(AchievmentManager.Builder builder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentManagerConfig.cs.meta
Normal file
11
Achievments/AchievmentManagerConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88120b6e616164f489387a6a32a25dee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/AchievmentTypes.meta
Normal file
8
Achievments/AchievmentTypes.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79e626bf8b94e5f4d813912f9b1d304e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Achievments/AchievmentTypes/AchievmentData.cs
Normal file
21
Achievments/AchievmentTypes/AchievmentData.cs
Normal file
@ -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 Achievment { get; private set; }
|
||||
|
||||
public abstract bool IsCompleted { get; }
|
||||
|
||||
public AchievmentData(AchievmentDefinition achivment)
|
||||
{
|
||||
Achievment = achivment;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/AchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/AchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f39500a9deabad43b87bc76122646fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Achievments/AchievmentTypes/AchievmentDefinition.cs
Normal file
15
Achievments/AchievmentTypes/AchievmentDefinition.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/AchievmentDefinition.cs.meta
Normal file
11
Achievments/AchievmentTypes/AchievmentDefinition.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4aef60a6b4e41e243845a476862049e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Achievments/AchievmentTypes/FloatAchievmentData.cs
Normal file
40
Achievments/AchievmentTypes/FloatAchievmentData.cs
Normal file
@ -0,0 +1,40 @@
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Use to GET current progress
|
||||
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||
/// </summary>
|
||||
public float CurrentProgress
|
||||
{
|
||||
get => currentProgress;
|
||||
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)Achievment;
|
||||
|
||||
private float currentProgress;
|
||||
|
||||
public FloatAchievmentData(FloatAchievmentDefinition def) : base(def)
|
||||
{
|
||||
currentProgress = def.InitialProgress;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/FloatAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/FloatAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32572809c0644434d8e64878a3c22f0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
29
Achievments/AchievmentTypes/FloatAchievmentDefinition.cs
Normal file
29
Achievments/AchievmentTypes/FloatAchievmentDefinition.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d7270d5452c9b04ca07ef43a491a18d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
41
Achievments/AchievmentTypes/IntAchievmentData.cs
Normal file
41
Achievments/AchievmentTypes/IntAchievmentData.cs
Normal file
@ -0,0 +1,41 @@
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Use to GET current progress
|
||||
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||
/// </summary>
|
||||
public int CurrentProgress
|
||||
{
|
||||
get => currentProgress;
|
||||
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)Achievment;
|
||||
|
||||
private int currentProgress;
|
||||
|
||||
public IntAchievmentData(IntAchievmentDefinition def) : base(def)
|
||||
{
|
||||
currentProgress = def.InitialProgress;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/IntAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/IntAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a121b6e6fa8ecc45ab4506c15e5f46e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Achievments/AchievmentTypes/IntAchievmentDefinition.cs
Normal file
27
Achievments/AchievmentTypes/IntAchievmentDefinition.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta
Normal file
11
Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5318fea685aa56646a3310c38a9a9bac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Achievments/AchievmentTypes/ToggleAchievmentData.cs
Normal file
23
Achievments/AchievmentTypes/ToggleAchievmentData.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||
{
|
||||
public class ToggleAchievmentData : AchievmentData
|
||||
{
|
||||
public override bool IsCompleted => CompletionState;
|
||||
|
||||
/// <summary>
|
||||
/// Use to GET current progress
|
||||
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||
/// </summary>
|
||||
public bool CompletionState { get; set; } = false;
|
||||
|
||||
public ToggleAchievmentData(ToggleAchievmentDefinition def) : base(def)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e0806da00902994f9aeb26d295956f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs
Normal file
15
Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 608c7e921b8b16b42919fc6f55b67fcb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Achievments/AchievmentsUpdater.cs
Normal file
15
Achievments/AchievmentsUpdater.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
public class AchievmentsUpdater : MonoBehaviour
|
||||
|
BitterSmile
commented
Should be created automaticly Should be created automaticly
Ghost
commented
How? How?
BitterSmile
commented
Create game object and add component? Create game object and add component?
Ghost
commented
When? When?
BitterSmile
commented
Duno it's your system Duno it's your system
|
||||
{
|
||||
void Update()
|
||||
{
|
||||
Achievment.Instance.UpdateBackend();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/AchievmentsUpdater.cs.meta
Normal file
11
Achievments/AchievmentsUpdater.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5a8c2721326a014bb32737116e4d74b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/Backend.meta
Normal file
8
Achievments/Backend.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3541d03056defb3468d957da0b69a7b9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/Backend/LoacalBaackend.meta
Normal file
8
Achievments/Backend/LoacalBaackend.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0226747b74e86c4b8e89d01e9eeeb3f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
145
Achievments/Backend/LoacalBaackend/LocalBackendConfig.cs
Normal file
145
Achievments/Backend/LoacalBaackend/LocalBackendConfig.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using NEG.Utils.Achievments.AchievmentTypes;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Achievments/Config/Backend/Local")]
|
||||
public class LocalBackendConfig : ScriptableObject, IAchievmentBackendConfig
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||
private static void Init()
|
||||
{
|
||||
#if LOCAL_ACHIEVMENT_BACKEND
|
||||
Achievment.BackendLabel = "LocalAchievments";
|
||||
#endif
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private string saveLocation;
|
||||
|
||||
public IAchievmentBackend ConstructBackend()
|
||||
{
|
||||
return new LocalBackend(saveLocation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This backend is not optimised at all, do not use in public builds
|
||||
/// </summary>
|
||||
public class LocalBackend : IAchievmentBackend
|
||||
{
|
||||
private string saveLocation;
|
||||
|
||||
public LocalBackend(string saveLocation)
|
||||
{
|
||||
this.saveLocation = saveLocation;
|
||||
}
|
||||
|
||||
public void AchievmentCompleted(AchievmentData achievment)
|
||||
{
|
||||
string id = achievment.Achievment.Id;
|
||||
JObject jobj = LoadJson();
|
||||
|
||||
JToken token = jobj[id];
|
||||
|
||||
if (token is not JObject achievmentObj)
|
||||
{
|
||||
achievmentObj = new JObject();
|
||||
}
|
||||
|
||||
achievmentObj["completed"] = true;
|
||||
|
||||
jobj[id] = achievmentObj;
|
||||
|
||||
SaveJson(jobj);
|
||||
}
|
||||
|
||||
public void AchievmentStateChanged(AchievmentData achievment)
|
||||
{
|
||||
string id = achievment.Achievment.Id;
|
||||
JObject jobj = LoadJson();
|
||||
|
||||
JToken token = jobj[id];
|
||||
|
||||
if (token is not JObject achievmentObj)
|
||||
{
|
||||
achievmentObj = new JObject();
|
||||
}
|
||||
|
||||
switch (achievment)
|
||||
{
|
||||
case IntAchievmentData intAchievment:
|
||||
achievmentObj["data"] = intAchievment.CurrentProgress;
|
||||
break;
|
||||
case FloatAchievmentData floatAchievment:
|
||||
achievmentObj["data"] = floatAchievment.CurrentProgress;
|
||||
break;
|
||||
case ToggleAchievmentData toggleAchievment:
|
||||
achievmentObj["data"] = toggleAchievment.IsCompleted;
|
||||
break;
|
||||
}
|
||||
|
||||
jobj[id] = achievmentObj;
|
||||
|
||||
SaveJson(jobj);
|
||||
}
|
||||
|
||||
public AchievmentData GetStoredAchivment(AchievmentDefinition definition)
|
||||
{
|
||||
JObject jobj = LoadJson();
|
||||
|
||||
JToken token = jobj[definition.Id];
|
||||
|
||||
if (token is not JObject)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AchievmentData achievment = definition.Construct();
|
||||
|
||||
switch (achievment)
|
||||
{
|
||||
case IntAchievmentData intAchievment:
|
||||
intAchievment.CurrentProgress = (int)token["data"];
|
||||
break;
|
||||
case FloatAchievmentData floatAchievment:
|
||||
floatAchievment.CurrentProgress = (float)token["data"];
|
||||
break;
|
||||
case ToggleAchievmentData toggleAchievment:
|
||||
toggleAchievment.CompletionState = (bool)token["data"];
|
||||
break;
|
||||
}
|
||||
|
||||
return achievment;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
//Nothing here
|
||||
}
|
||||
|
||||
private JObject LoadJson()
|
||||
{
|
||||
if (Directory.Exists(Path.GetDirectoryName(saveLocation)) && File.Exists(saveLocation))
|
||||
{
|
||||
return JObject.Parse(File.ReadAllText(saveLocation));
|
||||
}
|
||||
return new JObject();
|
||||
}
|
||||
|
||||
private void SaveJson(JObject obj)
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(saveLocation)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(saveLocation));
|
||||
}
|
||||
|
||||
File.WriteAllText(saveLocation, obj.ToString(Formatting.Indented));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a1257a87feec064697193df412554d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/Backend/SteamBackend.meta
Normal file
8
Achievments/Backend/SteamBackend.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db06184b29a56ba44aa446107ada7f66
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "NEG.Utils.Achivmnets.Backend.SteamBackend",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:380ad496eab7ace4b98ceede94941223",
|
||||
"GUID:68bd7fdb68ef2684e982e8a9825b18a5"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"STEAM_ACHIEVMENT_BACKEND"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 243913f72edbe1c4294164fe2ed9dc0c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
115
Achievments/Backend/SteamBackend/SteamBackendConfig.cs
Normal file
115
Achievments/Backend/SteamBackend/SteamBackendConfig.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using NEG.Utils.Achievments.AchievmentTypes;
|
||||
#if STEAM_ACHIEVMENT_BACKEND
|
||||
using Steamworks;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Achievments/Config/Backend/Local")]
|
||||
public class SteamBackendConfig : ScriptableObject, IAchievmentBackendConfig
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||
private static void Init()
|
||||
{
|
||||
#if STEAM_ACHIEVMENT_BACKEND
|
||||
Achievment.BackendLabel = "SteamAchievments";
|
||||
#endif
|
||||
}
|
||||
|
||||
public IAchievmentBackend ConstructBackend()
|
||||
{
|
||||
return new SteamBackend();
|
||||
}
|
||||
}
|
||||
|
||||
#if STEAM_ACHIEVMENT_BACKEND
|
||||
public class SteamBackend : IAchievmentBackend
|
||||
{
|
||||
private bool isDirty = false;
|
||||
|
||||
public SteamBackend()
|
||||
{
|
||||
//
|
||||
SteamUserStats.RequestCurrentStats();
|
||||
|
BitterSmile
commented
No reaction for callback No reaction for callback
Ghost
commented
I asked about it, you said to ignore it, but I can change it I asked about it, you said to ignore it, but I can change it
|
||||
}
|
||||
|
||||
public void AchievmentCompleted(AchievmentData achievment)
|
||||
{
|
||||
SteamUserStats.SetAchievement(achievment.Achievment.Id);
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
public void AchievmentStateChanged(AchievmentData achievment)
|
||||
{
|
||||
string id = achievment.Achievment.Id;
|
||||
|
||||
switch (achievment)
|
||||
{
|
||||
case IntAchievmentData intAchievment:
|
||||
SteamUserStats.SetStat(id, intAchievment.CurrentProgress);
|
||||
|
BitterSmile
commented
No reaction for bool No reaction for bool
Ghost
commented
will fix will fix
|
||||
break;
|
||||
case FloatAchievmentData floatAchievment:
|
||||
SteamUserStats.SetStat(id, floatAchievment.CurrentProgress);
|
||||
break;
|
||||
case ToggleAchievmentData toggleAchievment:
|
||||
//Do nothing, Achievment completed will also be called
|
||||
break;
|
||||
}
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
public AchievmentData GetStoredAchivment(AchievmentDefinition definition)
|
||||
{
|
||||
string id = definition.Id;
|
||||
|
||||
AchievmentData achievment = definition.Construct();
|
||||
|
||||
switch (achievment)
|
||||
{
|
||||
case IntAchievmentData intAchievment:
|
||||
if (SteamUserStats.GetStat(id, out int statI))
|
||||
{
|
||||
intAchievment.CurrentProgress = statI;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||
}
|
||||
break;
|
||||
case FloatAchievmentData floatAchievment:
|
||||
if (SteamUserStats.GetStat(id, out float statF))
|
||||
{
|
||||
floatAchievment.CurrentProgress = statF;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||
}
|
||||
break;
|
||||
case ToggleAchievmentData toggleAchievment:
|
||||
if (SteamUserStats.GetAchievement(id, out bool ach))
|
||||
{
|
||||
toggleAchievment.CompletionState = ach;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return achievment;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (isDirty)
|
||||
|
BitterSmile
commented
Should be check when last time, min time of refresh sholub be greater than minute Should be check when last time, min time of refresh sholub be greater than minute
Ghost
commented
I dont understand I dont understand
BitterSmile
commented
look to documentatnion, you should fire storage callback withing minutes not seconds look to documentatnion, you should fire storage callback withing minutes not seconds
|
||||
{
|
||||
//Reiterate on failure?
|
||||
isDirty = !SteamUserStats.StoreStats();
|
||||
|
BitterSmile
commented
No reaction for callback No reaction for callback
Ghost
commented
will fix will fix
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
11
Achievments/Backend/SteamBackend/SteamBackendConfig.cs.meta
Normal file
11
Achievments/Backend/SteamBackend/SteamBackendConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad7436a24c5bdb84fa2e60e027b7a734
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Achievments/IAchievmentBackend.cs
Normal file
31
Achievments/IAchievmentBackend.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using NEG.Utils.Achievments.AchievmentTypes;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to construct <see cref="IAchievmentBackend"/> instance
|
||||
/// </summary>
|
||||
public interface IAchievmentBackendConfig
|
||||
{
|
||||
/// <returns>Constructed backend</returns>
|
||||
public IAchievmentBackend ConstructBackend();
|
||||
}
|
||||
|
||||
|
||||
public interface IAchievmentBackend : IAchievmentCallbackReciever
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs an AchievmentData for given <paramref name="definition"/>
|
||||
/// </summary>
|
||||
/// <remarks>May return null if there is no stored data for this achievment</remarks>
|
||||
AchievmentData GetStoredAchivment(AchievmentDefinition definition);
|
||||
|
||||
/// <summary>
|
||||
/// Used for e.g. syncing with upstream
|
||||
/// </summary>
|
||||
void Update();
|
||||
}
|
||||
}
|
||||
11
Achievments/IAchievmentBackend.cs.meta
Normal file
11
Achievments/IAchievmentBackend.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfab45a1ce7cc0a4899f35a61b6a60f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Achievments/IAchievmentCallbackReciever.cs
Normal file
23
Achievments/IAchievmentCallbackReciever.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
using AchievmentTypes;
|
||||
|
||||
public interface IAchievmentCallbackReciever
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when an achivment is completed
|
||||
/// </summary>
|
||||
/// <param name="achievment"></param>
|
||||
void AchievmentCompleted(AchievmentData achievment);
|
||||
|
||||
/// <summary>
|
||||
/// Called when achivment progress changes
|
||||
/// </summary>
|
||||
/// <param name="achievment"></param>
|
||||
void AchievmentStateChanged(AchievmentData achievment);
|
||||
}
|
||||
}
|
||||
11
Achievments/IAchievmentCallbackReciever.cs.meta
Normal file
11
Achievments/IAchievmentCallbackReciever.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7218fed73c5be2c4ba31eca9fe44d37a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Achievments/IAchivmentManagerConfig.cs
Normal file
21
Achievments/IAchivmentManagerConfig.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments
|
||||
{
|
||||
public interface IAchivmentManagerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to Apply config data
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
void Apply(AchievmentManager.Builder builder);
|
||||
|
||||
/// <summary>
|
||||
/// Called after <see cref="Apply(AchievmentManager.Builder)"/> was called on every other config
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
void ApplyLast(AchievmentManager.Builder builder);
|
||||
}
|
||||
}
|
||||
11
Achievments/IAchivmentManagerConfig.cs.meta
Normal file
11
Achievments/IAchivmentManagerConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd4b0d54603883447b6458263d6b3605
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Achievments/NEG.Utils.Achievments.asmdef
Normal file
17
Achievments/NEG.Utils.Achievments.asmdef
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "NEG.Utils.Achievments",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||
"GUID:84651a3751eca9349aac36a66bba901b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Achievments/NEG.Utils.Achievments.asmdef.meta
Normal file
7
Achievments/NEG.Utils.Achievments.asmdef.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 380ad496eab7ace4b98ceede94941223
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/PlaymodeTests.meta
Normal file
8
Achievments/PlaymodeTests.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7c140577a904c8419a760a8ac6133c7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
65
Achievments/PlaymodeTests/BackendTests.cs
Normal file
65
Achievments/PlaymodeTests/BackendTests.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NEG.Utils.Achievments.Tests
|
||||
{
|
||||
public class BackendTests
|
||||
{
|
||||
//If stests start to fail first make sure these are correct in relation to test config asset
|
||||
public const string configLabel = "TestAchievments";
|
||||
public const string backendLabel = "AchievmentsLocalTests";
|
||||
public const string saveLocation = "./LocalAchievments/Tests.json";
|
||||
|
||||
public const string AchievmentIdToggle = "TOGGLE";
|
||||
public const string AchievmentIdInt = "INT";
|
||||
public const string AchievmentIdFloat = "FLOAT";
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTtimeSetup()
|
||||
{
|
||||
Achievment.BackendLabel = backendLabel;
|
||||
Achievment.ConfigLabel = configLabel;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Achievment.NullifyInstance();
|
||||
if (File.Exists(saveLocation))
|
||||
{
|
||||
File.Delete(saveLocation);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadWrite()
|
||||
{
|
||||
#if ACHIEVMENT_BACKEND_TESTS
|
||||
//We assume that the achievments are set correctly because otherwise other tests would fail
|
||||
Achievment.SetToggleAchivment(AchievmentIdToggle);
|
||||
Achievment.SetIntProgress(AchievmentIdInt, 20);
|
||||
Achievment.SetFloatProgress(AchievmentIdFloat, 20);
|
||||
|
||||
//We need to assume NullifyInstance works correctly because we dont have access to an AchievmentManager which has not syncked yet
|
||||
Achievment.NullifyInstance();
|
||||
|
||||
Assert.IsTrue(Achievment.IsCompleted(AchievmentIdToggle));
|
||||
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 20);
|
||||
Assert.AreEqual(Achievment.GetFloatProgress(AchievmentIdFloat), 20, 0f);
|
||||
|
||||
Achievment.SetIntProgress(AchievmentIdInt, 30);
|
||||
Achievment.SetFloatProgress(AchievmentIdFloat, 30);
|
||||
|
||||
Achievment.NullifyInstance();
|
||||
|
||||
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 30);
|
||||
Assert.AreEqual(Achievment.GetFloatProgress(AchievmentIdFloat), 30, 0f);
|
||||
#else
|
||||
throw new System.Exception("Backend tests are not enabled. To enable Backend tests add define ACHIEVMENT_BACKEND_TESTS");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/PlaymodeTests/BackendTests.cs.meta
Normal file
11
Achievments/PlaymodeTests/BackendTests.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c09ce9536c2c5f541bb7d07d5eca1d69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "NEG.Utils.Achievments.Tests.Playmode",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"NEG.Utils.Achievments"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38e8b1e483202e14182d34baaea3958e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/PlaymodeTests/TestAssets.meta
Normal file
8
Achievments/PlaymodeTests/TestAssets.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fad16eb700fc70c408c359dca9a76fc9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Achievments/PlaymodeTests/TestAssets/TestLocalBackend.asset
Normal file
15
Achievments/PlaymodeTests/TestAssets/TestLocalBackend.asset
Normal file
@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6a1257a87feec064697193df412554d4, type: 3}
|
||||
m_Name: TestLocalBackend
|
||||
m_EditorClassIdentifier:
|
||||
saveLocation: ./LocalAchievments/Tests.json
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47c9689c811dc9842a5a5e9ca19c6e3c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5
Achievments/TODO.txt
Normal file
5
Achievments/TODO.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Static Achievments class (done)
|
||||
|
BitterSmile
commented
This file shouldn't exist This file shouldn't exist
Ghost
commented
will fix will fix
|
||||
Implement Storage again API (done)
|
||||
Fix typos
|
||||
Merge AchievmentCollection with AchievmentManagerConfig (done)
|
||||
Static backend constructors (done)
|
||||
7
Achievments/TODO.txt.meta
Normal file
7
Achievments/TODO.txt.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94e4aa3c6dc078c4db6a47949655f8a5
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/Tests.meta
Normal file
8
Achievments/Tests.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bab659ddb2d136440a51c5c9b76fefcb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
380
Achievments/Tests/ConfigTests.cs
Normal file
380
Achievments/Tests/ConfigTests.cs
Normal file
@ -0,0 +1,380 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace NEG.Utils.Achievments.Tests
|
||||
{
|
||||
using AchievmentTypes;
|
||||
using static Internal.Extensions;
|
||||
|
||||
public class ConfigTests
|
||||
{
|
||||
public const string AchievmentsLabel = "TestAchievments";
|
||||
|
||||
public const string AchievmentIdToggle = "TOGGLE";
|
||||
public const string AchievmentIdInt = "INT";
|
||||
public const string AchievmentIdFloat = "FLOAT";
|
||||
public const string AchievmentIdInvalid = "huptyrz";
|
||||
public const int RandomProgress = 15;
|
||||
public const int ProgressChangeDelta = 15;
|
||||
public const int CompletedProgress = 100;
|
||||
public const int OvershootProgress = 150;
|
||||
|
||||
#region Id And Types
|
||||
[Test]
|
||||
public void AchivmentInvalidId()
|
||||
{
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||
|
||||
TestInvalidId(AchievmentIdInvalid, (id) => manager.GetAchievmentForId(id), "Get");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentInvalidType()
|
||||
{
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||
|
||||
manager.TestInvalidType<IntAchievmentData, ToggleAchievmentData>(AchievmentIdToggle, "Toggle");
|
||||
manager.TestInvalidType<FloatAchievmentData, IntAchievmentData>(AchievmentIdInt, "Int");
|
||||
manager.TestInvalidType<ToggleAchievmentData, FloatAchievmentData>(AchievmentIdFloat, "Float");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentCorrectIdAndType()
|
||||
{
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||
|
||||
manager.TestValidIdAndType<ToggleAchievmentData>(AchievmentIdToggle, "Toggle");
|
||||
manager.TestValidIdAndType<IntAchievmentData>(AchievmentIdInt, "Int");
|
||||
manager.TestValidIdAndType<FloatAchievmentData>(AchievmentIdFloat, "Float");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Toggle
|
||||
[Test]
|
||||
public void AchivmentToggleSet()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
manager.SetToggleAchivment(AchievmentIdToggle);
|
||||
callbackTester.TestCompleted<ToggleAchievmentData>(AchievmentIdToggle);
|
||||
callbackTester.Reset();
|
||||
|
||||
manager.SetToggleAchivment(AchievmentIdToggle);
|
||||
callbackTester.TestNoChanges();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int
|
||||
[Test]
|
||||
public void AchivmentIntSetLess()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value progress
|
||||
manager.SetIntProgress(AchievmentIdInt, RandomProgress);
|
||||
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||
|
||||
Assert.AreEqual(RandomProgress, data.CurrentProgress);
|
||||
Assert.IsFalse(data.IsCompleted);
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentIntSetEqual()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value equal to required value
|
||||
manager.SetIntProgress(AchievmentIdInt, CompletedProgress);
|
||||
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||
Assert.AreEqual(CompletedProgress, data.CurrentProgress);
|
||||
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing sould change
|
||||
manager.SetIntProgress(AchievmentIdInt, CompletedProgress);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentIntSetGreater()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value greater than required
|
||||
manager.SetIntProgress(AchievmentIdInt, OvershootProgress);
|
||||
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||
//Testing against completed progress, should be clamped down
|
||||
Assert.AreEqual(CompletedProgress, data.CurrentProgress);
|
||||
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing sould change
|
||||
manager.SetIntProgress(AchievmentIdInt, OvershootProgress);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentIntChangeCompletion()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Add progresss one interval below completion
|
||||
for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++)
|
||||
{
|
||||
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||
callbackTester.TestNotCompleted();
|
||||
var changed = callbackTester.GetChanged<IntAchievmentData>();
|
||||
|
||||
Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress);
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
//Add progress one more time, should now be completed
|
||||
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||
var changed1 = callbackTester.GetChanged<IntAchievmentData>();
|
||||
Assert.AreEqual(CompletedProgress, changed1.CurrentProgress);
|
||||
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing should change
|
||||
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, but down this time also nothing should change
|
||||
manager.ChangeIntProgress(AchievmentIdInt, -ProgressChangeDelta);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Float
|
||||
[Test]
|
||||
public void AchivmentFloatSetLess()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value progress
|
||||
manager.SetFloatProgress(AchievmentIdFloat, RandomProgress);
|
||||
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||
|
||||
Assert.AreEqual((float)RandomProgress, data.CurrentProgress);
|
||||
Assert.IsFalse(data.IsCompleted);
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentFloatSetEqual()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value equal to required value
|
||||
manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress);
|
||||
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||
Assert.AreEqual((float)CompletedProgress, data.CurrentProgress);
|
||||
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing sould change
|
||||
manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentFloatSetGreater()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Set progress to some value greater than required
|
||||
manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress);
|
||||
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||
//Testing against completed progress, should be clamped down
|
||||
Assert.AreEqual((float)CompletedProgress, data.CurrentProgress);
|
||||
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing sould change
|
||||
manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AchivmentFloatChangeCompletion()
|
||||
{
|
||||
var callbackTester = new TestCallbackRereiver();
|
||||
|
||||
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||
.WithCallbackReciever(callbackTester)
|
||||
.Build();
|
||||
|
||||
//Add progresss one interval below completion
|
||||
for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++)
|
||||
{
|
||||
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||
callbackTester.TestNotCompleted();
|
||||
var changed = callbackTester.GetChanged<FloatAchievmentData>();
|
||||
|
||||
Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress, 0.0f);
|
||||
callbackTester.Reset();
|
||||
}
|
||||
|
||||
//Add progress one more time, should now be completed
|
||||
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||
var changed1 = callbackTester.GetChanged<FloatAchievmentData>();
|
||||
Assert.AreEqual((float)CompletedProgress, changed1.CurrentProgress);
|
||||
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, this time nothing should change
|
||||
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
|
||||
//Do that again, but down this time also nothing should change
|
||||
manager.ChangeFloatProgress(AchievmentIdFloat, -ProgressChangeDelta);
|
||||
callbackTester.TestNoChanges();
|
||||
callbackTester.Reset();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private class TestCallbackRereiver : IAchievmentCallbackReciever
|
||||
{
|
||||
public AchievmentData LastDataUpdated { get; private set; } = null;
|
||||
public Type LastTypeSet { get; private set; } = null;
|
||||
public string LastIdSet { get; private set; } = null;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
LastDataUpdated = null;
|
||||
LastTypeSet = null;
|
||||
LastIdSet = null;
|
||||
}
|
||||
|
||||
public T GetChanged<T>() where T : AchievmentData
|
||||
{
|
||||
Assert.IsInstanceOf(typeof(T), LastDataUpdated);
|
||||
|
||||
return (T)LastDataUpdated;
|
||||
}
|
||||
|
||||
public void TestNoChanges()
|
||||
{
|
||||
Assert.IsNull(LastDataUpdated);
|
||||
Assert.IsNull(LastTypeSet);
|
||||
Assert.IsNull(LastIdSet);
|
||||
}
|
||||
|
||||
public void TestNotCompleted()
|
||||
{
|
||||
//No need to also check LastTypeSet, they are both set or bot null
|
||||
Assert.IsNull(LastIdSet);
|
||||
}
|
||||
|
||||
public void TestCompleted<Type>(string id)
|
||||
{
|
||||
Assert.AreEqual(typeof(Type), LastTypeSet);
|
||||
Assert.AreEqual(id, LastIdSet);
|
||||
//Shold not be null: if we axpect achievment to be completed it must have also been updated
|
||||
Assert.IsTrue(LastDataUpdated.IsCompleted);
|
||||
}
|
||||
|
||||
public void AchievmentCompleted(AchievmentData achievment)
|
||||
{
|
||||
LastTypeSet = achievment.GetType();
|
||||
LastIdSet = achievment.Achievment.Id;
|
||||
}
|
||||
|
||||
public void AchievmentStateChanged(AchievmentData achievment)
|
||||
{
|
||||
LastDataUpdated = achievment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static void TestValidIdAndType<Type>(this AchievmentManager manager, string id, string testName) where Type : AchievmentData
|
||||
{
|
||||
TestValidIdAndType(id, (id) => manager.GetAchievmentForId<Type>(id), testName);
|
||||
}
|
||||
|
||||
public static void TestValidIdAndType(string id, Action<string> manipulation, string testName)
|
||||
{
|
||||
Assert.DoesNotThrow(() => manipulation(id), $"{testName}: Invalid type or id");
|
||||
}
|
||||
|
||||
public static void TestInvalidId(this AchievmentManager manager, string id, string testName)
|
||||
{
|
||||
TestInvalidId(id, (id) => manager.GetAchievmentForId(id), testName);
|
||||
}
|
||||
|
||||
public static void TestInvalidId(string id, Action<string> manipulation, string testName)
|
||||
{
|
||||
var exception = Assert.Throws<AchievmentException>(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}");
|
||||
|
||||
Assert.AreEqual(exception.Id, id, $"{testName}: Achievment id does not match");
|
||||
}
|
||||
|
||||
public static void TestInvalidType<Expected, Actual>(this AchievmentManager manager, string id, string testName) where Expected : AchievmentData where Actual : AchievmentData
|
||||
{
|
||||
TestInvalidType<Expected, Actual>(id, (id) => manager.GetAchievmentForId<Expected>(id), testName);
|
||||
}
|
||||
|
||||
public static void TestInvalidType<Expected, Actual>(string id, Action<string> manipulation, string testName) where Expected : AchievmentData where Actual : AchievmentData
|
||||
{
|
||||
var exception = Assert.Throws<AchievmentTypeException>(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}");
|
||||
|
||||
Assert.AreEqual(id, exception.Id, $"{testName}: Achievment id does not match");
|
||||
Assert.AreSame(typeof(Expected), exception.Expected, $"{testName}: Target achievment type does not match");
|
||||
Assert.AreSame(typeof(Actual), exception.Actual, $"{testName}: Actual achievment type does not match");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Achievments/Tests/ConfigTests.cs.meta
Normal file
11
Achievments/Tests/ConfigTests.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c47a38eaf8bffa849b130320427701cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef
Normal file
26
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "NEG.Utils.Achivments.Tests",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"Unity.Addressables",
|
||||
"Unity.ResourceManager",
|
||||
"NEG.Utils.Achievments"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef.meta
Normal file
7
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18b8be0ae04b6ad45ba52b2ddeb8198d
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Achievments/Tests/TestAssets.meta
Normal file
8
Achievments/Tests/TestAssets.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f7445ed9dd5a4548b89d56c196cbec7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Achievments/Tests/TestAssets/BaseConfig.asset
Normal file
18
Achievments/Tests/TestAssets/BaseConfig.asset
Normal file
@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 88120b6e616164f489387a6a32a25dee, type: 3}
|
||||
m_Name: BaseConfig
|
||||
m_EditorClassIdentifier:
|
||||
<Achivments>k__BackingField:
|
||||
- {fileID: 11400000, guid: 7734df2e5d4033346aac56f0a2b2a836, type: 2}
|
||||
- {fileID: 11400000, guid: c704b1ea2247ad540842a9caff628211, type: 2}
|
||||
- {fileID: 11400000, guid: c71840de74e747e45afc82ecf8922dcd, type: 2}
|
||||
8
Achievments/Tests/TestAssets/BaseConfig.asset.meta
Normal file
8
Achievments/Tests/TestAssets/BaseConfig.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15513fd07fae44548bac5d923171a2a3
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Achievments/Tests/TestAssets/Float.asset
Normal file
18
Achievments/Tests/TestAssets/Float.asset
Normal file
@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2d7270d5452c9b04ca07ef43a491a18d, type: 3}
|
||||
m_Name: Float
|
||||
m_EditorClassIdentifier:
|
||||
<Id>k__BackingField: FLOAT
|
||||
<ProgressRequired>k__BackingField: 100
|
||||
<InitialProgress>k__BackingField: 0
|
||||
<Clamped>k__BackingField: 0
|
||||
8
Achievments/Tests/TestAssets/Float.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Float.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7734df2e5d4033346aac56f0a2b2a836
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Achievments/Tests/TestAssets/Int.asset
Normal file
18
Achievments/Tests/TestAssets/Int.asset
Normal file
@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5318fea685aa56646a3310c38a9a9bac, type: 3}
|
||||
m_Name: Int
|
||||
m_EditorClassIdentifier:
|
||||
<Id>k__BackingField: INT
|
||||
<ProgressRequired>k__BackingField: 100
|
||||
<InitialProgress>k__BackingField: 0
|
||||
<Clamped>k__BackingField: 0
|
||||
8
Achievments/Tests/TestAssets/Int.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Int.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c704b1ea2247ad540842a9caff628211
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Achievments/Tests/TestAssets/Toggle.asset
Normal file
15
Achievments/Tests/TestAssets/Toggle.asset
Normal file
@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 608c7e921b8b16b42919fc6f55b67fcb, type: 3}
|
||||
m_Name: Toggle
|
||||
m_EditorClassIdentifier:
|
||||
<Id>k__BackingField: TOGGLE
|
||||
8
Achievments/Tests/TestAssets/Toggle.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Toggle.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c71840de74e747e45afc82ecf8922dcd
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
x
Reference in New Issue
Block a user
Why need this, when all are empty
was needed in earlier version, i will remove it