feat(upserver): 保存M2客户端KV迁移至本人统计写检查点

保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
This commit is contained in:
Liubing\LB
2026-09-30 19:19:05 +08:00
parent 1c0cdf7a99
commit 6813da149a
511 changed files with 151858 additions and 2376 deletions

View File

@@ -17,6 +17,7 @@ namespace GameCore
{
public class PlayerData
{
[asap.core.Inject] public game.PlayerDataStorage.IPlayerSaveStore playerSaveStore { get; set; }
private cfg.Tables _tables;
MMTService _MMService;
public PlayerData(cfg.Tables tables, MMTService mmService)
@@ -336,7 +337,7 @@ namespace GameCore
if (!newRodList.Contains(id))
{
newRodList.Add(id);
PlayFabMgr.Instance.UpdateUserDataValue("NewRodList", JsonMapper.ToJson(newRodList));
playerSaveStore.Write("NewRodList", JsonMapper.ToJson(newRodList)).RequireAccepted();
if (addShowNewRod)
{
showNewRodList.Add(id);
@@ -367,7 +368,7 @@ namespace GameCore
public void RewardNewRod(int id)
{
newRodList.Remove(id);
PlayFabMgr.Instance.UpdateUserDataValue("NewRodList", JsonMapper.ToJson(newRodList));
playerSaveStore.Write("NewRodList", JsonMapper.ToJson(newRodList)).RequireAccepted();
GContext.container.Resolve<PlayerFishData>().SetRedPoint();
}
@@ -1233,7 +1234,7 @@ namespace GameCore
#if UNITY_EDITOR && !SERVICE_HOST
if(game.PlayerDataStorage.PlayerKVGameplayLoop.Enabled) return game.PlayerDataStorage.PlayerKVGameplayLoop.Write("NewPlayerDataDic",Newtonsoft.Json.JsonConvert.SerializeObject(NewPlayerDataDic),remote);
#endif
PlayFabMgr.Instance.UpdateUserDataValue("NewPlayerDataDic", Newtonsoft.Json.JsonConvert.SerializeObject(NewPlayerDataDic), remote);
playerSaveStore.Write("NewPlayerDataDic", Newtonsoft.Json.JsonConvert.SerializeObject(NewPlayerDataDic), remote).RequireAccepted();
return null;
}
public void Init()
@@ -1392,13 +1393,14 @@ namespace GameCore
}
public async void CoRecoveryEnergy(int energyRecoveryTime)
{
var store = playerSaveStore;
tokenSource?.Cancel();
tokenSource = new System.Threading.CancellationTokenSource();
var token = tokenSource.Token;
_isRecoveryEnergy = true;
int initEnergyRestorationSpeed = _tables.TbGlobalConfig.InitEnergyRestorationSpeed * 60;
while (Energy < MaxEnergy && !token.IsCancellationRequested)
while (Energy < MaxEnergy && !token.IsCancellationRequested && store.IsCurrent)
{
if (energyRecoveryTime >= initEnergyRestorationSpeed)
{
@@ -1431,7 +1433,7 @@ namespace GameCore
SavePlayerData();
}
await Awaiters.Seconds(1);
if (token.IsCancellationRequested)
if (token.IsCancellationRequested || !store.IsCurrent)
{
return;
}
@@ -1502,14 +1504,17 @@ namespace GameCore
public async void OpenAppraisePopupPanel(int fishId)
{
var store = playerSaveStore;
if (!store.IsCurrent) return;
if (lastMapId != _tables.TbMapData.DataList[0].ID && !IsOpenAppraise)
{
var fishData = _tables.TbFishData.GetOrDefault(fishId);
if (fishData != null && fishData.Quality >= 5)
{
await UIManager.Instance.ShowUI(UITypes.AppraisePopupPanel);
if (!store.IsCurrent) return;
IsOpenAppraise = true;
PlayFabMgr.Instance.UpdateUserDataValue("IsOpenAppraise", "true");
playerSaveStore.Write("IsOpenAppraise", "true").RequireAccepted();
}
}
}