package space import ( "blazing/common/data/xmlres" "blazing/common/utils" "blazing/logic/service/common" "blazing/modules/blazing/model" "sync" ) // Space 针对Player的并发安全map,键为uint32类型 type Space struct { mu sync.RWMutex // 读写锁,读多写少场景更高效 data map[uint32]common.PlayerI // 存储玩家数据的map,键为玩家ID CanRefresh bool //是否能够刷怪 ID uint32 // 地图ID Name string //地图名称 DefaultPos model.Pos //默认位置DefaultPos Positions map[uint32]model.Pos //从上一个地图跳转后默认位置 } // NewSyncMap 创建一个新的玩家同步map func NewSpace() *Space { return &Space{ data: make(map[uint32]common.PlayerI), } } // Get 根据玩家ID获取玩家实例 // 读操作使用RLock,允许多个goroutine同时读取 func (m *Space) Get(playerID uint32) (common.PlayerI, bool) { m.mu.RLock() defer m.mu.RUnlock() val, exists := m.data[playerID] return val, exists } // Set 存储玩家实例(按ID) // 写操作使用Lock,独占锁保证数据一致性 func (m *Space) Set(playerID uint32, player common.PlayerI) *Space { m.mu.Lock() defer m.mu.Unlock() m.data[playerID] = player return m } // Delete 根据玩家ID删除玩家实例 // 写操作使用Lock func (m *Space) Delete(playerID uint32) { m.mu.Lock() defer m.mu.Unlock() delete(m.data, playerID) } // Len 获取当前玩家数量 // 读操作使用RLock func (m *Space) Len() int { m.mu.RLock() defer m.mu.RUnlock() return len(m.data) } // Range 遍历所有玩家并执行回调函数 // 读操作使用RLock,遍历过程中不会阻塞其他读操作 func (m *Space) Range(f func(playerID uint32, player common.PlayerI) bool) { m.mu.RLock() defer m.mu.RUnlock() for id, player := range m.data { // 若回调返回false,则停止遍历 if !f(id, player) { break } } } // 获取星球 func GetSpace(id uint32) *Space { planet, ok := planetmap.Load(id) if ok { return planet } if id > 10000 { //说明是玩家地图GetSpace t := NewSpace() planetmap.Store(id, t) return t } //如果不ok,说明星球未创建,那就新建星球 for _, v := range xmlres.MapConfig.Maps { if v.ID == int(id) { //找到这个地图 t := NewSpace() t.DefaultPos = model.Pos{X: uint32(v.X), Y: uint32(v.Y)} t.ID = uint32(v.ID) t.Name = v.Name t.Positions = make(map[uint32]model.Pos) for _, v := range v.Entries.Entries { //添加地图入口 t.Positions[uint32(v.FromMap)] = model.Pos{X: uint32(v.PosX), Y: uint32(v.PosY)} } planetmap.Store(id, t) return t } } return nil } var planetmap = &utils.SyncMap[uint32, *Space]{} //玩家数据 type LeaveMapOutboundInfo struct { // 米米号 UserID uint32 `struc:"uint32" fieldDesc:"米米号" json:"user_id"` }