- 在 Player 结构中添加 MapId 字段,用于记录当前所在地图 ID - 新增地图配置解析功能,支持从 XML 文件中读取地图信息 - 实现玩家进入地图的逻辑,包括设置玩家位置和广播通知 - 更新登录逻辑,在玩家登录时自动进入默认地图 - 重构地图相关的数据结构和接口,为后续地图功能扩展做准备
72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package space
|
||
|
||
import (
|
||
"blazing/common/data/entity"
|
||
"blazing/modules/blazing/model"
|
||
"sync"
|
||
)
|
||
|
||
// Space 针对Player的并发安全map,键为uint32类型
|
||
type Space struct {
|
||
mu sync.RWMutex // 读写锁,读多写少场景更高效
|
||
data map[uint32]*entity.Player // 存储玩家数据的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]*entity.Player),
|
||
}
|
||
}
|
||
|
||
// Get 根据玩家ID获取玩家实例
|
||
// 读操作使用RLock,允许多个goroutine同时读取
|
||
func (m *Space) Get(playerID uint32) (*entity.Player, 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 *entity.Player) {
|
||
m.mu.Lock()
|
||
defer m.mu.Unlock()
|
||
m.data[playerID] = player
|
||
}
|
||
|
||
// 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 *entity.Player) bool) {
|
||
m.mu.RLock()
|
||
defer m.mu.RUnlock()
|
||
for id, player := range m.data {
|
||
// 若回调返回false,则停止遍历
|
||
if !f(id, player) {
|
||
break
|
||
}
|
||
}
|
||
}
|