You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

307 lines
11 KiB

using System;
using System.Collections.Generic;
using ProtoCSStruct;
using Sog;
namespace Game
{
public abstract class AbstractActivity
{
private static readonly Dictionary<ActivityType, AbstractActivity> ActivityTypes = new();
public static Dictionary<ActivityType, AbstractActivity> 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);
}
}
/// <summary>
///通用tick逻辑:以活动类型做分组tick,当前此类型的活动可以同时存在一个或者多个,互不影响,
///根据配置的时间开放,活动开始时候自动添加数据到活动db,抛出状态改变事件,活动状态改变后,也会抛出状态改变事件,
///若某个类型的活动之间相互有别的特殊逻辑,请在自己的活动类型种复写此方法,切勿修改此函数。
///!!!不要在这儿加入任何具体活动相关的逻辑,以便于分离活动类型和时间相关的逻辑
/// </summary>
/// <param name="player"></param>
/// <param name="activityType"></param>
/// <param name="changed">活动是否有变化</param>
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<CSTaskEXDeleteNotify>((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);
}
}
}
}