package main import ( "container/list" "math" "time" "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/mq" taskproto "mongo.games.com/game/protocol/task" "mongo.games.com/game/srvdata" "mongo.games.com/game/worldsrv/internal" ) /* 任务观察者 */ var TaskSubjectSingleton = &TaskSubject{ list: make(map[int]*list.List), } type ITask interface { // TaskUpdate 更新任务进度 // id 任务类型 // data 数据 TaskUpdate(id int, data any) } // TaskSubject 观察者 type TaskSubject struct { list map[int]*list.List } // Touch 任务统计事件 // id 任务类型 // data 数据 func (t *TaskSubject) Touch(id int, data any) { l, ok := t.list[id] if !ok { return } for e := l.Front(); e != nil; e = e.Next() { if o, ok := e.Value.(ITask); ok { o.TaskUpdate(id, data) } } } func (t *TaskSubject) Attach(id int, obj ITask) { l, ok := t.list[id] if !ok { l = new(list.List) t.list[id] = l } for e := l.Front(); e != nil; e = e.Next() { if e.Value == obj { return } } l.PushBack(obj) } type TaskData struct { SnId int32 GameID int GameFreeID int32 Num int64 Position int32 Debug bool } type TaskHandle struct { } func (t *TaskHandle) TaskUpdate(id int, data any) { info, ok := data.(*TaskData) if !ok { return } p := PlayerMgrSington.GetPlayerBySnId(info.SnId) if p == nil { return } num := info.Num logger.Logger.Tracef("玩家任务事件 Snid = %d,GameId = %d,GameFreeId = %d,任务 id = %d,num = %d", info.SnId, info.GameID, info.GameFreeID, id, num) t.AllTask(id, data) switch id { case common.TaskTypeAdv: // 看广告 case common.TaskTypeBuyCoin: // 买金币 case common.TaskTypeLogin: // 每日登录 case common.TaskTypeWinTimes: // 赢游戏次数 case common.TaskTypePlayTimes: // 玩游戏次数 case common.TaskTypeRankMatchTimes: // 排位赛次数 case common.TaskTypePay: // 玩家充值 p.PhoneLotteryTask(common.TaskTypePay, num) case common.TaskTypeWinOrLose: // 游戏输赢金币数量 p.PhoneLotteryTask(common.TaskTypeWinOrLose, num) case common.TaskTypeTienlenCount: //tienlen游戏场次 p.PhoneLotteryTask(common.TaskTypeTienlenCount, 1) case common.TaskTypeBindInviter: // 绑定邀请人数量 case common.TaskTypeWinCoin: // 赢取金币数量 case common.TaskTypeLoseCoin: //输的金币数量 case common.TaskTypeTienlenWinTimes: // tienlen游戏赢取次数 case common.TaskTypeActivityScore: // 活跃积分数量 case common.TaskTypeInviteScore: // 邀请积分数量 case common.TaskTypeFirstLogin: //抽奖次数增加 p.PhoneLotteryTask(common.TaskTypeFirstLogin, 0) p.CollectTask(common.TaskTypeFirstLogin, num) case common.TaskTypeInviteNum: case common.TaskTypeTurnplate: p.CollectTask(common.TaskTypeTurnplate, num) case common.TaskTypeTienlenWinCoin: // tienlen游戏赢取金币数量 WelfareMgrSington.UpdateDiamondBankData(p, num, true) case common.TaskTypeTienlenLoseCoin: // tienlen游戏输金币数量 WelfareMgrSington.UpdateDiamondBankData(p, int64(math.Abs(float64(num))), false) default: return } return } // AllTask 任务活动 func (t *TaskHandle) AllTask(id int, data any) { info, ok := data.(*TaskData) if !ok { return } p := PlayerMgrSington.GetPlayerBySnId(info.SnId) if p == nil { return } if p.WelfData == nil { p.WelfData = model.NewWelfareData() } if p.WelfData.Task == nil { p.WelfData.Task = make(map[int32]*model.TaskData) } logger.Logger.Tracef("AllTask taskID:%v %v", id, p.WelfData.Task[int32(id)]) now := time.Now() change := map[int32][]*taskproto.TaskData{} for _, v := range srvdata.TaskMgr.GetTaskType(int32(id)) { if !info.Debug { // 游戏类型 switch v.GetGameType() { case common.TaskGameTypeTienlen: if !srvdata.GameFreeMgr.IsGameDif(int32(info.GameID), common.GameDifTienlen) { continue } case common.TaskGameTypeThirteen: if !srvdata.GameFreeMgr.IsGameDif(int32(info.GameID), common.GameDifThirteen) { continue } case common.TaskGameTypeChess: if !srvdata.GameFreeMgr.IsGameDif(int32(info.GameID), common.GameDifChess) { continue } case common.TaskGameTypeSmallRocket: if !srvdata.GameFreeMgr.IsGameDif(int32(info.GameID), common.GameDifRocket) { continue } default: } // 大厅类型 if len(v.Position) > 0 && info.Position > 0 { if len(v.Position) > int(info.Position) { if v.Position[info.Position-1] != 1 { continue } } } } switch v.GetActivityType() { case common.TaskActivityTypeNianEveryDay, common.TaskActivityTypeNian: //判断是否在开启时间段内 pool := WelfareMgrSington.GetConfig(p.Platform).ActivityNianConfig if pool == nil || pool.List == nil { continue } if pool.Switch == model.WelfareClose { continue } startTime := pool.List[0].ActivityStart endTime := pool.List[0].ActivityEnd start, _ := time.Parse(time.DateTime, startTime) timestamp := start.Unix() end, _ := time.Parse(time.DateTime, endTime) endTimestamp := end.Unix() if now.Unix() < timestamp || now.Unix() > endTimestamp { continue } case common.TaskActivityTypeConsume: cfg := WelfareMgrSington.GetConfig(p.Platform).ConsumeConfig if cfg == nil || cfg.GetOn() != common.On || now.Unix() < common.StrTimeToTs(cfg.StartTime) || now.Unix() >= common.StrTimeToTs(cfg.EndTime) { continue } } if p.WelfData.Task[v.Id] == nil { p.WelfData.Task[v.Id] = &model.TaskData{N: 0} // 初始化任务数据 } p.WelfData.Task[v.Id].N += info.Num // 通知变更 if !IsTaskReward(p, v.Id) { item := &taskproto.TaskData{ Id: v.Id, N: p.WelfData.Task[v.Id].N, TargetN: v.TargetTimes, Status: 0, Reward: v.Award, TaskType: v.TaskType, } if item.N > item.TargetN { item.N = item.TargetN } if IsTaskFinish(p, v.Id) { item.Status = TaskStateFinish } change[v.GetActivityType()] = append(change[v.GetActivityType()], item) } } // 通知变更 for k, v := range change { if len(v) == 0 { continue } pack := &taskproto.SCTaskChange{ Tp: k, List: v, } p.SendToClient(int(taskproto.TaskPacketID_PACKET_SCTaskChange), pack) logger.Logger.Tracef("SCTaskChange %v", pack) } } func OnNotifyChange(p *Player, activityType int32) { add := p.GetSkillAdd(common.SkillIdTask) var l []*taskproto.TaskData for _, v := range srvdata.TaskMgr.GetActivityType(activityType) { if !IsTaskReward(p, v.Id) { // 皮肤技能每日任务金币加成 item := &taskproto.TaskData{ Id: v.Id, N: GetTaskTimes(p, v.Id), TargetN: v.GetTargetTimes(), Status: 0, Reward: make(map[int64]int64), TaskType: v.GetTaskType(), } for k, vv := range v.GetAward() { if v.GetActivityType() == common.TaskActivityTypeEveryDay && add > 0 && k == common.ItemIDCoin { vv += int64((float64(vv) * float64(add)) / 100.0) } item.Reward[k] = vv } l = append(l, item) } } pack := &taskproto.SCTaskChange{ Tp: activityType, List: l, } p.SendToClient(int(taskproto.TaskPacketID_PACKET_SCTaskChange), pack) logger.Logger.Tracef("SCTaskChange %v", pack) } // GetTaskTimes 获取任务完成进度 func GetTaskTimes(p *Player, id int32) int64 { if p.WelfData != nil && p.WelfData.Task[id] != nil { return p.WelfData.Task[id].N } return 0 } // IsTaskFinish 是否任务完成 func IsTaskFinish(p *Player, id int32) bool { data := srvdata.PBDB_TaskMgr.GetData(id) if data == nil { return false } if p.WelfData != nil && p.WelfData.Task[id] != nil { return p.WelfData.Task[id].N >= data.GetTargetTimes() } return false } // IsTaskReward 是否任务奖励已领取 func IsTaskReward(p *Player, id int32) bool { if p.WelfData != nil && p.WelfData.Task != nil { if data := p.WelfData.Task[id]; data != nil && data.Ts > 0 { t := srvdata.PBDB_TaskMgr.GetData(id) switch t.ActivityType { case common.TaskActivityTypeEveryDay, common.TaskActivityTypePermitEveryDay, common.TaskActivityTypeNianEveryDay, common.TaskActivityTypeConsume: if common.TsInSameDay(time.Now().Unix(), data.Ts) { return true } case common.TaskActivityTypeWeek: if common.TsInSameWeek(time.Now().Unix(), data.Ts) { return true } case common.TaskActivityTypeNovice, common.TaskActivityTypeInvite, common.TaskActivityTypeAchieve: if data.Ts > 0 { return true } case common.TaskActivityTypePermit: startTs := PlatformMgrSingleton.GetConfig(p.Platform).PermitStartTs endTs := PlatformMgrSingleton.GetConfig(p.Platform).PermitEndTs if startTs > 0 { return data.Ts >= startTs && data.Ts < endTs } return true case common.TaskActivityTypeNian: pool := WelfareMgrSington.GetConfig(p.Platform).ActivityNianConfig if pool == nil || pool.List == nil { return false } if pool.Switch == model.WelfareClose { return false } startTime := pool.List[0].ActivityStart endTime := pool.List[0].ActivityEnd start, _ := time.Parse(time.DateTime, startTime) timestamp := start.Unix() end, _ := time.Parse(time.DateTime, endTime) endTimestamp := end.Unix() if timestamp > 0 { return data.Ts >= timestamp && data.Ts < endTimestamp } return true } } } return false } // SendTaskReward 发送任务奖励 func SendTaskReward(p *Player, m map[int64]int64, tp int32) { isPermit := p.GetIsPermit() add := p.GetSkillAdd(common.SkillIdTask) var items []*model.Item for k, v := range m { if k == common.ItemIDPermit && isPermit { v += int64(float64(v) * common.PermitAdd) } // 皮肤技能每日任务金币加成 if tp == common.TaskActivityTypeEveryDay && add > 0 && k == common.ItemIDCoin { v += int64((float64(v) * float64(add)) / 100.0) } items = append(items, &model.Item{ ItemId: int32(k), ItemNum: v, }) } gain := int32(0) giveType := int32(-1) switch tp { case 1: gain = common.GainWayItemTaskEveryDay giveType = model.SystemFreeGive_GiveType_TaskEveryDay case 2: gain = common.GainWayItemWeekActive giveType = model.SystemFreeGive_GiveType_TaskWeekActive case 3: gain = common.GainWayItemTaskNewPlayer giveType = model.SystemFreeGive_GiveType_TaskNewPlayer case 4: gain = common.GainWayItemTaskInvite giveType = model.SystemFreeGive_GiveType_TaskInvite case 5: gain = common.GainWayItemTaskAchievement giveType = model.SystemFreeGive_GiveType_TaskAchievement case 6: gain = common.GainWayItemTaskPermit giveType = model.SystemFreeGive_GiveType_TaskPermit case 8: gain = common.GainWayNianGain_EveryDayTask giveType = model.SystemFreeGive_NianEveryDayTask case 9: gain = common.GainWayNianGain_Task giveType = model.SystemFreeGive_NianTask case 10: gain = common.GainWayConsume } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: items, Add: 0, GainWay: gain, Operator: "system", Remark: "任务奖励", GameId: 0, GameFreeId: 0, }) for _, v := range items { tp := int32(-1) if v.ItemId == common.ItemIDCoin { tp = model.SystemFreeGive_CoinType_Coin } else if v.ItemId == common.ItemIDDiamond { tp = model.SystemFreeGive_CoinType_Diamond } if !p.IsRob && tp >= 0 && giveType >= 0 { mq.Write(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, p.Channel, giveType, tp, v.ItemNum)) } } if giveType == model.SystemFreeGive_GiveType_TaskPermit { mq.Write(model.GenerateActivityLog(p.SnId, p.Platform, model.ActivityLog_Permit, 1)) } } func init() { taskHandle := new(TaskHandle) TaskSubjectSingleton.Attach(common.TaskTypeAdv, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeBuyCoin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeLogin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeWinTimes, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypePlayTimes, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeRankMatchTimes, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypePay, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeWinOrLose, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeTienlenCount, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeBindInviter, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeWinCoin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeTienlenWinTimes, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeInviteScore, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeActivityScore, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeFirstLogin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeInviteNum, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeTurnplate, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeInviteRecharge, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeLoseCoin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeOnlineTs, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeBuyPig, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeDaZhong, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeInvitePlay, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeJoinMatch, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeMatchRank10, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeCostDiamond, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeTienlenLoseCoin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeTienlenWinCoin, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeRankMatchWinTimes, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeBuyPermit, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeBuyRedBag, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeNianBossKill, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeNianBossDamage, taskHandle) TaskSubjectSingleton.Attach(common.TaskTypeNianSign, taskHandle) internal.RegisterPlayerListenerFunc(&internal.PlayerListenerFunc[*Player, *Scene]{ OnPlayerDayChangedFunc: func(p *Player, isLogin, isContinue bool) { if p.WelfData != nil && p.WelfData.Task != nil { for _, v := range []int32{ // todo 每日重置的任务列表 common.TaskActivityTypeEveryDay, common.TaskActivityTypePermitEveryDay, common.TaskActivityTypeNianEveryDay, common.TaskActivityTypeConsume} { for _, vv := range srvdata.TaskMgr.GetActivityType(v) { p.WelfData.Task[vv.GetId()] = &model.TaskData{} } } } }, OnPlayerWeekChangedFunc: func(p *Player, isLogin, isContinue bool) { if p.WelfData != nil && p.WelfData.Task != nil { for _, v := range []int32{ // todo 每周重置的任务列表 common.TaskActivityTypeWeek} { for _, vv := range srvdata.TaskMgr.GetActivityType(v) { p.WelfData.Task[vv.GetId()] = &model.TaskData{} } } } }, }) }