using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using asap.core; using cfg; using game; using GameCore; using Newtonsoft.Json; using UnityEngine; namespace DataCenter { // EventPartnerGather 游戏数据结构 public class EventPartnerGatherData { public bool FirstOpen = true; public int EventId; public DateTime StartTime; public DateTime EndTime; // 核心游戏数据 public int CurrentPoints = 0; // 当前积分 public int CurrentMiningProgress = 0; // 挖矿进度 public int TrainProgress = 0; // 火车进度 (0-5节点) public List CompletedNodes = new List(); // 已完成的节点 // 好友系统数据(第二阶段) public List Friends = new List(); public int InvitedCount = 0; // 奖励记录 public List CollectedRewards = new List(); public bool IsFinished = false; public float BonusPercent = 0f; public DateTime BonusExpireUtc = DateTime.MinValue; public class FriendData { public string Id; public string Name; public int MiningProgress; public int ContributionPoints; public bool IsActive; } } // EventPartnerGather 管理器 public class EventPartnerGatherManager { public const string SaveKey = "EventPartnerGatherData"; [Inject] public Tables _tables { get; set; } private FishingEvent _fishingEvent; // 检查数据是否改变过 private bool _isEventDataChanged = false; public EventPartnerGatherData GatherData { get; private set; } // 数据 public EventPartnerMain2 EventPartnerMain2Data { get; private set; } // 抽奖数据 public List EventPartnerSpinPointList { get; private set; } // 模型数据,目前开来需要构造模型从表里读取 public EventPartnerInit EventPartnerInitData { get; private set; } // 累分状态 private readonly List _nodeCumulativeSteps = new List(); // 配置数据(后续从表格读取) public int MaxTrainNodes => 5; public int PointsPerMining => 10; public int PointsPerNode => 100; public bool IsFirstOpen { get => GatherData?.FirstOpen ?? false; set { if (GatherData != null && GatherData.FirstOpen) { GatherData.FirstOpen = false; SaveData(); } } } public void UpdateEventData(FishingEvent fishingEvent) { Log($"UpdateEventData: {fishingEvent?.ID}"); _fishingEvent = fishingEvent; InitializeData(); // } } public void CheckInit() { Init(); } public void Init() { Log("Init()-> "); if (GatherData == null && _fishingEvent != null) { CreateNewData(); } //TODO:LF 等上面触发完成之后,移走 //TODO:LF:后面优化 2025-09-17 InitializeData(); ValidateAndUpdateData(); } private void CreateNewData() { var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition; var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow()); var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow()); GatherData = new EventPartnerGatherData { FirstOpen = true, EventId = _fishingEvent.ID, StartTime = startTime, EndTime = endTime, CurrentPoints = 0, CurrentMiningProgress = 0, TrainProgress = 0 }; SaveData(); } private void InitializeData() { Log("InitializeData() -> "); if (_fishingEvent == null) return; var redirectId = _fishingEvent.RedirectID; var eventPartnerDataList = _tables.TbEventPartnerMain2.DataList; EventPartnerMain2Data = eventPartnerDataList.FirstOrDefault(data => data.ID == redirectId); var allSpinPoints = _tables.TbEventPartnerSpinPoint.DataList; var ids = EventPartnerMain2Data?.SpinPoint; if (ids != null && ids.Count > 0) { var filtered = new List(); foreach (var id in ids) { var sp = _tables.TbEventPartnerSpinPoint.GetOrDefault(id); if (sp != null) filtered.Add(sp); } EventPartnerSpinPointList = filtered; } else { EventPartnerSpinPointList = new List(); } _nodeCumulativeSteps.Clear(); if (EventPartnerMain2Data?.StagePoint != null && EventPartnerMain2Data.StagePoint.Count > 0) { int sum = 0; for (int i = 0; i < EventPartnerMain2Data.StagePoint.Count; i++) { sum += EventPartnerMain2Data.StagePoint[i]; _nodeCumulativeSteps.Add(sum); } } var eventPartnerInitDataList = _tables.TbEventPartnerInit.DataList; // foreach (var eventPartnerInitData in eventPartnerInitDataList.Where(data => data.ID == redirectId)) // { // EventPartnerInitData = eventPartnerInitData; // } EventPartnerInitData = eventPartnerInitDataList.FirstOrDefault(data => data.ID == redirectId); // 检查是否需要重置数据 if (GatherData != null && !IsTimeValid()) { HandleEventEnd(); GatherData = null; } } private void ValidateAndUpdateData() { if (GatherData == null) return; // 验证时间有效性 if (!IsTimeValid()) { HandleEventEnd(); } } public bool IsTimeValid() { if (GatherData == null) return false; var now = ZZTimeHelper.UtcNow(); return now >= GatherData.StartTime && now <= GatherData.EndTime; } public TimeSpan GetRemainingTime() { if (GatherData == null) return TimeSpan.Zero; return GatherData.EndTime - ZZTimeHelper.UtcNow(); } public bool CheckOpen() { if (GatherData == null) return false; if (!IsTimeValid()) return false; if (GatherData.IsFinished) return false; return true; } // 核心游戏逻辑 // 抽奖数据 public EventPartnerSpinPoint GetSpinPointElem() { // if (EventPartnerSpinPointList is { Count: > 0 }) // { // // 根据权重,生成字典 // var dict = EventPartnerSpinPointList.ToDictionary(elem => elem, elem => elem.Weight); // var elem = OfferChainsChestManager.WeightedRandom(dict); // Log($"GetSpinPointElem -> {elem.ID}"); // return elem; // } return null; } public void AddPoints(int points) { if (GatherData == null) { Log("错误:GatherData 为空,无法添加积分"); return; } if (GatherData.IsFinished) { Log("警告:游戏已结束,无法添加积分"); return; } if (points <= 0) { Log($"警告:尝试添加无效积分值:{points}"); return; } EnsureBonusValid(); float mult = 1f + Mathf.Max(0f, GatherData.BonusPercent); int eff = Mathf.Max(0, Mathf.RoundToInt(points * mult)); // 防止积分溢出 long newPoints = (long)GatherData.CurrentPoints + eff; if (newPoints > int.MaxValue) { Log($"警告:积分即将溢出,限制在最大值"); GatherData.CurrentPoints = int.MaxValue; } else { GatherData.CurrentPoints += eff; } Log($"AddPoints: {eff}, TotalPoints: {GatherData.CurrentPoints}"); SaveData(); GContext.Publish(new EventPartnerGatherPointsUpdate { Points = GatherData.CurrentPoints }); // 检查是否需要触发自动挖矿 CheckAutoMining(); } private void CheckAutoMining() { // 每累积一定积分自动触发挖矿 bool dataChanged = false; while (GatherData.CurrentPoints >= PointsPerMining) { GatherData.CurrentPoints -= PointsPerMining; GatherData.CurrentMiningProgress++; dataChanged = true; // 检查节点完成 CheckNodeProgress(); } // 如果数据有变化,发布更新事件 if (dataChanged) { SaveData(); PublishDataUpdateEvents(); } } private void CheckNodeProgress() { int completedNodes = 0; if (_nodeCumulativeSteps != null && _nodeCumulativeSteps.Count > 0) { for (int i = 0; i < _nodeCumulativeSteps.Count; i++) { if (GatherData.CurrentMiningProgress >= _nodeCumulativeSteps[i]) completedNodes++; else break; } } if (completedNodes > GatherData.TrainProgress) { int target = Mathf.Min(completedNodes, MaxTrainNodes); for (int idx = GatherData.TrainProgress; idx < target; idx++) { CompleteTrainNode(idx); } GatherData.TrainProgress = target; if (GatherData.TrainProgress >= MaxTrainNodes) { HandleGameComplete(); } } } private void CompleteTrainNode(int nodeIndex) { Log($"CompleteNode: {nodeIndex}"); if (!GatherData.CompletedNodes.Contains(nodeIndex)) { GatherData.CompletedNodes.Add(nodeIndex); // 发放节点奖励 DistributeNodeReward(nodeIndex); } } private void DistributeNodeReward(int nodeIndex) { // 使用现有的奖励系统 var dropId = GetNodeRewardDropId(nodeIndex); if (dropId > 0) { var playerItemData = GContext.container.Resolve(); var rewards = playerItemData.GetItemDataByDropId(dropId); playerItemData.AddItem(rewards); GContext.Publish(new ShowData(rewards)); GatherData.CollectedRewards.Add(dropId); SaveData(); } } private int GetNodeRewardDropId(int nodeIndex) { // 根据节点返回对应的掉落ID(后续从配置表读取) return 10000 + nodeIndex; } private void HandleGameComplete() { Log("Game Complete!"); GatherData.IsFinished = true; // 发放最终大奖 DistributeFinalReward(); SaveData(); GContext.Publish(new EventPartnerGatherComplete()); } private void DistributeFinalReward() { var dropId = GetFinalRewardDropId(); if (dropId > 0) { var playerItemData = GContext.container.Resolve(); var rewards = playerItemData.GetItemDataByDropId(dropId); playerItemData.AddItem(rewards); GContext.Publish(new ShowData(rewards)); } } private int GetFinalRewardDropId() { // 最终奖励掉落ID(后续从配置表读取) return 99999; } private void HandleEventEnd() { if (GatherData == null || GatherData.IsFinished) return; Log("Event Ended"); // 结算未领取的奖励 if (GatherData.TrainProgress >= MaxTrainNodes && !GatherData.IsFinished) { HandleGameComplete(); } ClearData(); } public int ResolveSpinAndGetPoints(EventPartnerSpinPoint p) { if (p == null || p.SpinPointParam == null) return 0; switch (p.SpinPointParam) { case NormalSpinPoint n: return Mathf.Max(0, n.SpinPoints); case FreeSpinPoint f: return Mathf.Max(0, f.SpinPoints); case MoreSpinPoint m: ApplyBonus(m.BonusPercent, m.BonusDuration); return 0; } return 0; } private void ApplyBonus(float percent, int durationSec) { if (GatherData == null) return; GatherData.BonusPercent = Mathf.Max(0f, percent); GatherData.BonusExpireUtc = ZZTimeHelper.UtcNow().AddSeconds(Mathf.Max(0, durationSec)); SaveData(); GContext.Publish(new EventPartnerGatherRefreshEvent()); } private void EnsureBonusValid() { if (GatherData == null) return; if (GatherData.BonusPercent > 0f && ZZTimeHelper.UtcNow() > GatherData.BonusExpireUtc) { GatherData.BonusPercent = 0f; GatherData.BonusExpireUtc = DateTime.MinValue; SaveData(); GContext.Publish(new EventPartnerGatherRefreshEvent()); } } public bool IsBonusActive() { return GatherData != null && GatherData.BonusPercent > 0f && ZZTimeHelper.UtcNow() <= GatherData.BonusExpireUtc; } private void SaveData() { if (GatherData != null) { PlayFabMgr.Instance.UpdateUserDataValue(SaveKey, JsonConvert.SerializeObject(GatherData)); } } public void LoadData(string dataValue) { if (!string.IsNullOrEmpty(dataValue)) { GatherData = JsonConvert.DeserializeObject(dataValue); } } private void ClearData() { GatherData = null; SaveData(); } // 进入游戏场景 public void EnterGatherScene() { Log("EnterGatherScene() "); IsFirstOpen = false; GContext.Publish(new UnloadActToNextAct("EventPartnerGatherAct", UITypes.CloudTransitionPanel, 0.5f)); } // 开始采矿 public void StartMining() { // throw new NotImplementedException(); Log("StartMining()"); ((EventPartnerGatherAct)_act)?.OnEnterGather(); } private static void Log(object t) { Debug.Log($"EventPartnerGatherManager-> {t} "); } private AGameAct _act; public void SetGameAct(AGameAct act) { _act = act; } // 组件绑定管理 private UI.PartnerGather.Mining.EventPartnerMiningSceneController _miningController; private UI.PartnerGather.Mining.EventPartnerDrawMiningPanel _drawPanel; /// /// 设置挖矿场景控制器引用 /// public void SetMiningController(UI.PartnerGather.Mining.EventPartnerMiningSceneController controller) { _miningController = controller; Log($"设置挖矿控制器: {controller?.name ?? "null"}"); } /// /// 设置抽奖UI面板引用 /// public void SetDrawPanel(UI.PartnerGather.Mining.EventPartnerDrawMiningPanel panel) { _drawPanel = panel; Log($"设置抽奖面板: {panel?.name ?? "null"}"); } /// /// 获取挖矿控制器引用 /// public UI.PartnerGather.Mining.EventPartnerMiningSceneController GetMiningController() { return _miningController; } /// /// 获取抽奖面板引用 /// public UI.PartnerGather.Mining.EventPartnerDrawMiningPanel GetDrawPanel() { return _drawPanel; } /// /// 通知所有绑定组件刷新数据显示 /// public void RefreshAllUI() { if (GatherData == null) return; // 刷新抽奖面板 if (_drawPanel != null) { _drawPanel.SetPoints(GatherData.CurrentPoints); _drawPanel.SetMiningProgress(GatherData.CurrentMiningProgress); _drawPanel.SetTrainProgress(GatherData.TrainProgress, MaxTrainNodes); } Log("已刷新所有UI组件数据"); } /// /// 发布所有相关的数据更新事件 /// private void PublishDataUpdateEvents() { if (GatherData == null) return; // 发布积分更新事件 GContext.Publish(new EventPartnerGatherPointsUpdate { Points = GatherData.CurrentPoints }); // 发布挖矿进度更新事件 GContext.Publish(new EventPartnerGatherMiningProgressUpdate { Progress = GatherData.CurrentMiningProgress }); // 发布火车进度更新事件 GContext.Publish(new EventPartnerGatherTrainProgressUpdate { Progress = GatherData.TrainProgress, MaxNodes = MaxTrainNodes }); // 刷新绑定的UI组件 RefreshAllUI(); Log($"已发布数据更新事件 - 积分:{GatherData.CurrentPoints}, 挖矿进度:{GatherData.CurrentMiningProgress}, 火车进度:{GatherData.TrainProgress}"); } // 有可能会激活,不应该在OnEnable 中调用Init(); public void CheckForOnEnable() { //throw new NotImplementedException(); } } // 事件定义 public class EventPartnerGatherPointsUpdate { public int Points; } public class EventPartnerGatherMiningProgressUpdate { public int Progress; } public class EventPartnerGatherTrainProgressUpdate { public int Progress; public int MaxNodes; } public class EventPartnerGatherComplete { } public class EventPartnerGatherRefreshEvent { } }