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,354 @@
|
||||
using System.Text;
|
||||
using asap.core;
|
||||
using GameCore;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class EventOfferJourneyData : AEventOfferJourneyData
|
||||
{
|
||||
private int _progress, _eventId, _ticketCount, _vipLvlOnTrigger, _roundCount;
|
||||
private float _inflationRate;
|
||||
private EventOfferJourneyTableContext _ctx;
|
||||
public override int Progress => _progress;
|
||||
public override int TicketCount => _ticketCount;
|
||||
public override int EventId => _eventId;
|
||||
public override float InflationRate => _inflationRate;
|
||||
public override ShopBuyType BuyType => ShopBuyType.EventPack;
|
||||
public int VipLvlOnTrigger => _vipLvlOnTrigger;
|
||||
|
||||
public void Init(int eventId, int vipLvl)
|
||||
{
|
||||
_progress = 0;
|
||||
_eventId = eventId;
|
||||
_ticketCount = 0;
|
||||
_vipLvlOnTrigger = vipLvl;
|
||||
_roundCount = 0;
|
||||
_ctx = EventOfferJourneyTableContext.CreateNew(eventId);
|
||||
_inflationRate = GContext.container.Resolve<PlayerData>().InflationRate;
|
||||
}
|
||||
|
||||
public void InitTest()
|
||||
{
|
||||
_progress = 0;
|
||||
_eventId = 90500001;
|
||||
_ticketCount = 114514;
|
||||
_vipLvlOnTrigger = GContext.container.Resolve<PlayerData>().PriceLv;
|
||||
_roundCount = 0;
|
||||
_ctx = EventOfferJourneyTableContext.GetTestSample();
|
||||
}
|
||||
|
||||
private EventOfferJourneyPlayfabData ToPlayfabData()
|
||||
{
|
||||
return new EventOfferJourneyPlayfabData(_eventId, _progress, _ticketCount, _vipLvlOnTrigger, _roundCount, _inflationRate);
|
||||
}
|
||||
|
||||
public override bool AddTicket(int n)
|
||||
{
|
||||
_ticketCount += n;
|
||||
if (_ticketCount < 0)
|
||||
{
|
||||
_ticketCount -= n;
|
||||
return false;
|
||||
}
|
||||
SaveData();
|
||||
// GContext.container.Resolve<FishingEventData>().SaveTransitionData(_eventId, _ticketCount);
|
||||
GContext.Publish(new EventTicketUpdate());
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnBuySuccess()
|
||||
{
|
||||
if (_ctx == null)
|
||||
{
|
||||
Debug.LogError($"[EventOfferJourney]Trying to buy pack but there is no context.");
|
||||
return;
|
||||
}
|
||||
if (_progress >= _ctx.GetRewardList(_vipLvlOnTrigger).Count)
|
||||
{
|
||||
Debug.LogError($"[EventOfferJourney]Trying to buy pack no.{_progress} but there are only {_ctx.GetRewardList(_vipLvlOnTrigger).Count} rewards.");
|
||||
return;
|
||||
}
|
||||
_progress++;
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public override void ProgressUp()
|
||||
{
|
||||
if (_ctx == null)
|
||||
{
|
||||
Debug.LogError($"[EventOfferJourney]Trying to progress pack but there is no context.");
|
||||
return;
|
||||
}
|
||||
_progress++;
|
||||
if (_progress >= _ctx.GetRewardList(_vipLvlOnTrigger).Count)
|
||||
{
|
||||
_progress = 0;
|
||||
_roundCount++;
|
||||
Debug.Log($"[EventOfferJourney] Update vip level from {_vipLvlOnTrigger}");
|
||||
_vipLvlOnTrigger = GContext.container.Resolve<PlayerData>().PriceLv;
|
||||
Debug.Log($"[EventOfferJourney] to {_vipLvlOnTrigger}");
|
||||
}
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public override void SaveData()
|
||||
{
|
||||
ToPlayfabData().Save();
|
||||
}
|
||||
|
||||
public override bool LoadDataFromPlayfab()
|
||||
{
|
||||
var pfData = EventOfferJourneyPlayfabData.Load();
|
||||
if (pfData == null)
|
||||
return false;
|
||||
_eventId = pfData.EventId;
|
||||
_inflationRate = pfData.InflationRate;
|
||||
_progress = pfData.Progress;
|
||||
_ticketCount = pfData.TicketCount;
|
||||
_vipLvlOnTrigger = pfData.VipLvlOnTrigger;
|
||||
_roundCount = pfData.RoundCount;
|
||||
_ctx = EventOfferJourneyTableContext.CreateNew(_eventId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override EventOfferJourneyEntranceData ToEntranceData()
|
||||
{
|
||||
if (_ctx == null)
|
||||
{
|
||||
return new EventOfferJourneyEntranceData(false, TimeSpan.Zero, "", false);
|
||||
}
|
||||
(var startTime, var endTime) = _ctx.GetEventStartTimeAndEndTime();
|
||||
var isActive = ZZTimeHelper.UtcNow() >= startTime && ZZTimeHelper.UtcNow() < endTime && _roundCount < _ctx.MaxRoundCount;
|
||||
var remainingTime = endTime - ZZTimeHelper.UtcNow();
|
||||
var iconUrl = _ctx.EntranceIconUrl;
|
||||
var cost = _ctx.GetTicketCostByProgress(_progress, _vipLvlOnTrigger);
|
||||
var doNeedRedPoint = cost > 0 && cost <= _ticketCount;
|
||||
var res = new EventOfferJourneyEntranceData(isActive, remainingTime, iconUrl, doNeedRedPoint);
|
||||
return res;
|
||||
}
|
||||
|
||||
public override List<EventOfferJourneyBlockData> GetRewardList()
|
||||
{
|
||||
if (_ctx == null)
|
||||
return new List<EventOfferJourneyBlockData>();
|
||||
return _ctx.GetRewardList(_vipLvlOnTrigger);
|
||||
}
|
||||
|
||||
public override ITimerContext ToTimerData(Action OnExpire)
|
||||
{
|
||||
if (_ctx == null)
|
||||
{
|
||||
Debug.LogError($"[EventOfferJourney]Trying to get timer data but there is no context.");
|
||||
return new TimerContext();
|
||||
}
|
||||
var res = new TimerContext
|
||||
{
|
||||
StartTime = _ctx.GetEventStartTimeAndEndTime().Item1,
|
||||
ExpiryTime = _ctx.GetEventStartTimeAndEndTime().Item2,
|
||||
OnExpire = OnExpire
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
public override EventOfferJourneyUiData GetUiData()
|
||||
{
|
||||
return _ctx.GetUiData();
|
||||
}
|
||||
|
||||
public override int[] GetTicketRewardArray()
|
||||
{
|
||||
return _ctx.GetTicketRewardArray();
|
||||
}
|
||||
|
||||
public override string GetTicketName()
|
||||
{
|
||||
return _ctx.GetTicketName();
|
||||
}
|
||||
|
||||
public override void OnRaid(int multiplier = 1)
|
||||
{
|
||||
int rewardCount = _ctx.GetTicketRewardArray()[0] * multiplier;
|
||||
GContext.Publish(new game.TargetAddData(_ctx.GetTicketId(), TicketCount, rewardCount));
|
||||
AddTicket(rewardCount);
|
||||
}
|
||||
|
||||
public override void OnBomb(int multiplier = 1)
|
||||
{
|
||||
int rewardCount = _ctx.GetTicketRewardArray()[1] * multiplier;
|
||||
GContext.Publish(new game.TargetAddData(_ctx.GetTicketId(), TicketCount, rewardCount));
|
||||
AddTicket(rewardCount);
|
||||
}
|
||||
|
||||
public override int GetStartPosParam()
|
||||
{
|
||||
return _ctx.GetStartPosParam();
|
||||
}
|
||||
}
|
||||
public abstract class AEventOfferJourneyData : IEventOfferJourneyData
|
||||
{
|
||||
public abstract int Progress { get; }
|
||||
public abstract int TicketCount { get; }
|
||||
public abstract int EventId { get; }
|
||||
public abstract float InflationRate { get; }
|
||||
public abstract ShopBuyType BuyType { get; }
|
||||
public string RedPointKey => "event_offer_journey.entrance";
|
||||
public abstract bool AddTicket(int n);
|
||||
public abstract List<EventOfferJourneyBlockData> GetRewardList();
|
||||
public abstract int GetStartPosParam();
|
||||
public abstract string GetTicketName();
|
||||
public abstract int[] GetTicketRewardArray();
|
||||
public abstract EventOfferJourneyUiData GetUiData();
|
||||
public abstract bool LoadDataFromPlayfab();
|
||||
public abstract void OnBomb(int multiplier = 1);
|
||||
public abstract void OnBuySuccess();
|
||||
public abstract void OnRaid(int multiplier = 1);
|
||||
public abstract void ProgressUp();
|
||||
public abstract void SaveData();
|
||||
public abstract EventOfferJourneyEntranceData ToEntranceData();
|
||||
public abstract ITimerContext ToTimerData(Action OnExpire);
|
||||
}
|
||||
|
||||
public interface IEventOfferJourneyData
|
||||
{
|
||||
public int Progress { get; }
|
||||
public int TicketCount { get; }
|
||||
public int EventId { get; }
|
||||
public float InflationRate { get; }
|
||||
public ShopBuyType BuyType { get; }
|
||||
public bool AddTicket(int n);
|
||||
public bool LoadDataFromPlayfab();
|
||||
public void SaveData();
|
||||
public void ProgressUp();
|
||||
public void OnBuySuccess();
|
||||
public List<EventOfferJourneyBlockData> GetRewardList();
|
||||
public EventOfferJourneyEntranceData ToEntranceData();
|
||||
public EventOfferJourneyUiData GetUiData();
|
||||
public ITimerContext ToTimerData(Action OnExpire);
|
||||
public int[] GetTicketRewardArray();
|
||||
public string GetTicketName();
|
||||
public void OnRaid(int multiplier = 1);
|
||||
public void OnBomb(int multiplier = 1);
|
||||
public int GetStartPosParam();
|
||||
public string RedPointKey { get; }
|
||||
}
|
||||
|
||||
public class EventOfferJourneyBlockData
|
||||
{
|
||||
public enum EType { IAP, Ticket }
|
||||
public EType Type;
|
||||
public int Price, DropId;
|
||||
private EventOfferJourneyBlockData() { }
|
||||
|
||||
public static EventOfferJourneyBlockData CreateIapData(int iapId, int dropId)
|
||||
{
|
||||
var data = new EventOfferJourneyBlockData();
|
||||
data.Type = EType.IAP;
|
||||
data.Price = iapId;
|
||||
data.DropId = dropId;
|
||||
return data;
|
||||
}
|
||||
|
||||
public static EventOfferJourneyBlockData CreateTicketData(int ticketCost, int dropId)
|
||||
{
|
||||
var data = new EventOfferJourneyBlockData();
|
||||
data.Type = EType.Ticket;
|
||||
data.Price = ticketCost;
|
||||
data.DropId = dropId;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public class EventOfferJourneyPlayfabData
|
||||
{
|
||||
readonly game.PlayerDataStorage.IPlayerSaveStore saveStore = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>();
|
||||
|
||||
public int EventId, Progress, TicketCount, VipLvlOnTrigger, RoundCount;
|
||||
public float InflationRate;
|
||||
private const string Key = "EventOfferJourneyData";
|
||||
private const int TokenCount = 6;
|
||||
private const char Splitter = '|', Comma = ',';
|
||||
|
||||
public EventOfferJourneyPlayfabData(int eventId, int progress, int ticketCount, int vipLvlOnTrigger, int roundCount, float inflationRate)
|
||||
{
|
||||
EventId = eventId;
|
||||
Progress = progress;
|
||||
TicketCount = ticketCount;
|
||||
VipLvlOnTrigger = vipLvlOnTrigger;
|
||||
RoundCount = roundCount;
|
||||
InflationRate = inflationRate;
|
||||
}
|
||||
|
||||
private string Serialize()
|
||||
{
|
||||
var res = new StringBuilder();
|
||||
res.Append(EventId).Append(Splitter)
|
||||
.Append(Progress).Append(Splitter)
|
||||
.Append(TicketCount).Append(Splitter)
|
||||
.Append(VipLvlOnTrigger).Append(Splitter)
|
||||
.Append(RoundCount).Append(Splitter)
|
||||
.Append(InflationRate);
|
||||
return res.ToString();
|
||||
}
|
||||
|
||||
private static EventOfferJourneyPlayfabData Deserialize(string s)
|
||||
{
|
||||
if (s == null || s == "")
|
||||
return null;
|
||||
var tokens = s.Trim(Splitter).Split(Splitter);
|
||||
if (tokens.Length != TokenCount && tokens.Length != TokenCount - 1)
|
||||
{
|
||||
Debug.LogError($"[EventOfferJourney]Wrong amount of parameters. Expect {TokenCount}, but got {tokens.Length} in \"{s}\".");
|
||||
return null;
|
||||
}
|
||||
|
||||
var eventId = int.Parse(tokens[0]);
|
||||
var progress = int.Parse(tokens[1]);
|
||||
var ticketCount = int.Parse(tokens[2]);
|
||||
var vipLvlOnTrigger = int.Parse(tokens[3]);
|
||||
var roundCount = int.Parse(tokens[4]);
|
||||
float inflationRate = 0;
|
||||
if (tokens.Length == TokenCount)
|
||||
{
|
||||
inflationRate = float.Parse(tokens[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Old data detected, missing inflation rate. Setting to 0.");
|
||||
}
|
||||
return new EventOfferJourneyPlayfabData(eventId, progress, ticketCount, vipLvlOnTrigger, roundCount, inflationRate);
|
||||
}
|
||||
|
||||
public static EventOfferJourneyPlayfabData Load()
|
||||
{
|
||||
var s = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>().Read(Key).ValueOrThrow();
|
||||
return Deserialize(s);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var s = Serialize();
|
||||
saveStore.Write(Key, s).RequireAccepted();
|
||||
}
|
||||
}
|
||||
|
||||
public class EventOfferJourneyEntranceData
|
||||
{
|
||||
public bool IsActive { get; }
|
||||
public TimeSpan RemainingTime { get; }
|
||||
public string IconUrl { get; }
|
||||
public bool DoNeedRedPoint { get; }
|
||||
public EventOfferJourneyEntranceData(bool isActive, TimeSpan remainingTime, string iconUrl, bool doNeedRedPoint)
|
||||
{
|
||||
IsActive = isActive;
|
||||
RemainingTime = remainingTime;
|
||||
IconUrl = iconUrl;
|
||||
DoNeedRedPoint = doNeedRedPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public class EventOfferJourneyUiData
|
||||
{
|
||||
public string PanelUrl { get; set; }
|
||||
public string InfoPanelUrl { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user