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,300 @@
|
||||
using asap.core;
|
||||
using cfg;
|
||||
using GameCore;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UI.Wheel;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.UI.AdWheel
|
||||
{
|
||||
public class AdWheelManager:IDisposable
|
||||
{
|
||||
readonly game.PlayerDataStorage.IPlayerSaveStore saveStore = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>();
|
||||
|
||||
|
||||
public AdWheelManager()
|
||||
{
|
||||
GContext.OnEvent<TargetEvent>().Subscribe(OnEvent_TargetEvent).AddTo(Disposables);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_disposableSimple?.Dispose();
|
||||
Disposables?.Dispose();
|
||||
}
|
||||
|
||||
private CompositeDisposable _disposable;
|
||||
private CompositeDisposable Disposables => _disposable ??= new CompositeDisposable();
|
||||
#region event
|
||||
private void OnEvent_TargetEvent(TargetEvent targetEvent)
|
||||
{
|
||||
if (targetEvent.type == 2 && targetEvent.subType == 4)
|
||||
{
|
||||
//只有一个广告转盘
|
||||
RefreshData(targetEvent.id);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region data
|
||||
[Inject]
|
||||
public Tables Tables { get; set; }
|
||||
private AdWheelData _adWheelData;
|
||||
public AdWheelData Data => _adWheelData ??= new AdWheelData(Tables);
|
||||
private void RefreshData(int eventId)
|
||||
{
|
||||
//判断开启时间
|
||||
var fishingEvent = Tables.TbFishingEvent.GetOrDefault(eventId);
|
||||
if (fishingEvent == null) return;
|
||||
var daily = fishingEvent.TimeDefinition as Daily;
|
||||
var now = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||||
var refreshTime = new DateTimeOffset(now).ToUnixTimeSeconds() + (daily.EndTime - (long)now.TimeOfDay.TotalSeconds);
|
||||
var cacheData = GetCachedData();
|
||||
if (cacheData != null && cacheData.ActiveEventTime > 0)
|
||||
{
|
||||
this.Data.SetData(cacheData);
|
||||
if (this.Data.EventRefreshTimeSeconds != refreshTime)
|
||||
{
|
||||
this.Data.EventRefreshTimeSeconds = refreshTime;
|
||||
this.Data.ClearProgress();
|
||||
SaveData();
|
||||
}
|
||||
if (this.Data.EventID != eventId)
|
||||
{
|
||||
this.Data.EventID = eventId;
|
||||
SaveData();
|
||||
}
|
||||
SetRedPoint();
|
||||
CheckIsAddGiftFaceUI();
|
||||
return;
|
||||
}
|
||||
|
||||
bool isOpenEvent = IsOpenEvent(eventId);
|
||||
if (!isOpenEvent) return;
|
||||
|
||||
InitData(eventId, now, refreshTime);
|
||||
SaveData();
|
||||
}
|
||||
|
||||
private void InitData(int eventId, DateTime now, long refreshTime)
|
||||
{
|
||||
var nowTimeSeconds = new DateTimeOffset(now).ToUnixTimeSeconds();
|
||||
this.Data.EventID = eventId;
|
||||
this.Data.lastViewAdTime = 0;
|
||||
this.Data.ActiveEventTime = nowTimeSeconds;
|
||||
this.Data.EventRefreshTimeSeconds = refreshTime;
|
||||
this.Data.ClearProgress();
|
||||
CheckIsAddGiftFaceUI();
|
||||
}
|
||||
|
||||
private void CheckIsAddGiftFaceUI()
|
||||
{
|
||||
if(Data.IsActive&&GetRedPointState())
|
||||
GContext.container.Resolve<IFaceUIService>().AddGiftFaceUI(Data.EventID, UITypes.EventBonusWheelPopupPanel, 0);
|
||||
}
|
||||
|
||||
private AdWheelData GetCachedData()
|
||||
{
|
||||
var dataStr = saveStore.Read(nameof(AdWheelData)).ValueOrThrow();
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log($"jsd AdWheelData LoadData sData {dataStr}");
|
||||
#endif
|
||||
return dataStr == null ? null : JsonConvert.DeserializeObject<AdWheelData>(dataStr) ?? throw new JsonSerializationException("Null AdWheelData save.");
|
||||
}
|
||||
|
||||
private bool IsOpenEvent(int eventId)
|
||||
{
|
||||
var eventConfig = Tables.TbFishingEvent.GetOrDefault(eventId);
|
||||
if (eventConfig == null) return true;
|
||||
var isOpen = GContext.container.Resolve<FishingEventData>()?.Condition(eventConfig) ?? false;
|
||||
return isOpen;
|
||||
}
|
||||
public void SaveData()
|
||||
{
|
||||
SetRedPoint();
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log($"jsd AdWheelData SaveData {JsonConvert.SerializeObject(Data)}");
|
||||
#endif
|
||||
saveStore.Write(nameof(AdWheelData), JsonConvert.SerializeObject(Data)).RequireAccepted();
|
||||
}
|
||||
|
||||
private List<IWheelReward> _rewards = new List<IWheelReward>();
|
||||
public List<IWheelReward> GetEventAdWheelRewards()
|
||||
{
|
||||
if (Data == null) return null;
|
||||
|
||||
if (_rewards == null)
|
||||
_rewards = new List<IWheelReward>();
|
||||
else
|
||||
_rewards.Clear();
|
||||
var adWheelMainID = Data.EventConfig.RedirectID;
|
||||
if (adWheelMainID <= 0) return null;
|
||||
|
||||
var adWheelMain = Data.AdWheelMain;
|
||||
if (adWheelMain == null) return null;
|
||||
|
||||
foreach (var id in adWheelMain.WheelRewardList)
|
||||
{
|
||||
var rewardConfig = Tables.TbEventAdWheelReward.Get(id);
|
||||
if (rewardConfig == null
|
||||
|| _rewards.Find(x => x.Index == rewardConfig.Index) != null)
|
||||
continue;
|
||||
_rewards.Add(new EventAdWheelRewardAdapter(rewardConfig,0));
|
||||
|
||||
}
|
||||
CalculateWeights();
|
||||
return _rewards;
|
||||
}
|
||||
|
||||
// 缓存数据
|
||||
private int totalWeight = 0;
|
||||
private List<int> weightRanges = new List<int>();
|
||||
|
||||
private void CalculateWeights()
|
||||
{
|
||||
totalWeight = _rewards.Sum(r => r.Weight);
|
||||
BuildWeightRanges();
|
||||
}
|
||||
private void BuildWeightRanges()
|
||||
{
|
||||
weightRanges.Clear();
|
||||
int currentWeight = 0;
|
||||
|
||||
foreach (var reward in _rewards)
|
||||
{
|
||||
currentWeight += reward.Weight;
|
||||
weightRanges.Add(currentWeight);
|
||||
}
|
||||
}
|
||||
|
||||
// 根据权重随机获取奖励
|
||||
public int GetRandomRewardIndex()
|
||||
{
|
||||
if (totalWeight <= 0)
|
||||
{
|
||||
Debug.LogError("总权重为0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int randomValue = UnityEngine.Random.Range(0, totalWeight);
|
||||
|
||||
for (int i = 0; i < weightRanges.Count; i++)
|
||||
{
|
||||
if (randomValue < weightRanges[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return _rewards.Count - 1;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static List<ItemData> GetProgressRewards(AdWheelData adWheelData)
|
||||
{
|
||||
if (adWheelData == null) return null;
|
||||
|
||||
var adWheelMainID = adWheelData.EventConfig.RedirectID;
|
||||
if (adWheelMainID <= 0) return null;
|
||||
|
||||
var adWheelMain = adWheelData.AdWheelMain;
|
||||
if (adWheelMain == null) return null;
|
||||
|
||||
List<ItemData> rewards = new List<ItemData>();
|
||||
foreach (var dropID in adWheelMain.ProgressRewardDropIDList)
|
||||
{
|
||||
var itemData = GContext.container.Resolve<PlayerItemData>().GetItemDataOne(dropID);
|
||||
if (itemData != null)
|
||||
rewards.Add(itemData);
|
||||
}
|
||||
return rewards;
|
||||
}
|
||||
public static bool GetProgressRewardByProgress(AdWheelData adWheelData, out int dropID)
|
||||
{
|
||||
dropID = -1;
|
||||
if (adWheelData == null) return false;
|
||||
|
||||
var adWheelMainID = adWheelData.EventConfig.RedirectID;
|
||||
if (adWheelMainID <= 0) return false;
|
||||
|
||||
var adWheelMain = adWheelData.AdWheelMain;
|
||||
if (adWheelMain == null) return false;
|
||||
|
||||
if (adWheelMain.ProgressRewardADTimeList == null)
|
||||
{
|
||||
Debug.LogError($"AdWheelManager GetProgressRewardByProgress adWheelMain {adWheelMain.ID} ProgressRewardADTimeList is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
var index = adWheelMain.ProgressRewardADTimeList.IndexOf(adWheelData.Count);
|
||||
if (index == -1) return false;
|
||||
|
||||
if (adWheelMain.ProgressRewardDropIDList == null)
|
||||
{
|
||||
Debug.LogError($"AdWheelManager GetProgressRewardByProgress adWheelMain {adWheelMain.ID} ProgressRewardDropIDList is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index > adWheelMain.ProgressRewardDropIDList.Count - 1)
|
||||
{
|
||||
Debug.LogError($"AdWheelManager GetProgressRewardByProgress adWheelMain {adWheelMain.ID} index error index:{index}");
|
||||
return false;
|
||||
}
|
||||
dropID = adWheelMain.ProgressRewardDropIDList[index];
|
||||
return true;
|
||||
}
|
||||
public bool IsOpen(FishingEventData data, FishingEvent fishingEvent,
|
||||
Func<EventCondition,bool> getEventCondition,
|
||||
Func<int, bool> Condition_NoRechargeSeconds)
|
||||
{
|
||||
//开过一次一直开
|
||||
var cacheData = GetCachedData();
|
||||
if (cacheData is { ActiveEventTime: > 0 })
|
||||
return true;
|
||||
for (int i = 0; i < fishingEvent.ConditionList.Count; i++)
|
||||
{
|
||||
var condition= fishingEvent.ConditionList[i];
|
||||
if (condition.Condition == ConditionType.NoRechargeSeconds)
|
||||
{
|
||||
var mmt = GContext.container.Resolve<MMTService>();
|
||||
int time=int.Parse(condition.Param[0]);
|
||||
if (!Condition_NoRechargeSeconds(time)) return false;
|
||||
}
|
||||
else if(!getEventCondition(condition)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#region Red
|
||||
private IDisposable _disposableSimple;
|
||||
private string GetRedPointKey()
|
||||
{
|
||||
return "eventAdWheel.red";
|
||||
}
|
||||
private bool GetRedPointState()
|
||||
{
|
||||
if (Data?.AdWheelMain == null) return false;
|
||||
|
||||
var nowTime = new DateTimeOffset(ZZTimeHelper.UtcNow().UtcNowOffset()).ToUnixTimeSeconds();
|
||||
var cdTime = nowTime - Data.lastViewAdTime;
|
||||
var remainCd = Data.AdWheelMain.ADInterval - cdTime;
|
||||
var isCd = remainCd > 0;
|
||||
if (!isCd) return Data.Progerss < 1;
|
||||
_disposableSimple?.Dispose();
|
||||
_disposableSimple=Observable.Interval(TimeSpan.FromSeconds(remainCd)).Subscribe(_ =>
|
||||
{
|
||||
SetRedPoint();
|
||||
_disposableSimple?.Dispose();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
private void SetRedPoint()
|
||||
{
|
||||
RedPointManager.Instance?.SetRedPointState(GetRedPointKey(), GetRedPointState());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user