achivments #1
@ -110,6 +110,8 @@ namespace NEG.Utils.Achievments
|
|||||||
private Dictionary<string, AchievmentDefinition> definitionCache;
|
private Dictionary<string, AchievmentDefinition> definitionCache;
|
||||||
private Dictionary<AchievmentDefinition, AchievmentData> dataCache;
|
private Dictionary<AchievmentDefinition, AchievmentData> dataCache;
|
||||||
|
|
||||||
|
private IAchievmentBackend activeBackend;
|
||||||
|
|
||||||
private AchievmentManager()
|
private AchievmentManager()
|
||||||
{
|
{
|
||||||
definitionCache = new Dictionary<string, AchievmentDefinition>();
|
definitionCache = new Dictionary<string, AchievmentDefinition>();
|
||||||
@ -135,6 +137,7 @@ namespace NEG.Utils.Achievments
|
|||||||
/// <remarks>Resets all achievments data</remarks>
|
/// <remarks>Resets all achievments data</remarks>
|
||||||
private void InitBackend(IAchievmentBackend achievmentBackend)
|
private void InitBackend(IAchievmentBackend achievmentBackend)
|
||||||
{
|
{
|
||||||
|
activeBackend = achievmentBackend;
|
||||||
foreach (var definition in definitionCache.Values)
|
foreach (var definition in definitionCache.Values)
|
||||||
{
|
{
|
||||||
var storedProgress = achievmentBackend.GetStoredAchivment(definition);
|
var storedProgress = achievmentBackend.GetStoredAchivment(definition);
|
||||||
@ -300,6 +303,11 @@ namespace NEG.Utils.Achievments
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void UpdateBackend()
|
||||||
|
{
|
||||||
|
activeBackend?.Update();
|
||||||
|
}
|
||||||
|
|
||||||
private T ValidateAchievmentType<T>(AchievmentData data) where T : AchievmentData
|
private T ValidateAchievmentType<T>(AchievmentData data) where T : AchievmentData
|
||||||
{
|
{
|
||||||
if (data is not T convetred)
|
if (data is not T convetred)
|
||||||
|
|||||||
@ -8,10 +8,15 @@ namespace NEG.Utils.Achievments.AchievmentTypes
|
|||||||
{
|
{
|
||||||
public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired;
|
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
|
public float CurrentProgress
|
||||||
{
|
{
|
||||||
get => currentProgress;
|
get => currentProgress;
|
||||||
internal set
|
set
|
||||||
{
|
{
|
||||||
if (Def.Clamped)
|
if (Def.Clamped)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,10 +9,15 @@ namespace NEG.Utils.Achievments.AchievmentTypes
|
|||||||
{
|
{
|
||||||
public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired;
|
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
|
public int CurrentProgress
|
||||||
{
|
{
|
||||||
get => currentProgress;
|
get => currentProgress;
|
||||||
internal set
|
set
|
||||||
{
|
{
|
||||||
if (Def.Clamped)
|
if (Def.Clamped)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,7 +8,12 @@ namespace NEG.Utils.Achievments.AchievmentTypes
|
|||||||
{
|
{
|
||||||
public override bool IsCompleted => CompletionState;
|
public override bool IsCompleted => CompletionState;
|
||||||
|
|
||||||
public bool CompletionState { get; internal set; } = false;
|
/// <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)
|
public ToggleAchievmentData(ToggleAchievmentDefinition def) : base(def)
|
||||||
{
|
{
|
||||||
|
|||||||
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
|
||||||
|
|
|||||||
|
{
|
||||||
|
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:
|
||||||
@ -15,7 +15,7 @@ namespace NEG.Utils.Achievments
|
|||||||
private static void Init()
|
private static void Init()
|
||||||
{
|
{
|
||||||
#if LOCAL_ACHIEVMENT_BACKEND
|
#if LOCAL_ACHIEVMENT_BACKEND
|
||||||
Achievments.BackendLabel = "LocalAchievments";
|
Achievment.BackendLabel = "LocalAchievments";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +28,9 @@ namespace NEG.Utils.Achievments
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This backend is not optimised at all, do not use in public builds
|
||||||
|
/// </summary>
|
||||||
public class LocalBackend : IAchievmentBackend
|
public class LocalBackend : IAchievmentBackend
|
||||||
{
|
{
|
||||||
private string saveLocation;
|
private string saveLocation;
|
||||||
@ -115,6 +118,11 @@ namespace NEG.Utils.Achievments
|
|||||||
return achievment;
|
return achievment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
//Nothing here
|
||||||
|
}
|
||||||
|
|
||||||
private JObject LoadJson()
|
private JObject LoadJson()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(Path.GetDirectoryName(saveLocation)) && File.Exists(saveLocation))
|
if (Directory.Exists(Path.GetDirectoryName(saveLocation)) && File.Exists(saveLocation))
|
||||||
|
|||||||
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:
|
||||||
@ -21,6 +21,11 @@ namespace NEG.Utils.Achievments
|
|||||||
/// Constructs an AchievmentData for given <paramref name="definition"/>
|
/// Constructs an AchievmentData for given <paramref name="definition"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>May return null if there is no stored data for this achievment</remarks>
|
/// <remarks>May return null if there is no stored data for this achievment</remarks>
|
||||||
public AchievmentData GetStoredAchivment(AchievmentDefinition definition);
|
AchievmentData GetStoredAchivment(AchievmentDefinition definition);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for e.g. syncing with upstream
|
||||||
|
/// </summary>
|
||||||
|
void Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "NEG.Utils.Achivments",
|
"name": "NEG.Utils.Achievments",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||||
@ -37,6 +37,7 @@ namespace NEG.Utils.Achievments.Tests
|
|||||||
[Test]
|
[Test]
|
||||||
public void ReadWrite()
|
public void ReadWrite()
|
||||||
{
|
{
|
||||||
|
#if ACHIEVMENT_BACKEND_TESTS
|
||||||
//We assume that the achievments are set correctly because otherwise other tests would fail
|
//We assume that the achievments are set correctly because otherwise other tests would fail
|
||||||
Achievment.SetToggleAchivment(AchievmentIdToggle);
|
Achievment.SetToggleAchivment(AchievmentIdToggle);
|
||||||
Achievment.SetIntProgress(AchievmentIdInt, 20);
|
Achievment.SetIntProgress(AchievmentIdInt, 20);
|
||||||
@ -56,7 +57,9 @@ namespace NEG.Utils.Achievments.Tests
|
|||||||
|
|
||||||
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 30);
|
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 30);
|
||||||
Assert.AreEqual(Achievment.GetFloatProgress(AchievmentIdFloat), 30, 0f);
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
"references": [
|
"references": [
|
||||||
"UnityEngine.TestRunner",
|
"UnityEngine.TestRunner",
|
||||||
"UnityEditor.TestRunner",
|
"UnityEditor.TestRunner",
|
||||||
"NEG.Utils.Achivments"
|
"NEG.Utils.Achievments"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@ -4,10 +4,9 @@
|
|||||||
"references": [
|
"references": [
|
||||||
"UnityEngine.TestRunner",
|
"UnityEngine.TestRunner",
|
||||||
"UnityEditor.TestRunner",
|
"UnityEditor.TestRunner",
|
||||||
"NEG.Utils.Achivments",
|
|
||||||
"Unity.Addressables",
|
"Unity.Addressables",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager",
|
||||||
""
|
"NEG.Utils.Achievments"
|
||||||
],
|
],
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user
Should be created automaticly
How?
Create game object and add component?
When?
Duno it's your system