364 lines
10 KiB
Go
364 lines
10 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
|
|
|
|
//eventManager *logic.EventManager
|
|
serverManager *logic.ServerManager
|
|
playerManager *logic.PlayerManager
|
|
|
|
httpRpcClient *rpc.HttpRpcClient
|
|
}
|
|
|
|
func NewMessageHandler(svr server.Server, tables *data.Tables /*eventManager *logic.EventManager, */, serverManager *logic.ServerManager, playerManager *logic.PlayerManager, httpRpcClient *rpc.HttpRpcClient) *MessageHandler {
|
|
return &MessageHandler{Handler: newHandler(svr, tables) /*eventManager: eventManager, */, serverManager: serverManager, playerManager: playerManager, httpRpcClient: httpRpcClient}
|
|
}
|
|
|
|
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.PlayerLogout(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.Unix()
|
|
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.server.AppId()}
|
|
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
|
|
}
|
|
|
|
var player = this.playerManager.GetPlayer(verifyAck.UserId) //get player from memory
|
|
if player != nil {
|
|
this.playerManager.Kick(player, proto.ErrLoginOtherPlace.Error())
|
|
player = nil
|
|
}
|
|
|
|
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 p.BanningTime < 0 || p.BanningTime > util.Unix() {
|
|
// this.logger.Error("Player role banned, userId: %d, roleId: %d, banTime: %d", p.UserId, p.RoleId, p.BanningTime)
|
|
// continue
|
|
//}
|
|
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)
|
|
|
|
//this.eventManager.PlayerLogin(player, logic.LogTypePlayerUserLogin, 0, msg.Conn.RemoteAddr())
|
|
}
|
|
|
|
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 player = this.playerManager.NewPlayer()
|
|
player.RoleId = roleId
|
|
player.Platform = authCtx.verifyAck.Platform
|
|
player.Channel = authCtx.verifyAck.Channel
|
|
player.UserId = authCtx.verifyAck.UserId
|
|
player.ServerId = this.server.AppId()
|
|
player.Username = authCtx.verifyAck.Username
|
|
player.CreateTime = util.Unix()
|
|
|
|
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.UserId)
|
|
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
|
|
}
|
|
|
|
if req.RoleId != player.RoleId {
|
|
_ = this.TipNotice(msg.Conn, proto.ErrRoleNotLogged)
|
|
_ = 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.LogTypePlayerRoleLogout, 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)
|
|
}
|