基于GoLang的MMO游戏服务器(四)

世界聊天

  • 首先定义世界聊天的路由方法
    在这里插入图片描述
    具体实现
type WorldChatAPI struct {
	znet.BaseRouter
}

func (wca WorldChatAPI) Handle(request ziface.IRequest) {
	pid, err := request.GetConnection().GetProperty("pid")
	if err != nil {
		fmt.Println(err)
		return
	}
	protoMsg := &Pb.Talk{}
	err = proto.Unmarshal(request.GetData(), protoMsg)
	if err != nil {
		fmt.Println(err)
		return
	}
	player := core.WorldMgrObj.GetPlayerByPid(pid.(int32))
	player.Talk(protoMsg.Content)
}
  • 对聊天业务的处理
func (p *Player) Talk(context string) {
	protoMsg := &Pb.BroadCase{
		Pid: p.Pid,
		Tp:  1,
		Data: &Pb.BroadCase_Content{
			Content: context,
		},
	}
	players := WorldMgrObj.GetAllPlayers()
	for _, player := range players {
		player.SendMsg(200, protoMsg)
	}
}

让周围玩家显示当前玩家,当前玩家显示其它玩家

  • 当玩家接入成功后,在回调中添加同步玩家方法
    在这里插入图片描述
  • 告知其它玩家我上线
  • 告知我其它玩家位置信息
func (p *Player) SyncSurrounding() {
	playerIDs := WorldMgrObj.AoiMgr.GetSurroundPlayersByPos(p.X, p.Z)
	if playerIDs != nil && len(playerIDs) > 0 {
		// 告知其它玩家我上线

		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,
				}},
		}
		players := make([]*Pb.Player, 0, len(playerIDs))
		for i := 0; i < len(playerIDs); i++ {
			player := WorldMgrObj.GetPlayerByPid(int32(playerIDs[i]))
			players = append(players, &Pb.Player{
				Pid: int32(playerIDs[i]),
				P: &Pb.Position{
					X: player.X,
					Y: player.Y,
					Z: player.Z,
					V: player.V,
				},
			})
			player.SendMsg(200, protoMsg)
		}

		// 告知我其它玩家位置信息

		protoMsg1 := &Pb.SyncPlayers{Ps: players}
		p.SendMsg(202, protoMsg1)
	}

}

同步玩家移动

在这里插入图片描述

  • 路由方法的具体实现
type MoveAPI struct {
	znet.BaseRouter
}

func (m MoveAPI) Handle(request ziface.IRequest) {
	protoMsg := &Pb.Position{}
	err := proto.Unmarshal(request.GetData(), protoMsg)
	if err != nil {
		fmt.Println(err)
		return
	}
	pid, err := request.GetConnection().GetProperty("pid")
	if err != nil {
		fmt.Println(err)
		return
	}
	player := core.WorldMgrObj.GetPlayerByPid(pid.(int32))
	if player == nil {
		return
	}
	player.UpdatePos(protoMsg.X, protoMsg.Y, protoMsg.Z, protoMsg.V)
}
  • 更新玩家的位置
func (p *Player) UpdatePos(x, y, z, v float32) {
	p.X = x
	p.Y = y
	p.Z = z
	p.V = v
	protoMsg := &Pb.BroadCase{
		Pid: p.Pid,
		Tp:  4,
		Data: &Pb.BroadCase_P{
			P: &Pb.Position{
				X: x,
				Y: y,
				Z: z,
				V: v,
			},
		},
	}
	playerIDs := WorldMgrObj.AoiMgr.GetSurroundPlayersByPos(x, z)
	for i := 0; i < len(playerIDs); i++ {
		player := WorldMgrObj.GetPlayerByPid(int32(playerIDs[i]))
		player.SendMsg(200, protoMsg)
	}
}

同步玩家下线功能

  • 添加连接断开回调函数
    在这里插入图片描述
  • Offline方法具体实现
func (p *Player) Offline() {
	playerIDs := WorldMgrObj.AoiMgr.GetSurroundPlayersByPos(p.X, p.Z)
	protoMsg := &Pb.SyncPid{Pid: p.Pid}
	for i := 0; i < len(playerIDs); i++ {
		player := WorldMgrObj.GetPlayerByPid(int32(playerIDs[i]))
		player.SendMsg(201, protoMsg)
	}
	WorldMgrObj.RemovePlayerByPid(p.Pid)
}