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) //switch pb.Channel(verifyAck.Channel) { //case pb.Channel_Internal: ////case pb.Channel_WechatMiniGame: //// var ok bool //// player.Temp.WechatSessionKey, ok = verifyAck.ThirdInfo["sessionKey"].(string) //// if !ok { //// this.logger.Error("User auth token verify ack does not has wechat sesscion key, thirdInfo: ", util.ToJsonString(verifyAck.ThirdInfo)) //// _ = this.TipNotice(msg.Conn, proto.ErrInternalError) //// return //// } //// //// if req.Args != nil && req.Args.WechatUserInfo != nil { //// player.Temp.ThirdData = &logic.PlayerThirdData{ //// NickName: req.Args.WechatUserInfo.NickName, //// AvatarUrl: req.Args.WechatUserInfo.AvatarUrl, //// } //// } ////case pb.Channel_TapTap: //// name, _ := verifyAck.ThirdInfo["name"].(string) //// avatar, _ := verifyAck.ThirdInfo["avatar"].(string) //// player.Temp.ThirdData = &logic.PlayerThirdData{ //// NickName: name, //// AvatarUrl: avatar, //// } //default: // _ = this.TipNotice(msg.Conn, proto.ErrChannelError) // return //} // //msg.Conn.BindObject(player) // //var ack = &pb.UserAuthAck{UserId: player.UserId} ////if player.Role != nil { //// ack.RoleList = []*proto.Role{{RoleId: player.UserId, RoleName: player.RoleName}} ////} // //_ = 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.ErrInternalError) 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 } 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.Username = authCtx.verifyAck.Username player.UserId = authCtx.verifyAck.UserId player.ServerId = this.server.AppId() 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.ErrInternalError) 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 } 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.TipNotice(msg.Conn, proto.ErrRoleNotCreated) 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 } player.Temp.Address = msg.Conn.RemoteAddr() msg.Conn.BindObject(player) this.playerManager.Reenter(player, msg.Conn) } 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) }