using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Unity.Services.Authentication;
using Unity.Services.CloudSave;
using Unity.Services.Core;
using UnityEngine;
public class CloudSaveClient : ISaveClient
{
public async Task Initialise()
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
Client = CloudSaveService.Instance.Data;
}
Unity.Services.CloudSave.Internal.IDataService Client;
#region Save
public async Task Save(string Key, object Value)
{
var Data = new Dictionary<string, object> { { Key, Value } };
await Call(Client.Player.SaveAsync(Data));
}
public async Task Save(params (string Key, object Value)[] Values)
{
var Data = Values.ToDictionary(Item => Item.Key, Item => Item.Value);
await Call(Client.Player.SaveAsync(Data));
}
#endregion
#region Load
public async Task<T> Load<T>(string Key)
{
var Query = await Call(Client.Player.LoadAsync(new HashSet<string> { Key }));
return Query.TryGetValue(Key, out var Item) ? Deserialize<T>(Item.Value.GetAsString()) : default;
}
public async Task<IEnumerable<T>> Load<T>(params string[] Keys)
{
var Query = await Call(Client.Player.LoadAsync(Keys.ToHashSet()));
return Keys.Select(Key =>
{
if (Query.TryGetValue(Key, out var Item) && Item.Value != null)
{
return Deserialize<T>(Item.Value.GetAsString());
}
return default;
});
}
#endregion
#region Delete
public async Task Delete(string Key)
{
await Call(Client.Player.DeleteAsync(Key, new Unity.Services.CloudSave.Models.Data.Player.DeleteOptions()));
}
public async Task DeleteAll()
{
var ItemKeys = await Call(Client.Player.ListAllKeysAsync());
var Keys = ItemKeys.Select(ItemKey => ItemKey.Key).ToList();
var Tasks = Keys.Select(Key => Client.Player.DeleteAsync(Key, new Unity.Services.CloudSave.Models.Data.Player.DeleteOptions())).ToList();
await Call(Task.WhenAll(Tasks));
}
#endregion
private static T Deserialize<T>(string Input)
{
if (typeof(T) == typeof(string)) return (T)(object)Input;
return JsonConvert.DeserializeObject<T>(Input);
}
public async Task<List<string>> GetKeys()
{
var ItemKeys = await Call(Client.Player.ListAllKeysAsync());
return ItemKeys.Select(ItemKey => ItemKey.Key).ToList();
}
#region Error Handling
static async Task Call(Task Action)
{
try
{
await Action;
}
catch (CloudSaveValidationException Exception)
{
Debug.LogError(Exception);
}
catch (CloudSaveRateLimitedException Exception)
{
Debug.LogError(Exception);
}
catch (CloudSaveException Exception)
{
Debug.LogError(Exception);
}
}
static async Task<T> Call<T>(Task<T> Action)
{
try
{
return await Action;
}
catch (CloudSaveValidationException Exception)
{
Debug.LogError(Exception);
}
catch (CloudSaveRateLimitedException Exception)
{
Debug.LogError(Exception);
}
catch (CloudSaveException Exception)
{
Debug.LogError(Exception);
}
return default;
}
#endregion
}
#region Interface
public interface ISaveClient
{
Task Initialise();
Task Save(string Key, object Value);
Task Save(params (string Key, object Value)[] Values);
Task<T> Load<T>(string Key);
Task<IEnumerable<T>> Load<T>(params string[] Keys);
Task Delete(string Key);
Task DeleteAll();
Task<List<string>> GetKeys();
}
#endregion