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,321 @@
|
||||
using asap.core;
|
||||
using cfg;
|
||||
using GameCore;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using game;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class BargainPackData
|
||||
{
|
||||
[asap.core.Inject] public game.PlayerDataStorage.IPlayerSaveStore SaveStore { get; set; }
|
||||
|
||||
private readonly Tables _tables = GContext.container.Resolve<Tables>();
|
||||
private readonly TbEventPackManager _epm = GContext.container.Resolve<Tables>().TbEventPackManager;
|
||||
private readonly TbSpecialPack _spp = GContext.container.Resolve<Tables>().TbSpecialPack;
|
||||
private GeneralEventPackData _data;
|
||||
|
||||
private bool _kvLoadPresent;
|
||||
#if UNITY_EDITOR
|
||||
internal bool SelectionsAreIndependentForKVValidation()
|
||||
{
|
||||
var source = new List<int> { 7, 9 };
|
||||
var state = new game.PlayerDataStorage.PlayerKVBargainState(true,0,_data.redirectID,0,0,0,0,0,0,0,0,0,false,false,0,source);
|
||||
ReplaceFromKVDecoded(state);
|
||||
source.Clear();
|
||||
if (_data.selections.Count != 2 || ReferenceEquals(_data.selections, source) || ReferenceEquals(_data.selections, state.selections)) return false;
|
||||
var previous = _data.selections;
|
||||
_data.selections[0] = 10;
|
||||
if (state.selections[0] != 7) return false;
|
||||
ResetForKVLoad();
|
||||
return _data.selections.Count == 0 && !ReferenceEquals(previous, _data.selections) && !_kvLoadPresent;
|
||||
}
|
||||
#endif
|
||||
internal bool KVLoadPresent => _kvLoadPresent;
|
||||
internal static game.PlayerDataStorage.PlayerKVBargainState DecodeForKVLoad(
|
||||
IReadOnlyDictionary<string, string> raw, game.PlayerDataStorage.PlayerKVSchemaSnapshot snapshot,
|
||||
game.PlayerDataStorage.PlayerKVSchemaDiagnostics errors) =>
|
||||
game.PlayerDataStorage.PlayerKVSaveSchema.DecodeBargain(raw, snapshot, errors);
|
||||
|
||||
internal void ResetForKVLoad()
|
||||
{
|
||||
_kvLoadPresent = false;
|
||||
_data = default(GeneralEventPackData);
|
||||
_data.selections = new List<int>();
|
||||
}
|
||||
internal void ReplaceFromKVDecoded(game.PlayerDataStorage.PlayerKVBargainState state)
|
||||
{
|
||||
if (state == null) throw new ArgumentNullException(nameof(state));
|
||||
if (!state.IsPresent) { ResetForKVLoad(); return; }
|
||||
var replacement = new GeneralEventPackData
|
||||
{
|
||||
currentEventID = state.currentEventID,
|
||||
redirectID = state.redirectID,
|
||||
VIPLvlWhenEventActivate = state.VIPLvlWhenEventActivate,
|
||||
purchaseCount = state.purchaseCount,
|
||||
savingProgress = state.savingProgress,
|
||||
discountLvl = state.discountLvl,
|
||||
visualProgress = state.visualProgress,
|
||||
visualDiscountLvl = state.visualDiscountLvl,
|
||||
rodID = state.rodID,
|
||||
lastPackIDBought = state.lastPackIDBought,
|
||||
packID = state.packID,
|
||||
doNeedTrigger = state.doNeedTrigger,
|
||||
isTriggered = state.isTriggered,
|
||||
inflation = state.inflation,
|
||||
selections = state.selections == null ? null : new List<int>(state.selections),
|
||||
};
|
||||
_data = replacement;
|
||||
_kvLoadPresent = true;
|
||||
}
|
||||
internal game.PlayerDataStorage.PlayerKVBargainState SnapshotForKVValidation() =>
|
||||
new game.PlayerDataStorage.PlayerKVBargainState(_kvLoadPresent, _data.currentEventID, _data.redirectID, _data.VIPLvlWhenEventActivate, _data.purchaseCount, _data.savingProgress, _data.discountLvl, _data.visualProgress, _data.visualDiscountLvl, _data.rodID, _data.lastPackIDBought, _data.packID, _data.doNeedTrigger, _data.isTriggered, _data.inflation, _data.selections);
|
||||
|
||||
public int CurrentEventID => _data.currentEventID;
|
||||
|
||||
public FishingEvent CurrentEvent => _tables.TbFishingEvent[_data.currentEventID];
|
||||
|
||||
public TimeSpan RemainingTime =>
|
||||
DateTime.Parse((_tables.TbFishingEvent[_data.currentEventID].TimeDefinition as LimitedTime).EndTime) -
|
||||
ZZTimeHelper.UtcNow();
|
||||
|
||||
public bool IsWithinEventTime
|
||||
{
|
||||
get
|
||||
{
|
||||
var fishingEvent = _tables.TbFishingEvent.GetOrDefault(CurrentEventID);
|
||||
if (!(fishingEvent?.TimeDefinition is LimitedTime time)) return false;
|
||||
|
||||
var et = DateTime.Parse(time.EndTime);
|
||||
var st = DateTime.Parse(time.StartTime);
|
||||
return ZZTimeHelper.UtcNow() >= st && ZZTimeHelper.UtcNow() < et;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPackActivated
|
||||
{
|
||||
get
|
||||
{
|
||||
bool res = _tables.TbFishingEvent.DataMap.ContainsKey(_data.currentEventID)
|
||||
&& _epm.DataMap.ContainsKey(_data.redirectID)
|
||||
&& _epm[_data.redirectID].PackType == 3
|
||||
&& IsWithinEventTime
|
||||
&& _data.isTriggered
|
||||
&& _data.purchaseCount < _epm[_data.redirectID].MaxCount;
|
||||
//Debug.Log(_tables.TbFishingEvent.DataMap.ContainsKey(_data.currentEventID));
|
||||
//Debug.Log(_epm.DataMap.ContainsKey(_data.redirectID));
|
||||
//Debug.Log(_epm[_data.redirectID].PackType == 3);
|
||||
//Debug.Log(IsWithinEventTime);
|
||||
//Debug.Log(_data.isTriggered);
|
||||
//Debug.Log(_data.purchaseCount < _epm[_data.redirectID].MaxCount);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public int RedirectID => _data.redirectID;
|
||||
public bool DoNeedTrigger => _data.doNeedTrigger;
|
||||
public int PackID => _epm[_data.redirectID].VIPPackList[_data.VIPLvlWhenEventActivate][0];
|
||||
public int DiscountLvlCount => _spp[PackID].IAPID.Count;
|
||||
public int DiscountLvl => _data.discountLvl;
|
||||
public int PurchaseCount => _data.purchaseCount;
|
||||
public int Progress => _data.savingProgress;
|
||||
public int VIPLvlWhenEventActivated => _data.VIPLvlWhenEventActivate;
|
||||
public int ActivateItemId => _spp[PackID].ActivateItemId;
|
||||
public string ActiveItemImg => _spp[PackID].ActiveItemImg;
|
||||
public int EventItemId => IsPackActivated ? _spp[PackID].EventItemId : 0;
|
||||
public int RewardDropID => _spp[PackID].DropID[0];
|
||||
public int MaxCount => _epm[_data.redirectID].MaxCount;
|
||||
public float Inflation => _data.inflation;
|
||||
|
||||
public int NextTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
int lvl = _data.discountLvl >= DiscountLvlCount - 1 ? DiscountLvlCount - 1 : _data.discountLvl + 1;
|
||||
int count = _spp[PackID].EventItemRequire[lvl];
|
||||
PlayerItemData playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||||
count = playerItemData.IntInflation(count, _data.inflation);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFull => _data.discountLvl >= DiscountLvlCount - 1 && _data.savingProgress >= NextTarget;
|
||||
public int IAPID => _spp[PackID].IAPID[DiscountLvl];
|
||||
public List<int> FishingScoreList => _spp[PackID].EventItemGet;
|
||||
public int NextDiscount
|
||||
{
|
||||
get
|
||||
{
|
||||
int lvl = _data.discountLvl >= DiscountLvlCount - 1 ? DiscountLvlCount - 1 : _data.discountLvl + 1;
|
||||
return _spp[PackID].DiscountList[lvl];
|
||||
}
|
||||
}
|
||||
public int VisualProgress => _data.visualProgress;
|
||||
public int VisualDiscountLvl => _data.visualDiscountLvl;
|
||||
public int NextVisualTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
int lvl = _data.visualDiscountLvl >= DiscountLvlCount - 1
|
||||
? DiscountLvlCount - 1
|
||||
: _data.visualDiscountLvl + 1;
|
||||
int EventItemRequire = _spp[PackID].EventItemRequire[lvl];
|
||||
PlayerItemData playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||||
EventItemRequire = playerItemData.IntInflation(EventItemRequire, _data.inflation);
|
||||
return EventItemRequire;
|
||||
}
|
||||
}
|
||||
|
||||
public int NextVisualDiscount
|
||||
{
|
||||
get
|
||||
{
|
||||
int lvl = _data.visualDiscountLvl >= DiscountLvlCount - 1
|
||||
? DiscountLvlCount - 1
|
||||
: _data.visualDiscountLvl + 1;
|
||||
return _spp[PackID].DiscountList[lvl];
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveData()
|
||||
{
|
||||
//Debug.LogError("Testing, data not saved for debug purpose.");
|
||||
SaveStore.Write("GeneralEventPackData",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(_data)).RequireAccepted();
|
||||
}
|
||||
|
||||
public void LoadData(GeneralEventPackData data)
|
||||
{
|
||||
_data = data;
|
||||
if (IsPackActivated && IsFull)
|
||||
{
|
||||
GContext.container.Resolve<IFaceUIService>().AddGiftFaceUIForce(_data.currentEventID, UITypes.GiftBargainPopupPanel);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateData(FishingEvent e)
|
||||
{
|
||||
if (_epm[_tables.TbFishingEvent[e.ID].RedirectID].PackType != 3)
|
||||
{
|
||||
Debug.LogError($"Fishing event ID {e.ID} is not a Bargain back event");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_data.currentEventID != e.ID)
|
||||
{
|
||||
_data = new GeneralEventPackData(
|
||||
eventID: e.ID,
|
||||
vip: GContext.container.Resolve<PlayerData>().PriceLv,
|
||||
redirectID: e.RedirectID,
|
||||
savingProgress: 0,
|
||||
discountLvl: 0,
|
||||
isTriggered: false,
|
||||
doNeedTrigger: true,
|
||||
visualProgress: 0,
|
||||
visualDiscountLvl: 0,
|
||||
purchaseCount: 0,
|
||||
inflation: GContext.container.Resolve<PlayerData>().InflationRate);
|
||||
}
|
||||
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public void TriggerPack()
|
||||
{
|
||||
_data.doNeedTrigger = false;
|
||||
_data.isTriggered = true;
|
||||
int EventItemCountFirst = _spp[PackID].EventItemCountFirst;
|
||||
PlayerItemData playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||||
EventItemCountFirst = playerItemData.IntInflation(EventItemCountFirst, _data.inflation);
|
||||
AddProgress(EventItemCountFirst);
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public void AddProgress(int progress)
|
||||
{
|
||||
if (progress <= 0 || IsFull)
|
||||
return;
|
||||
_data.savingProgress += progress;
|
||||
while (_data.savingProgress >= NextTarget)
|
||||
{
|
||||
//DoUICut = true;
|
||||
_data.savingProgress -= NextTarget;
|
||||
_data.discountLvl++;
|
||||
if (_data.discountLvl >= DiscountLvlCount - 1)
|
||||
{
|
||||
_data.savingProgress = NextTarget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SaveData();
|
||||
return;
|
||||
}
|
||||
|
||||
public void AddProgress(int fishTier, int magnification)
|
||||
{
|
||||
if (!IsPackActivated || fishTier < 1 || fishTier > 5)
|
||||
{
|
||||
//Debug.LogError($"Fish Tier {fishTier} not defined in TbSpedialPack");
|
||||
return;
|
||||
}
|
||||
|
||||
int progress = _spp[PackID].EventItemGet[fishTier - 1] * magnification;
|
||||
if (progress <= 0 || IsFull)
|
||||
return;
|
||||
|
||||
int curProgress = _data.savingProgress;
|
||||
_data.savingProgress += progress;
|
||||
GContext.Publish(new TargetAddData(EventItemId, curProgress, progress));
|
||||
while (_data.savingProgress >= NextTarget)
|
||||
{
|
||||
//DoUICut = true;
|
||||
_data.savingProgress -= NextTarget;
|
||||
_data.discountLvl++;
|
||||
if (_data.discountLvl >= DiscountLvlCount - 1)
|
||||
{
|
||||
GContext.container.Resolve<IFaceUIService>()
|
||||
.AddGiftFaceUIForce(CurrentEventID, UITypes.GiftBargainPopupPanel);
|
||||
_data.savingProgress = NextTarget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SaveData();
|
||||
return;
|
||||
}
|
||||
|
||||
public void AddPurchase()
|
||||
{
|
||||
_data.purchaseCount++;
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public void RefreshVisualData()
|
||||
{
|
||||
_data.visualDiscountLvl = _data.discountLvl;
|
||||
_data.visualProgress = _data.savingProgress;
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public int GetNextDiscountTarget(int l)
|
||||
{
|
||||
int lvl = l >= DiscountLvlCount - 1 ? DiscountLvlCount - 1 : l + 1;
|
||||
int count = _spp[PackID].EventItemRequire[lvl];
|
||||
PlayerItemData playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||||
count = playerItemData.IntInflation(count, _data.inflation);
|
||||
return count;
|
||||
}
|
||||
|
||||
public int GetNextDiscount(int l)
|
||||
{
|
||||
int lvl = l >= DiscountLvlCount - 1 ? DiscountLvlCount - 1 : l + 1;
|
||||
return _spp[PackID].DiscountList[lvl];
|
||||
}
|
||||
}
|
||||
|
||||
public class BargainPackProgressEvent
|
||||
{
|
||||
public int type; //0: 初始化 1:增加动画
|
||||
public int addProgress;
|
||||
}
|
||||
Reference in New Issue
Block a user