Files
bl/logic/service/space/boss_time.go
昔念 0ae65cee45
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
1
2026-04-24 17:22:25 +08:00

135 lines
2.7 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{}
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
}