game_sync/worldsrv/taskmgr.go

506 lines
15 KiB
Go

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()*/
timestamp := common.StrTimeToTs(startTime)
endTimestamp := common.StrTimeToTs(endTime)
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
timestamp := common.StrTimeToTs(startTime)
endTimestamp := common.StrTimeToTs(endTime)
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{}
}
}
}
},
})
}