feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。 保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。 验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。 包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
using System.Collections.Generic;
|
||||
using asap.core;
|
||||
using cfg;
|
||||
using game;
|
||||
using GameCore;
|
||||
using UniRx;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
public interface IDeferredRewardStashService
|
||||
{
|
||||
public void DisposeSubscriptions();
|
||||
public void Reset();
|
||||
public void Flush(RewardType rewardType = RewardType.FishBoxFly, bool isShowReward = true);
|
||||
public void UploadData();
|
||||
public void LoadData();
|
||||
public IReadOnlyList<ItemData> Items { get; }
|
||||
public bool IsEmpty { get; }
|
||||
}
|
||||
|
||||
public class DeferredRewardStashService : IDeferredRewardStashService
|
||||
{
|
||||
readonly game.PlayerDataStorage.IPlayerSaveStore saveStore = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>();
|
||||
|
||||
private readonly TbItem _itemTable = GContext.container.Resolve<Tables>().TbItem;
|
||||
private readonly PlayerItemData _playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||||
private CompositeDisposable _disposables;
|
||||
private List<ItemData> _items;
|
||||
public IReadOnlyList<ItemData> Items => _items;
|
||||
public bool IsEmpty => _items is not { Count: > 0 };
|
||||
private const string Key = "DeferredRewardStashService", Comma = ",", Splitter = "|";
|
||||
|
||||
|
||||
public DeferredRewardStashService()
|
||||
{
|
||||
_disposables = new CompositeDisposable();
|
||||
GContext.OnEvent<EventStashDrop>().Subscribe(StashItemsByDrop).AddTo(_disposables);
|
||||
GContext.OnEvent<EventStashItems>().Subscribe(StashItems).AddTo(_disposables);
|
||||
GContext.OnEvent<EventStashDropList>().Subscribe(StashItemsByDropList).AddTo(_disposables);
|
||||
GContext.OnEvent<EventStashItem>().Subscribe(e => StashItem(e.Item)).AddTo(_disposables);
|
||||
}
|
||||
|
||||
public void DisposeSubscriptions()
|
||||
{
|
||||
_disposables.Dispose();
|
||||
_disposables = null;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_items = new List<ItemData>();
|
||||
//_items.Clear();
|
||||
}
|
||||
|
||||
public void Flush(RewardType rewardType = RewardType.FishBoxFly, bool isShowReward = true)
|
||||
{
|
||||
Debug.Log("[DeferredRewardStashService] Flush.");
|
||||
string textValue = LocalizationMgr.GetText("UI_MiniBattlePass_DivePopupPanel_8");
|
||||
if (IsEmpty)
|
||||
{
|
||||
rewardType = RewardType.FishBoxFlyRestore;
|
||||
textValue = LocalizationMgr.GetText("UI_FishingRewardPanel_101042");
|
||||
LoadData();
|
||||
}
|
||||
if (IsEmpty)
|
||||
return;
|
||||
if (isShowReward)
|
||||
{
|
||||
ShowData showData = new ShowData(_items, rewardType);
|
||||
showData.textValue = textValue;
|
||||
//UI_FishingRewardPanel_101041
|
||||
game.PlayerDataStorage.PlayerSaveAction.Present(() => GContext.Publish(showData));
|
||||
}
|
||||
_playerItemData.AddItem(_items, null);
|
||||
Reset();
|
||||
UploadData();
|
||||
}
|
||||
|
||||
private void StashItemsByDropList(EventStashDropList e)
|
||||
{
|
||||
foreach (var dropId in e.DropList)
|
||||
{
|
||||
var items = _playerItemData.GetItemDataByDropIdLureInflation(e.Inflate, dropId);
|
||||
foreach (var item in items)
|
||||
{
|
||||
item.changeSource = e.changeSource;
|
||||
StashItem(item);
|
||||
}
|
||||
}
|
||||
UploadData();
|
||||
}
|
||||
|
||||
private void StashItemsByDrop(EventStashDrop e)
|
||||
{
|
||||
var items = _playerItemData.GetItemDataByDropIdLureInflation(e.Inflate, e.DropId);
|
||||
foreach (var item in items)
|
||||
{
|
||||
item.changeSource = e.changeSource;
|
||||
StashItem(item);
|
||||
}
|
||||
UploadData();
|
||||
}
|
||||
|
||||
private void StashItems(EventStashItems e)
|
||||
{
|
||||
var items = e.Items;
|
||||
foreach (var item in items)
|
||||
{
|
||||
StashItem(item);
|
||||
}
|
||||
UploadData();
|
||||
}
|
||||
|
||||
private void StashItem(ItemData item)
|
||||
{
|
||||
if (!_itemTable.DataMap.ContainsKey(item.id))
|
||||
{
|
||||
//Debug.LogError($"Item id {item.id} not found in item table.");
|
||||
return;
|
||||
}
|
||||
// Debug.Log($"[RewardStash] Item {item.id} * {item.count} Stashed.");
|
||||
var itemDropPackageItems = GetItemDropPackageItemList(item);
|
||||
if (itemDropPackageItems != null && itemDropPackageItems.Count > 0)
|
||||
{
|
||||
GContext.container.Resolve<PlayerItemData>().LureInflation(itemDropPackageItems, item.inflate);
|
||||
foreach (var dropItem in itemDropPackageItems)
|
||||
{
|
||||
dropItem.changeSource = item.changeSource;
|
||||
_items.Add(dropItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_items.Add(item);
|
||||
}
|
||||
|
||||
UploadData();
|
||||
// _playerItemData.AddItem(item);
|
||||
}
|
||||
List<ItemData> GetItemDropPackageItemList(ItemData itemData)
|
||||
{
|
||||
Item item = _itemTable.GetOrDefault(itemData.id);
|
||||
if (item.Type == 9)
|
||||
{
|
||||
switch (item.SubType)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
return _playerItemData.GetItemDropPackageItemList(item.RedirectID, itemData.count);
|
||||
case 7:
|
||||
case 8:
|
||||
return _playerItemData.GetItemDropItemList(item.RedirectID, itemData.count);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private string Serialize()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var item in _items)
|
||||
sb.Append(item.id + Comma + (int)item.count + Splitter);
|
||||
if (sb.Length > 0)
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private List<ItemData> Deserialize(string s)
|
||||
{
|
||||
if (s == null || s == "")
|
||||
return new List<ItemData>();
|
||||
var items = s.Split(Splitter);
|
||||
var res = new List<ItemData>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
var split = item.Split(Comma);
|
||||
if (split.Length != 2)
|
||||
{
|
||||
Debug.LogWarning($"[DeferredRewardStashService]Wrong amount of parameters in \"{item}\".");
|
||||
continue;
|
||||
}
|
||||
var id = int.Parse(split[0]);
|
||||
var count = int.Parse(split[1]);
|
||||
var itemData = new ItemData(id, count);
|
||||
res.Add(itemData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void UploadData()
|
||||
{
|
||||
var s = Serialize();
|
||||
saveStore.Write(Key, s).RequireAccepted();
|
||||
}
|
||||
|
||||
public void LoadData()
|
||||
{
|
||||
var s = saveStore.Read(Key).ValueOrThrow();
|
||||
Reset();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return;
|
||||
_items = Deserialize(s);
|
||||
}
|
||||
|
||||
public class EventStashItems
|
||||
{
|
||||
public List<ItemData> Items;
|
||||
}
|
||||
|
||||
public class EventStashDrop
|
||||
{
|
||||
public int DropId;
|
||||
public float Inflate = 0;
|
||||
public ChangeSource changeSource;
|
||||
}
|
||||
|
||||
public class EventStashDropList
|
||||
{
|
||||
public List<int> DropList;
|
||||
public ChangeSource changeSource;
|
||||
public float Inflate = 0;
|
||||
}
|
||||
|
||||
public class EventStashItem
|
||||
{
|
||||
public ItemData Item;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user