All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
feat(game): 实现扭蛋系统批量物品添加功能并优化地图逻辑 - 新增ItemAddBatch方法用于批量添加物品,支持普通道具和特殊道具的分别处理 - 优化扭蛋游戏玩法中的物品添加逻辑,使用新的批量接口提升性能 - 在扭蛋机器人命令中实现完整的物品检查和批量添加流程 refactor(map): 重构地图控制器代码结构并添加注释 - 为EnterMap、LeaveMap、GetMapPlayerList等方法添加中文注释 - 统一地图相关的命名规范,如enter
192 lines
3.8 KiB
Go
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
|
|
}
|