Files
ft/CodexOutput/upserver/B3BatchMigration/M2/C2d修改前快照/062-IPlayerSaveStore.cs.txt
Liubing\LB 6813da149a feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
2026-09-30 19:19:05 +08:00

63 lines
2.6 KiB
Plaintext

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<PlayerSaveConfirmation> WriteAndConfirmAsync(string key, string value, CancellationToken token = default);
Task<PlayerSaveConfirmation> ConfirmAsync(PlayerSaveReceipt receipt, CancellationToken token = default);
Task<PlayerSaveConfirmation> FlushAsync(CancellationToken token = default);
}
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);
}
}
// Buffered and LocalOnly are deliberately different from cloud confirmation.
public enum PlayerSaveStatus { Confirmed, Buffered, LocalOnly, Rejected, Superseded, Unknown, Cancelled }
public sealed class PlayerSaveConfirmation
{
public PlayerSaveStatus Status { get; }
public bool Confirmed => Status == PlayerSaveStatus.Confirmed;
public string Error { get; }
internal PlayerSaveConfirmation(PlayerSaveStatus status, string error = null) { Status = status; Error = error; }
}
}