Files
bl/logic/service/space/timeboss.go

225 lines
6.7 KiB
Go
Raw Normal View History

package space
import (
"blazing/cool"
"math/rand"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
// ========== 1. 定义TimeBoss的定时规则补全周四-周六,新增周日规则) ==========
// TimeBossRule 单个BOSS的定时规则
type TimeBossRule struct {
PetID uint32 // BOSS ID对应XML的petID="261"
Week int // 星期1=周一2=周二...7=周日)
ShowHours []int // 出现小时如12,17,18,24周日填0-23表示每小时
ShowMinute int // 出现分钟如35,0
LastTime int // 持续时间(分钟)
MapIDs []uint32 // 可选刷新地图ID列表随机选一个
}
// 全局261号BOSS的规则配置补全周四-周六,新增周日)
var timeBossRules = []TimeBossRule{
// 周一规则
{
PetID: 261,
Week: 1, // 周一
ShowHours: []int{12, 17, 18, 24}, // 12|17|18|24点35分
ShowMinute: 35, // 35分
LastTime: 40, // 持续40分钟
MapIDs: []uint32{15, 105, 54}, // 随机选一个地图
},
// 周二规则
{
PetID: 261,
Week: 2, // 周二
ShowHours: []int{17, 18, 24}, // 17|18|24点0分
ShowMinute: 0, // 0分
LastTime: 5, // 持续5分钟
MapIDs: []uint32{15, 105, 54},
},
// 周三规则
{
PetID: 261,
Week: 3, // 周三
ShowHours: []int{17, 18, 24}, // 17|18|24点0分
ShowMinute: 0, // 0分
LastTime: 5, // 持续5分钟
MapIDs: []uint32{15, 105, 54},
},
// 周四规则(和周一完全一致)
{
PetID: 261,
Week: 4, // 周四
ShowHours: []int{12, 17, 18, 24}, // 12|17|18|24点35分
ShowMinute: 35, // 35分
LastTime: 40, // 持续40分钟
MapIDs: []uint32{15, 105, 54},
},
// 周五规则(和周二完全一致)
{
PetID: 261,
Week: 5, // 周五
ShowHours: []int{17, 18, 24}, // 17|18|24点0分
ShowMinute: 0, // 0分
LastTime: 5, // 持续5分钟
MapIDs: []uint32{15, 105, 54},
},
// 周六规则(和周三完全一致)
{
PetID: 261,
Week: 6, // 周六
ShowHours: []int{17, 18, 24}, // 17|18|24点0分
ShowMinute: 0, // 0分
LastTime: 5, // 持续5分钟
MapIDs: []uint32{15, 105, 54},
},
// 周日规则特殊每小时刷新持续10分钟
{
PetID: 261,
Week: 7, // 周日
ShowHours: generateHourRange(0, 23), // 0-23点每小时
ShowMinute: 0, // 每小时0分触发
LastTime: 10, // 持续10分钟
MapIDs: []uint32{15, 105, 54}, // 随机选一个地图
},
}
// ========== 2. 全局变量(无修改,新增随机数生成器已存在) ==========
var (
registeredCronIDs = make(map[string]bool) // 记录已注册的Cron任务ID
cronMu sync.Mutex // 保护registeredCronIDs的互斥锁
randSource = rand.New(rand.NewSource(time.Now().UnixNano())) // 安全的随机数生成器
)
// ========== 3. 工具函数生成0-23小时数组适配周日每小时规则 ==========
// generateHourRange 生成从start到end的连续小时数组如0-23
func generateHourRange(start, end int) []int {
hours := make([]int, 0, end-start+1)
for i := start; i <= end; i++ {
hours = append(hours, i)
}
return hours
}
// ========== 4. 原有方法gettimeboss无修改自动适配新规则 ==========
func init() { // 忽略传入的mapid随机选地图
// 遍历所有TimeBoss规则包含周四-周六-周日)
for _, rule := range timeBossRules {
// 为该规则的每个小时生成Cron任务
for _, hour := range rule.ShowHours {
// 生成唯一Cron任务ID避免重复注册
cronID := genCronTaskID(rule.PetID, rule.Week, hour, rule.ShowMinute)
cronMu.Lock()
if registeredCronIDs[cronID] {
cronMu.Unlock()
continue // 已注册过,跳过
}
registeredCronIDs[cronID] = true
cronMu.Unlock()
// 转换规则为Cron表达式
cronExpr := genCronExpr(rule.Week, hour, rule.ShowMinute)
// 捕获当前循环的rule避免闭包引用同一变量
currentRule := rule
// 注册Cron定时任务
cool.Cron.AddFunc(cronExpr, func() {
// 1. 随机选一个地图ID
randomMapID := getRandomMapID(currentRule.MapIDs)
if randomMapID == 0 {
return // 无可用地图,跳过
}
sp := GetSpace(randomMapID)
if sp != nil {
// 2. 显示BOSS指定随机地图广播
sp.refushgaiya(true)
// 3. 启动定时器持续时间到后隐藏BOSS同样指定地图
time.AfterFunc(time.Duration(currentRule.LastTime)*time.Minute, func() {
sp.refushgaiya(false)
})
}
})
}
}
}
// ========== 5. 修改后的refushgaiya指定地图广播 ==========
func (s *Space) refushgaiya(vis bool) {
if !vis {
atomic.StoreUint32(&s.TimeBoss.Flag, 0)
} else {
atomic.StoreUint32(&s.TimeBoss.Flag, 1)
}
atomic.StoreUint32(&s.TimeBoss.ID, 261)
// 只向指定地图广播(核心:不再全局广播)
s.Broadcast(nil, 2022, &s.TimeBoss)
}
// ========== 6. 工具函数(无修改,自动适配周日规则) ==========
// getRandomMapID 从地图列表中随机选一个
func getRandomMapID(mapIDs []uint32) uint32 {
if len(mapIDs) == 0 {
return 0
}
return mapIDs[randSource.Intn(len(mapIDs))]
}
// genCronExpr 生成Cron表达式自动适配周日的0值
func genCronExpr(week, hour, minute int) string {
// 1. 处理小时24点转为0点Cron小时范围0-23
cronHour := hour
if cronHour == 24 {
cronHour = 0
}
// 2. 处理星期XML的7=周日 → Cron的0=周日,其余直接用
cronWeek := week
if cronWeek == 7 {
cronWeek = 0
}
// 3. 生成Cron表达式秒 分 时 日 月 周)
return strings.Join([]string{
"0", // 秒固定0整分触发
strconv.Itoa(minute), // 分
strconv.Itoa(cronHour), // 时
"?", // 日(不指定)
"*", // 月(每月)
strconv.Itoa(cronWeek), // 周
}, " ")
}
// genCronTaskID 生成唯一的Cron任务ID
func genCronTaskID(petID uint32, week, hour, minute int) string {
return strings.Join([]string{
strconv.FormatUint(uint64(petID), 10),
strconv.Itoa(week),
strconv.Itoa(hour),
strconv.Itoa(minute),
}, "_")
}
// containsMapID 检查mapid是否在列表中备用
func containsMapID(mapIDs []uint32, mapid uint32) bool {
for _, id := range mapIDs {
if id == mapid {
return true
}
}
return false
}