项目结构
Player
服务器中每连接一个客户端,相当于一个玩家,封装一个Player结构体
type Player struct {
Pid int32
Conn ziface.IConnection
X float32
Y float32
Z float32
V float32
}
初始化一个玩家玩家发送消息给客户端
func (p *Player) SendMsg(msgID uint32, data proto.Message) error {
if p.Conn == nil {
fmt.Println("Connection Is Null Not Send Msg Error: ")
return errors.New("Connection Is Null Not Send Msg ")
}
buffer, err := proto.Marshal(data)
if err != nil {
fmt.Println("Send Error: ", err)
return err
}
err = p.Conn.SendMsg(msgID, buffer)
if err != nil {
fmt.Println("Send Error: ", err)
return err
}
return nil
}
当玩家连接上服务器时,服务器应该向客户端发送两个消息
- 同步玩家的ID
- 同步玩家的出生位置信息
func (p *Player) SyncPid() {
data := &Pb.SyncPid{Pid: p.Pid}
err := p.SendMsg(1, data)
if err != nil {
fmt.Println("Send SyncPid Message Error: ", err)
return
}
}
func (p *Player) BroadCastStartPosition() {
protoMsg := &Pb.BroadCase{
Pid: p.Pid,
Tp: 2,
Data: &Pb.BroadCase_P{
P: &Pb.Position{
X: p.X,
Y: p.Y,
Z: p.Z,
V: p.V,
},
},
}
err := p.SendMsg(200, protoMsg)
if err != nil {
fmt.Println("Send BroadCastStartPosition Message Error: ", err)
return
}
}
- 在注册连接接入的回调中执行这两个方法
WorldManager
新增WorldManager用来管理全部的Player以及AOIManager
var WorldMgrObj *WorldManager
因为全局唯一所以在init函数中初始化
func init() {
WorldMgrObj = &WorldManager{
AoiMgr: NewAOIManager(AOI_MIN_X, AOI_MAX_X, AOI_COUNT_X, AOI_MIN_Y, AOI_MAX_Y, AOI_COUNT_Y),
Players: make(map[int32]*Player),
}
}
- WorldManager中对Player的增删改查方法
func (wm *WorldManager) AddPlayer(player *Player) {
wm.PLock.Lock()
wm.Players[player.Pid] = player
wm.PLock.Unlock()
wm.AoiMgr.AddPlayerIDToGridByPos(int(player.Pid), player.X, player.Z)
}
func (wm *WorldManager) RemovePlayerByPid(pid int32) {
player, ok := wm.Players[pid]
if !ok {
fmt.Println("RemovePlayerByPid Pid:", pid, "Not Have")
return
}
wm.AoiMgr.RemovePlayerIDFormGridByPos(int(pid), player.X, player.Z)
wm.PLock.Lock()
delete(wm.Players, pid)
wm.PLock.Unlock()
}
func (wm *WorldManager) GetPlayerByPid(pid int32) *Player {
wm.PLock.RLock()
defer wm.PLock.RUnlock()
player, ok := wm.Players[pid]
if !ok {
fmt.Println("GetPlayerByPid Pid:", pid, "Not Have")
return nil
}
return player
}
func (wm *WorldManager) GetAllPlayers() []*Player {
wm.PLock.RLock()
defer wm.PLock.RUnlock()
players := make([]*Player, 0)
for _, p := range wm.Players {
players = append(players, p)
}
return players
}
- 当有客户端连接进来,创建Player之后需要添加到WorldManager中
- 同时Conn连接对象,需要拿到PlayerID
core.WorldMgrObj.AddPlayer(player)
conn.SetProperty("pid", player.Pid)