using System; using System.Threading; using System.Threading.Tasks; namespace game.PlayerDataStorage { // A store belongs to one login. Callers retain this instance across awaits. public interface IPlayerSaveStore { bool IsCurrent { get; } PlayerSaveReadResult Read(string key); PlayerSaveWriteResult Write(string key, string value, bool remoteStore = true); Task SyncDataImmidiate(string key, string value); } public sealed class PlayerSaveReadResult { public bool Success => Error == null; public bool? Found { get; } public string Value { get; } public string Error { get; } internal PlayerSaveReadResult(bool found, string value) { Found = found; Value = value; } internal PlayerSaveReadResult(string error) { Error = error ?? "ReadFailed"; } public string ValueOrThrow() { if (!Success) throw new InvalidOperationException("Player save read failed: " + Error); return Value; } } public sealed class PlayerSaveReceipt { internal readonly IPlayerSaveStore Store; internal readonly object Ticket; internal PlayerSaveReceipt(IPlayerSaveStore store, object ticket) { Store = store; Ticket = ticket; } } public sealed class PlayerSaveWriteResult { public bool Accepted => Error == null; public string Error { get; } public PlayerSaveReceipt Receipt { get; } internal PlayerSaveWriteResult(PlayerSaveReceipt receipt) { Receipt = receipt; } internal PlayerSaveWriteResult(string error) { Error = error ?? "WriteRejected"; } public void RequireAccepted() { if (!Accepted) throw new InvalidOperationException("Player save write rejected: " + Error); } } }