Files
bl/logic/service/space/space.go
昔念 d4551a8c35
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
refactor(space): 重构空间初始化逻辑并修复变量作用域问题

- 将tips和pits的初始化移到循环外部,避免重复创建
- 修复Name赋值位置,确保在正确时机设置空间名称
- 添加条件判断ret.Super != 0,优化性能
- 调整代码结构,提高可读性和维护性
- 移除注释掉的无用代码
```
2026-03-03 01:07:30 +08:00

281 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package space
import (
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/cool"
"strconv"
"strings"
"sync/atomic"
"time"
"blazing/logic/service/common"
"blazing/logic/service/space/info"
"blazing/modules/config/model"
"blazing/modules/config/service"
infomodel "blazing/modules/player/model"
"github.com/gogf/gf/v2/util/grand"
csmap "github.com/mhmtszr/concurrent-swiss-map"
"github.com/samber/lo"
"github.com/tnnmigga/enum"
)
// 定义天气状态枚举实例
var WeatherStatus = enum.New[struct {
Normal uint32 `enum:"0"` // 正常
Rain uint32 `enum:"1"` // 下雨
Snow uint32 `enum:"2"` // 下雪
}]()
// Space 针对Player的并发安全map键为uint32类型
type Space struct {
User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map键为玩家ID
UserInfo *csmap.CsMap[uint32, info.SimpleInfo]
CanRefresh bool //是否能够刷怪
Super uint32
//SuperValue *int32
ID uint32 // 地图ID
Name string //地图名称
Owner ARENA
info.MapBossSInfo
IsChange bool
WeatherType []uint32
TimeBoss info.S2C_2022
//Weather uint32
IsTime bool
PitS *csmap.CsMap[int, []model.MapPit]
}
// NewSyncMap 创建一个新的玩家同步map
func NewSpace() *Space {
ret := &Space{
User: csmap.New[uint32, common.PlayerI](),
UserInfo: csmap.New[uint32, info.SimpleInfo](),
}
return ret
}
// 获取星球
func GetSpace(id uint32) *Space {
planet, ok := planetmap.Load(id)
if ok {
return planet
}
ret := NewSpace()
ret.ID = id
defer ret.init()
planetmap.Store(id, ret)
return ret
}
var planetmap = csmap.New[uint32, *Space]()
func ParseCoordinateString(s string) []infomodel.Pos {
// 存储解析后的坐标
var points []infomodel.Pos
// 空字符串处理
if strings.TrimSpace(s) == "" {
return points
}
// 第一步:按竖线分割成单个坐标字符串
coordStrs := strings.Split(s, "|")
for _, coordStr := range coordStrs {
// 去除首尾空格(兼容可能的格式不规范)
coordStr = strings.TrimSpace(coordStr)
if coordStr == "" {
return nil
}
// 第二步按逗号分割X、Y值
xy := strings.Split(coordStr, ",")
if len(xy) != 2 {
return nil
}
// 第三步:转换为整数
xStr := strings.TrimSpace(xy[0])
yStr := strings.TrimSpace(xy[1])
x, err := strconv.Atoi(xStr)
if err != nil {
return nil
}
y, err := strconv.Atoi(yStr)
if err != nil {
return nil
}
// 添加到切片
points = append(points, infomodel.Pos{X: uint32(x), Y: uint32(y)})
}
return points
}
func (t *Space) Next(time.Time) time.Time {
return time.Now().Add(grand.D(6*time.Second, 30*time.Second))
}
func (ret *Space) init() {
if ret.ID < 10000 { //说明是玩家地图GetSpace
for _, v := range xmlres.MapConfig.Maps {
if v.ID == int(ret.ID) { //找到这个地图
ret.Super = uint32(v.Super)
if ret.Super == 0 {
ret.Super = uint32(v.ID)
}
ret.ID = uint32(v.ID)
_, ok := maphot[ret.Super]
if !ok {
maphot[ret.Super] = &MapTip{}
maphot[ret.Super].TipInfoS = make(map[uint32]*TipInfo, 0)
}
ret.Name = v.Name
//ogreconfig := service.NewMapPitService().GetData(ret.ID, uint32(i))
break
}
}
tips := &TipInfo{}
r := service.NewMapService().GetData(ret.ID)
if r != nil {
tips.Diao = service.NewMapService().GetData(ret.ID).DropItemIds
}
pits := service.NewMapPitService().GetDataALL(ret.ID)
ret.PitS = csmap.New[int, []model.MapPit]()
for _, v := range pits {
tips.Pet = append(tips.Pet, v.RefreshID...)
for _, vp := range v.Pos {
t, ok := ret.PitS.Load(vp)
if ok {
t = append(t, v)
ret.PitS.Store(vp, t)
} else {
ret.PitS.Store(vp, []model.MapPit{v})
}
}
}
if ret.Super != 0 {
tips.Pet = lo.Union(tips.Pet)
tips.Talk = service.NewTalkConfigService().GetTip(ret.ID)
tips.Boss = service.NewMapNodeService().GetTip(ret.ID)
maphot[ret.Super].TipInfoS[ret.ID] = tips
}
}
r := service.NewMapService().GetData(ret.ID)
if r != nil {
if r.IsTimeSpace != 0 {
ret.IsTime = true
}
ret.MapBossSInfo = info.MapBossSInfo{}
ret.MapBossSInfo.INFO = make([]info.MapBossInfo, 0)
if len(r.WeatherType) > 1 {
ret.WeatherType = r.WeatherType
// ret.CanWeather = 1
cool.Cron.CustomFunc(ret, ret.GenWer)
}
for _, v := range service.NewMapNodeService().GetDataB(ret.ID) {
info := info.MapBossInfo{
Id: v.TriggerID,
Region: v.NodeID, //这个是注册的index
Hp: v.HP,
PosInfo: ParseCoordinateString(v.Pos),
MaxHP: int(v.HP),
Wer: v.Weather,
}
ret.MapBossSInfo.INFO = append(ret.MapBossSInfo.INFO, info)
}
if len(ret.MapBossSInfo.INFO) > 0 {
cool.Cron.ScheduleFunc(10*time.Second, ret.GenBoss)
cool.Cron.ScheduleFunc(300*time.Second, ret.HealHP)
}
}
}
func (ret *Space) GenBoss() {
for i := 0; i < len(ret.MapBossSInfo.INFO); i++ {
s := len(ret.MapBossSInfo.INFO[i].PosInfo)
if s != 0 {
ret.MapBossSInfo.INFO[i].Pos = ret.MapBossSInfo.INFO[i].PosInfo[(grand.Intn(s-1)+1+int(ret.MapBossSInfo.INFO[i].PosIndex))%s]
}
_, ok := lo.Find(ret.MapBossSInfo.INFO[i].Wer, func(item int32) bool {
return item == ret.MapBossSInfo.Wer
})
if ok {
ret.MapBossSInfo.INFO[i].IsShow = 1
if ret.IsChange {
ret.MapBossSInfo.INFO[i].IsShow = 2
}
} else {
ret.MapBossSInfo.INFO[i].IsShow = 0
}
}
ret.Broadcast(nil, 2021, &ret.MapBossSInfo)
}
func (ret *Space) HealHP() {
for _, v := range ret.MapBossSInfo.INFO {
atomic.StoreInt32(&v.Hp, int32(v.MaxHP))
}
}
func (ret *Space) GenWer() {
//if ret.CanWeather == 1 {
var neww uint32 = 0
if len(ret.WeatherType) == 2 {
neww, _ = utils.RandomByWeight(ret.WeatherType, []uint32{9, 1})
} else {
neww, _ = utils.RandomByWeight(ret.WeatherType, []uint32{8, 1, 1})
}
if neww != uint32(ret.MapBossSInfo.Wer) {
ret.IsChange = true
ret.MapBossSInfo.Wer = int32(neww)
ret.GenBoss()
println(ret.Name, "change weather", neww)
} else {
ret.IsChange = false
}
//}
}