Files
bl/logic/service/space/boss_time.go
昔念 5995f0670c
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(game): 实现扭蛋系统批量物品添加功能并优化地图逻辑

- 新增ItemAddBatch方法用于批量添加物品,支持普通道具和特殊道具的分别处理
- 优化扭蛋游戏玩法中的物品添加逻辑,使用新的批量接口提升性能
- 在扭蛋机器人命令中实现完整的物品检查和批量添加流程

refactor(map): 重构地图控制器代码结构并添加注释

- 为EnterMap、LeaveMap、GetMapPlayerList等方法添加中文注释
- 统一地图相关的命名规范,如enter
2026-04-01 20:10:29 +08:00

192 lines
3.8 KiB
Go

package space
import (
"blazing/cool"
"math/rand"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
// TimeBossRule describes one timed boss spawn rule.
type TimeBossRule struct {
PetID uint32
Week int
ShowHours []int
ShowMinute int
LastTime int
MapIDs []uint32
}
// Timed boss schedule config.
var timeBossRules = []TimeBossRule{
{
PetID: 261,
Week: 1,
ShowHours: []int{12, 17, 18, 24},
ShowMinute: 35,
LastTime: 40,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 2,
ShowHours: []int{17, 18, 24},
ShowMinute: 0,
LastTime: 5,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 3,
ShowHours: []int{17, 18, 24},
ShowMinute: 0,
LastTime: 5,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 4,
ShowHours: []int{12, 17, 18, 24},
ShowMinute: 35,
LastTime: 40,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 5,
ShowHours: []int{17, 18, 24},
ShowMinute: 0,
LastTime: 5,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 6,
ShowHours: []int{17, 18, 24},
ShowMinute: 0,
LastTime: 5,
MapIDs: []uint32{15, 105, 54},
},
{
PetID: 261,
Week: 7,
ShowHours: generateHourRange(0, 23),
ShowMinute: 0,
LastTime: 10,
MapIDs: []uint32{15, 105, 54},
},
}
var (
registeredCronIDs = make(map[string]bool)
cronMu sync.Mutex
randSource = rand.New(rand.NewSource(time.Now().UnixNano()))
)
// generateHourRange builds an inclusive hour range.
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
}
func init() {
for _, rule := range timeBossRules {
for _, hour := range rule.ShowHours {
cronID := genCronTaskID(rule.PetID, rule.Week, hour, rule.ShowMinute)
cronMu.Lock()
if registeredCronIDs[cronID] {
cronMu.Unlock()
continue
}
registeredCronIDs[cronID] = true
cronMu.Unlock()
cronExpr := genCronExpr(rule.Week, hour, rule.ShowMinute)
currentRule := rule
cool.Cron.AddFunc(cronExpr, func() {
randomMapID := getRandomMapID(currentRule.MapIDs)
if randomMapID == 0 {
return
}
sp := GetSpace(randomMapID)
if sp != nil {
sp.refushgaiya(true)
time.AfterFunc(time.Duration(currentRule.LastTime)*time.Minute, func() {
sp.refushgaiya(false)
})
}
})
}
}
}
// refushgaiya updates timed boss visibility and broadcasts it.
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, 2021, &s.TimeBoss)
}
// getRandomMapID picks one random map id from candidates.
func getRandomMapID(mapIDs []uint32) uint32 {
if len(mapIDs) == 0 {
return 0
}
return mapIDs[randSource.Intn(len(mapIDs))]
}
// genCronExpr builds a Quartz-style cron expression.
func genCronExpr(week, hour, minute int) string {
cronHour := hour
if cronHour == 24 {
cronHour = 0
}
cronWeek := week
if cronWeek == 7 {
cronWeek = 0
}
return strings.Join([]string{
"0",
strconv.Itoa(minute),
strconv.Itoa(cronHour),
"?",
"*",
strconv.Itoa(cronWeek),
}, " ")
}
// genCronTaskID builds a unique task id for dedupe.
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 checks whether a map id exists in the list.
func containsMapID(mapIDs []uint32, mapid uint32) bool {
for _, id := range mapIDs {
if id == mapid {
return true
}
}
return false
}