feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。 保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。 验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。 包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using asap.core;
|
||||
using asap.core;
|
||||
using cfg;
|
||||
using GameCore;
|
||||
using System;
|
||||
@@ -32,6 +32,57 @@ namespace game
|
||||
}
|
||||
public class ClubService //: IClubService
|
||||
{
|
||||
[Inject] public PlayerDataStorage.IPlayerSaveStore SaveStore { get; set; }
|
||||
// BEGIN B01 fixed prompt owner
|
||||
readonly bool requiresFormalKV;
|
||||
PlayerDataStorage.PlayerKVGameSessionHandle promptOwner;
|
||||
internal PlayerDataStorage.PlayerKVEditResult LastPromptEdit { get; private set; }
|
||||
public ClubService() : this(RequireFrozenSelection()) { }
|
||||
static bool RequireFrozenSelection()
|
||||
{
|
||||
var selection = GContext.container.Resolve<PlayerDataStorage.PlayerKVRuntimeSelection>();
|
||||
if (selection == null) throw DefaultSettingService.PromptFailure("IsOpenClubRed: startup selection missing.");
|
||||
return selection.IsKV;
|
||||
}
|
||||
internal ClubService(bool formalKV) { requiresFormalKV = formalKV; }
|
||||
internal ClubService(PlayerDataStorage.PlayerKVGameSessionHandle owner) : this(true)
|
||||
{
|
||||
promptOwner = owner ?? throw new ArgumentNullException(nameof(owner));
|
||||
RequirePromptOwner();
|
||||
}
|
||||
// The constructor captures the registered startup selection, never a later mutable config value.
|
||||
internal void PreflightFormalPromptOwner(PlayerDataStorage.PlayerKVGameSessionHandle owner)
|
||||
{
|
||||
if (!requiresFormalKV || owner == null || (promptOwner != null && !ReferenceEquals(promptOwner, owner)))
|
||||
throw DefaultSettingService.PromptFailure("IsOpenClubRed: formal owner mismatch.");
|
||||
var read = KVMgr.ReadKV(owner, "IsOpenClubRed");
|
||||
if (!read.Success)
|
||||
throw DefaultSettingService.PromptFailure($"IsOpenClubRed owner={owner.OwnerInstanceId}: {read.Error}");
|
||||
}
|
||||
internal void BindFormalPromptOwner(PlayerDataStorage.PlayerKVGameSessionHandle owner)
|
||||
{
|
||||
PreflightFormalPromptOwner(owner);
|
||||
if (promptOwner == null) promptOwner = owner;
|
||||
RequirePromptOwner();
|
||||
}
|
||||
internal bool HasFormalPromptOwner(PlayerDataStorage.PlayerKVGameSessionHandle owner) =>
|
||||
requiresFormalKV && ReferenceEquals(promptOwner, owner);
|
||||
internal void RequirePromptOwner()
|
||||
{
|
||||
if (promptOwner != null) ReadPrompt();
|
||||
else if (requiresFormalKV)
|
||||
throw DefaultSettingService.PromptFailure("IsOpenClubRed: formal owner not handed off.");
|
||||
}
|
||||
PlayerDataStorage.PlayerKVKeyReadResult ReadPrompt()
|
||||
{
|
||||
if (LastPromptEdit != null && !LastPromptEdit.Accepted)
|
||||
throw DefaultSettingService.PromptFailure($"IsOpenClubRed owner={promptOwner.OwnerInstanceId}: {LastPromptEdit.StateResult.Error}; uncertain={LastPromptEdit.StateResult.LocalCommitMayHaveSucceeded}");
|
||||
var read = KVMgr.ReadKV(promptOwner, "IsOpenClubRed");
|
||||
if (!read.Success)
|
||||
throw DefaultSettingService.PromptFailure($"IsOpenClubRed owner={promptOwner.OwnerInstanceId}: {read.Error}");
|
||||
return read;
|
||||
}
|
||||
// END B01 fixed prompt owner
|
||||
[Inject]
|
||||
public IUserService userService { get; set; }
|
||||
[Inject]
|
||||
@@ -137,7 +188,7 @@ namespace game
|
||||
}
|
||||
void SaveLureDonateData()
|
||||
{
|
||||
PlayFabMgr.Instance.UpdateUserDataValue("LureDonateData", Newtonsoft.Json.JsonConvert.SerializeObject(lureDonateData));
|
||||
SaveStore.Write("LureDonateData", Newtonsoft.Json.JsonConvert.SerializeObject(lureDonateData)).RequireAccepted();
|
||||
}
|
||||
//刷新体力求助次数
|
||||
public void RefreshLureDonate()
|
||||
@@ -152,6 +203,22 @@ namespace game
|
||||
|
||||
public void SetOpenClubRed()
|
||||
{
|
||||
if (requiresFormalKV && promptOwner == null) RequirePromptOwner();
|
||||
if (promptOwner != null)
|
||||
{
|
||||
var read = ReadPrompt();
|
||||
// M14: any present string means read, including "0" and the empty string.
|
||||
if (read.Found != true)
|
||||
{
|
||||
LastPromptEdit = KVMgr.WriteKV(promptOwner, "IsOpenClubRed", "1");
|
||||
if (!LastPromptEdit.Accepted)
|
||||
throw DefaultSettingService.PromptFailure($"IsOpenClubRed owner={promptOwner.OwnerInstanceId}: {LastPromptEdit.StateResult.Error}; uncertain={LastPromptEdit.StateResult.LocalCommitMayHaveSucceeded}");
|
||||
}
|
||||
RequirePromptOwner();
|
||||
IsOpenClubRed = false;
|
||||
SetClubRed();
|
||||
return;
|
||||
}
|
||||
if (IsOpenClubRed)
|
||||
{
|
||||
IsOpenClubRed = false;
|
||||
@@ -623,7 +690,7 @@ namespace game
|
||||
{
|
||||
if (!TryReadClubResponse<ClubSinginResp>(json, out var clubSinginResp, 0)) return;
|
||||
signTime = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||||
PlayFabMgr.Instance.UpdateUserDataValue("ClubSignin", signTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
SaveStore.Write("ClubSignin", signTime.Value.ToString("yyyy-MM-dd HH:mm:ss")).RequireAccepted();
|
||||
if (clubSinginResp.code == 0)
|
||||
{
|
||||
chatService.SendSystemMessage($"{MessageChatType.SI}_{apiPlayerId}");
|
||||
|
||||
Reference in New Issue
Block a user