using System; using System.Collections.Generic; using ProtoCSStruct; using Sog; namespace Game { public abstract class AbstractActivity { private static readonly Dictionary ActivityTypes = new(); public static Dictionary GetAllActivityTypes() { return ActivityTypes; } public static void Register() { ActivityTypes[ActivityType.Question] = new QuestionnaireSvc(); ActivityTypes[ActivityType.LoopSign] = new SignLoopAct(); ActivityTypes[ActivityType.Sign] = new SignAct(); ActivityTypes[ActivityType.MonthlyCard] = new LongEmptyActivity(); ActivityTypes[ActivityType.PowerPass] = new PowerPassAct(); ActivityTypes[ActivityType.ChapterPass] = new ChapterPassAct(); ActivityTypes[ActivityType.HandBook] = new HandBookAct(); ActivityTypes[ActivityType.AdventurePass] = new AdventurePassAct(); } //所有的活动应该都要关注这几件事情:1玩家进入游戏时候;2活动状态改变的时候;3系统解锁的时候;4新的一天(可能是某个时候)的时候 public abstract void OnRoleEnter(PlayerOnGame player); protected abstract void OnStateChange(PlayerOnGame player, int actId, ActivityState state); public abstract void OnSystemUnlock(PlayerOnGame player, int sysId); protected abstract void OnDailyRefresh(PlayerOnGame player, ref DBActInfo activityInfo); public static void TickAll(PlayerOnGame player) { var notifyClient = false; foreach (var kv in ActivityTypes) { kv.Value.OnTick(player, kv.Key, out var change); if (change) { notifyClient = true; } kv.Value.OnTickCheck(player); } if (notifyClient) { player.MakeDirty(); SyncActivity(player); } } /// ///通用tick逻辑:以活动类型做分组tick,当前此类型的活动可以同时存在一个或者多个,互不影响, ///根据配置的时间开放,活动开始时候自动添加数据到活动db,抛出状态改变事件,活动状态改变后,也会抛出状态改变事件, ///若某个类型的活动之间相互有别的特殊逻辑,请在自己的活动类型种复写此方法,切勿修改此函数。 ///!!!不要在这儿加入任何具体活动相关的逻辑,以便于分离活动类型和时间相关的逻辑 /// /// /// /// 活动是否有变化 protected virtual void OnTick(PlayerOnGame player, ActivityType activityType, out bool changed) { var now = GameServerUtils.GetTimeSecond(); changed = false; var groups = ActivityDescMgr.Instance.GetActivityDescByType(activityType); if (groups == null) { return; } ref var activityData = ref player.RoleData.ActivityInfo; foreach (var desc in groups) { var index = -1; for (var i = 0; i < activityData.Count; i++) { if (activityData[i].ActID == desc.id) { index = i; } } var state = ActivitySvc.GetActivityState(player, desc.id); if (state == ActivityState.ActivityNotStarted) { continue; } //活动状态发生改变, if (index >= 0 && activityData[index].State != (int)state) { //活动状态发生改变, OnStateChange(player, desc.id, state); activityData[index].State = (int)state; //更新活动状态 //当活动结束之后,所有后续处理都需要在这个之前,否则任务数据没了 if (state == ActivityState.ActivityEnded) { RemoveTask(player, desc.activityTask); RemoveTask(player, desc.activityDailyTask); RemoveTask(player, desc.activityWeekTask); } changed = true; } //新活动开始 if (index < 0 && state == ActivityState.InProgress) { AddActivity(player, desc.id, (int)ActivityState.InProgress); OnStateChange(player, desc.id, state); changed = true; } //活动在有效期内 if (index >= 0 && state == ActivityState.InProgress) { ref var info = ref activityData[index]; if (!AppTime.IsSameDay(info.RefreshTime, now)) { RefreshDaily(player, ref info); info.RefreshTime = now; changed = true; } } //玩法结束 if (index >= 0 && state == ActivityState.GameplayEnded) { activityData.RemoveAt(index); changed = true; } } } protected virtual void OnTickCheck(PlayerOnGame player) { } //添加一个新活动 protected static void AddActivity(PlayerOnGame player, int actId, int state) { var desc = ActivityDescMgr.Instance.GetConfig(actId); for (var i = 0; i < player.RoleData.ActivityInfo.Count; i++) { if (player.RoleData.ActivityInfo[i].ActID == actId) { player.Error("AbstractActivity.AddActivity activity exist uid={0},actId={1}", player.UserID, actId); return; } } if (player.RoleData.ActivityInfo.Count == player.RoleData.ActivityInfo.GetMaxCount()) { player.Error("AbstractActivity.AddActivity in processing activity overflow uid={0},actId={1}", player.UserID, actId); return; } var info = new DBActInfo { ActID = desc.id, State = (int)state, OpenTime = ActivitySvc.GetActOpenTimeDate(player, desc.id), EndTime = ActivitySvc.GetLastTimeToEnd(player, desc.id), RefreshTime = GameServerUtils.GetTimeSecond(), }; player.RoleData.ActivityInfo.Add(info); AddTask(player, desc.activityTask); AddTask(player, desc.activityDailyTask); AddTask(player, desc.activityWeekTask); } public static void SyncActivity(PlayerOnGame player) { CSActivityInfoSync sync = new CSActivityInfoSync(); sync.ActivityInfo.CopyFrom(ref player.RoleData.ActivityInfo); player.SendToClient((int)CSGameMsgID.ActivitySncInfo, ref sync); } public static void AddTask(PlayerOnGame player, int[] tasks) { if (tasks.Length == 0) { return; } int index; CSTaskEXAcceptTaskRes taskRes = new CSTaskEXAcceptTaskRes(); foreach (var taskId in tasks) { if (taskId == 0) { continue; } taskRes.TaskId = taskId; taskRes.Ret = TaskEXSvc.ProcessAcceptTask(player, taskId, true, out index); if (taskRes.Ret == CSErrCode.None) { taskRes.Taskdata.CopyFrom(ref TaskEXSvc.GetTaskByIndex(player, index)); TaskEXEvent.ProcessCheckNotifyClient(taskRes.TaskId, player); } player.SendToClient((int)CSGameMsgID.TaskexAcceptTaskRes, ref taskRes); } } public static void RemoveTask(PlayerOnGame player, int[] tasks) { if (tasks.Length == 0) { return; } var delNotify = new CSTaskEXDeleteNotify(); foreach (var id in tasks) { if (id == 0) { continue; } var ret = TaskEXSvc.ProcessGiveupTask2(player, id, out int index); if (ret == CSErrCode.None) { delNotify.DelTaskIDList.Add(id); } else { TraceLog.Error("AbstractActivity.RemoveTask ,delete task error Ret is " + ret + "taskId = " + id); } if (delNotify.DelTaskIDList.Count >= delNotify.DelTaskIDList.GetMaxCount()) { player.SendToClient((int)CSGameMsgID.TaskexDeleteNotify, ref delNotify); delNotify.Clear(); } } if (delNotify.DelTaskIDList.Count > 0) { player.SendToClient((int)CSGameMsgID.TaskexDeleteNotify, ref delNotify); } } protected void RefreshDaily(PlayerOnGame player, ref DBActInfo activityInfo) { OnDailyRefresh(player, ref activityInfo); //处理完一天干的事情后,再去重制任务数据 RefreshTask(player, ref activityInfo); } private static void RefreshTask(PlayerOnGame player, ref DBActInfo activityInfo) { //刷新任务 var desc = ActivityDescMgr.Instance.GetConfig(activityInfo.ActID); RemoveTask(player, desc.activityDailyTask); AddTask(player, desc.activityDailyTask); if (!AppTime.IsSameWeek127(activityInfo.RefreshTime, GameServerUtils.GetTimeSecond())) { RemoveTask(player, desc.activityWeekTask); AddTask(player, desc.activityWeekTask); } } protected static void DeleteActPayItemData(PlayerOnGame player, int actId) { var desc = ActivityDescMgr.Instance.GetConfig(actId); var payDiamondIds = desc.payDiamondId; var change = false; foreach (var payDiamondId in payDiamondIds) { ref var record = ref player.RoleData.PayData.PayItemRecord; for (var j = 0; j < record.Count; j++) { if (payDiamondId != record[j].ItemId) { continue; } player.RoleData.PayData.PayItemRecord.RemoveAt(j); change = true; break; } } if (change) { PlayerNotify.NotifyPlayerPayDataChange(player); } } } }