362 lines
9.8 KiB
Go
362 lines
9.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"ecs/proto"
|
|
"ecs/proto/pb"
|
|
"ecs/servers/game/data"
|
|
"ecs/servers/game/logic"
|
|
"github.com/oylshe1314/framework/client/rpc"
|
|
"github.com/oylshe1314/framework/net"
|
|
"github.com/oylshe1314/framework/server"
|
|
"github.com/oylshe1314/framework/util"
|
|
)
|
|
|
|
type userAuthContext struct {
|
|
newId uint64
|
|
players []*logic.Player
|
|
verifyAck *proto.MsgUserTokenVerifyAck
|
|
}
|
|
|
|
type MessageHandler struct {
|
|
Handler
|
|
}
|
|
|
|
func NewMessageHandler(svr server.Server, httpRpcClient rpc.HttpRpcClient, tables *data.Tables, eventManager *logic.EventManager, serverManager *logic.ServerManager, playerManager *logic.PlayerManager) *MessageHandler {
|
|
return &MessageHandler{
|
|
Handler: Handler{
|
|
server: svr,
|
|
httpRpcClient: httpRpcClient,
|
|
tables: tables,
|
|
eventManager: eventManager,
|
|
serverManager: serverManager,
|
|
playerManager: playerManager},
|
|
}
|
|
}
|
|
|
|
func (this *MessageHandler) TipNotice(conn *net.Conn, err error) error {
|
|
//return conn.Send(uint16(pb.ModId_ModuleCommon), uint16(pb.MsgId_ModCommonTipNotice), &proto.MsgTipNoticeAck{Message: this.tables.TipNotice.GetLang(err.Error(), int(proto.LanguageSimpleChinese))})
|
|
return conn.Send(uint16(pb.ModId_ModuleCommon), uint16(pb.MsgId_ModCommonTipNotice), &pb.TipNoticeAck{Message: err.Error()})
|
|
}
|
|
|
|
func (this *MessageHandler) HandleConnect(conn *net.Conn) {
|
|
conn.Beating(uint16(pb.ModId_ModuleCommon), uint16(pb.MsgId_ModCommonHeartbeat), 60)
|
|
}
|
|
|
|
func (this *MessageHandler) HandleDisconnect(conn *net.Conn) {
|
|
var object = conn.Object()
|
|
if object == nil {
|
|
return
|
|
}
|
|
|
|
player, ok := object.(*logic.Player)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
this.playerManager.Lost(player)
|
|
|
|
this.eventManager.PlayerLogin(player, logic.LogTypePlayerLost, 0, conn.RemoteAddr())
|
|
}
|
|
|
|
func (this *MessageHandler) Heartbeat(msg *net.Message) {
|
|
var req = new(pb.HeartbeatReq)
|
|
var err = msg.Read(req)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrMessageError)
|
|
return
|
|
}
|
|
var now = util.NowUnix()
|
|
msg.Conn.Beat(now)
|
|
var ack = &pb.HeartbeatAck{Index: req.Index, ServerTime: now}
|
|
_ = msg.Reply(ack)
|
|
}
|
|
|
|
func (this *MessageHandler) UserAuth(msg *net.Message) {
|
|
var req = new(pb.UserAuthReq)
|
|
var err = msg.Read(req)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrMessageError)
|
|
return
|
|
}
|
|
|
|
if len(req.Token) == 0 {
|
|
this.Logger().Error("User auth token is empty")
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInvalidToken)
|
|
return
|
|
}
|
|
|
|
var verifyReq = &proto.MsgUserTokenVerifyReq{Token: req.GetToken(), ServerId: this.serverManager.Config().AreaConfig.Id}
|
|
if this.Logger().IsDebugEnabled() {
|
|
this.Logger().Debugf("[user:/verify/token] -> verifyReq: %s", util.ToJsonString(verifyReq))
|
|
}
|
|
|
|
var verifyAck = new(proto.MsgUserTokenVerifyAck)
|
|
reply, err := this.httpRpcClient.RandPost("user", "/verify/token", nil, verifyReq, verifyAck)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
if err = reply.Error(); err != nil {
|
|
this.Logger().Error(reply.Message)
|
|
_ = this.TipNotice(msg.Conn, err)
|
|
return
|
|
}
|
|
|
|
if reply.Data == nil {
|
|
this.Logger().Error("User auth token verify error, reply.Data == nil")
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInvalidToken)
|
|
return
|
|
}
|
|
|
|
if this.Logger().IsDebugEnabled() {
|
|
this.Logger().Debugf("[user:/verify/token] <- verifyAck: %s", util.ToJsonString(verifyAck))
|
|
}
|
|
|
|
if !proto.CheckPlatform(verifyAck.Platform) {
|
|
this.Logger().Error("User auth token verify ack platform error, platfrom: ", verifyAck.Platform)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
if !proto.CheckChannel(verifyAck.Channel) {
|
|
this.Logger().Error("User auth token verify ack channel error, channel: ", verifyAck.Channel)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
players, err := this.playerManager.QueryPlayers(verifyAck.UserId) //query player from database
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
var roleList []*pb.Role
|
|
for i := range players {
|
|
if players[i].BanningTime < 0 || players[i].BanningTime > util.NowUnix() {
|
|
this.Logger().Error("Player role banned, roleId: %d, banTime: %d", players[i].RoleId, players[i].BanningTime)
|
|
continue
|
|
}
|
|
|
|
var player = this.playerManager.GetPlayer(players[i].RoleId) //get player from memory
|
|
if player != nil {
|
|
this.playerManager.Kick(player, proto.ErrLoginOtherPlace.Error())
|
|
this.eventManager.PlayerLogin(player, logic.LogTypePlayerKickOut, 0, player.Temp.Address)
|
|
player = nil
|
|
}
|
|
|
|
roleList = append(roleList, &pb.Role{Id: players[i].RoleId, Name: players[i].RoleName, Gender: players[i].RoleGender})
|
|
}
|
|
|
|
msg.Conn.BindObject(&userAuthContext{players: players, verifyAck: verifyAck})
|
|
|
|
var ack = &pb.UserAuthAck{UserId: verifyAck.UserId, RoleList: roleList}
|
|
_ = msg.Reply(ack)
|
|
}
|
|
|
|
func (this *MessageHandler) RoleCreate(msg *net.Message) {
|
|
var object = msg.Conn.Object()
|
|
if object == nil {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrUserNotLogin)
|
|
return
|
|
}
|
|
|
|
authCtx, ok := object.(*userAuthContext)
|
|
if !ok {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrBadRequest)
|
|
return
|
|
}
|
|
|
|
if len(authCtx.players) >= this.serverManager.Config().MaxRoles {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrRolesAlreadyMax)
|
|
return
|
|
}
|
|
|
|
var req = new(pb.RoleCreateReq)
|
|
var err = msg.Read(req)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrMessageError)
|
|
return
|
|
}
|
|
|
|
if len(req.Name) == 0 {
|
|
this.Logger().Error("Parameter error, req.Name can not be empty")
|
|
_ = this.TipNotice(msg.Conn, proto.ErrParameterError)
|
|
return
|
|
}
|
|
|
|
if req.Gender != 0 && req.Gender != 1 {
|
|
this.Logger().Error("Parameter error, req.Gender: ", req.Gender)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrParameterError)
|
|
return
|
|
}
|
|
|
|
roleId, err := this.playerManager.NewRoleId()
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
var areaConfig = this.serverManager.Config().AreaConfig
|
|
|
|
var player = this.playerManager.NewPlayer()
|
|
player.RoleId = roleId
|
|
player.Platform = authCtx.verifyAck.Platform
|
|
player.Channel = authCtx.verifyAck.Channel
|
|
player.UserId = authCtx.verifyAck.UserId
|
|
player.ServerId = areaConfig.Id
|
|
player.Username = authCtx.verifyAck.Username
|
|
player.CreateTime = util.NowUnix()
|
|
|
|
player.Language = 0
|
|
player.RoleName = req.Name
|
|
player.RoleGender = req.Gender
|
|
|
|
err = this.playerManager.SavePlayer(player)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
|
|
authCtx.newId = player.RoleId
|
|
authCtx.players = append(authCtx.players, player)
|
|
|
|
_ = msg.Reply(&pb.RoleCreateAck{Role: &pb.Role{Id: player.RoleId, Name: player.RoleName, Gender: player.RoleGender}})
|
|
|
|
this.eventManager.PlayerCreate(player, logic.LogTypePlayerRoleCreate)
|
|
}
|
|
|
|
func (this *MessageHandler) RoleLogin(msg *net.Message) {
|
|
var object = msg.Conn.Object()
|
|
if object == nil {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrUserNotLogin)
|
|
return
|
|
}
|
|
|
|
authCtx, ok := object.(*userAuthContext)
|
|
if !ok {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrBadRequest)
|
|
return
|
|
}
|
|
|
|
if len(authCtx.players) == 0 {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrRoleNotCreated)
|
|
return
|
|
}
|
|
|
|
var req = new(pb.RoleLoginReq)
|
|
var err = msg.Read(req)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrMessageError)
|
|
return
|
|
}
|
|
|
|
if req.RoleId == 0 {
|
|
this.Logger().Error("Parameter error, req.RoleId: ", req.RoleId)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrParameterError)
|
|
return
|
|
}
|
|
|
|
var player *logic.Player
|
|
for i := range authCtx.players {
|
|
if authCtx.players[i].RoleId == req.RoleId {
|
|
player = authCtx.players[i]
|
|
if player.RoleId != authCtx.newId {
|
|
player, err = this.playerManager.QueryPlayer(req.RoleId)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrInternalError)
|
|
return
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
if player == nil {
|
|
this.Logger().Error("Parameter error, req.RoleId: ", req.RoleId)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrRoleNotFound)
|
|
return
|
|
}
|
|
|
|
player.Temp.Address = msg.Conn.RemoteAddr()
|
|
|
|
msg.Conn.BindObject(player)
|
|
this.playerManager.Enter(player, msg.Conn)
|
|
|
|
this.eventManager.PlayerLogin(player, logic.LogTypePlayerRoleLogin, 0, msg.Conn.RemoteAddr())
|
|
}
|
|
|
|
func (this *MessageHandler) RoleLogout(msg *net.Message) {
|
|
var object = msg.Conn.Object()
|
|
if object == nil {
|
|
return
|
|
}
|
|
|
|
msg.Conn.ClearObject()
|
|
|
|
player, ok := object.(*logic.Player)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
this.playerManager.Exit(player)
|
|
|
|
this.eventManager.PlayerLogin(player, logic.LogTypePlayerRoleLogout, 0, msg.Conn.RemoteAddr())
|
|
}
|
|
|
|
func (this *MessageHandler) Reconnect(msg *net.Message) {
|
|
var req = new(pb.ReconnectReq)
|
|
var err = msg.Read(req)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
_ = this.TipNotice(msg.Conn, proto.ErrMessageError)
|
|
_ = msg.Conn.Send(uint16(pb.ModId_ModuleLevel), uint16(pb.MsgId_ModLevelSceneEnter), &pb.SceneEnterAck{SceneId: 2})
|
|
return
|
|
}
|
|
|
|
var player = this.playerManager.GetPlayer(req.RoleId)
|
|
if player == nil {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrUserNotLogin)
|
|
_ = msg.Conn.Send(uint16(pb.ModId_ModuleLevel), uint16(pb.MsgId_ModLevelSceneEnter), &pb.SceneEnterAck{SceneId: 2})
|
|
return
|
|
}
|
|
|
|
player.Temp.Address = msg.Conn.RemoteAddr()
|
|
|
|
msg.Conn.BindObject(player)
|
|
this.playerManager.Reenter(player, msg.Conn)
|
|
|
|
this.eventManager.PlayerLogin(player, logic.LogTypePlayerReconnect, 0, msg.Conn.RemoteAddr())
|
|
}
|
|
|
|
func (this *MessageHandler) Message(msg *net.Message) {
|
|
var object = msg.Conn.Object()
|
|
if object == nil {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrUserNotLogin)
|
|
return
|
|
}
|
|
|
|
player, ok := object.(*logic.Player)
|
|
if !ok {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrRoleNotLogged)
|
|
return
|
|
}
|
|
|
|
//player = this.playerManager.GetPlayer(player.UserId)
|
|
//if player == nil {
|
|
// _ = this.TipNotice(msg.Conn, proto.ErrRoleNotLogged)
|
|
// return
|
|
//}
|
|
|
|
this.playerManager.Handle(player, msg)
|
|
}
|