package main import ( "github.com/golang/protobuf/proto" "math" "pro2d/cmd/gameserver/action" "pro2d/common" "pro2d/common/components" "pro2d/common/logger" "pro2d/models" "pro2d/pb" "sync" "sync/atomic" ) type Agent struct { components.IConnection Server components.IServer Role *models.RoleModel nextCheckTime int64 //下一次检查的时间 lastHeartCheckTime int64 heartTimeoutCount int //超时次数 } var agentPool = sync.Pool{New: func() interface{} { return new(Agent)}} func NewAgent(s components.IServer) *Agent { a := agentPool.Get().(*Agent) a.Server = s a.nextCheckTime = 0 a.lastHeartCheckTime = common.Timex() a.heartTimeoutCount= 0 return a } func (c *Agent) OnConnection(conn components.IConnection) { c.IConnection = conn } func (c *Agent) OnLogin(msg components.IMessage) { //第一次登录 errCode, irole := action.LoginRpc(msg) if errCode != 0 { c.Send(errCode, msg.GetHeader().GetMsgID(), nil) return } role := irole.(*models.RoleModel) protoMsg := &pb.RoleRsp{ Role: role.Role, Hero: role.GetAllHero(), Team: role.GetAllTeam(), } rsp, err := proto.Marshal(protoMsg) if err != nil { c.Send(-100, msg.GetHeader().GetMsgID(), nil) return } c.Send(errCode, msg.GetHeader().GetMsgID(), rsp) //登录成功,存储agent role c.Role = role } func (c *Agent) OnMessage(msg components.IMessage) { atomic.StoreInt64(&c.lastHeartCheckTime, common.Timex()) if msg.GetHeader().GetMsgID() == uint32(pb.ProtoCode_LoginReq) { c.OnLogin(msg) return } md := c.Server.GetAction(msg.GetHeader().GetMsgID()) if md == nil { logger.Debug("cmd: %d, handler is nil", msg.GetHeader().GetMsgID()) return } logger.Debug("protocolID: %d", msg.GetHeader().GetMsgID()) //fmt.Printf("errCode: %d, protoMsg:%v\n", errCode, protoMsg) f := md.(func (msg components.IMessage) (int32, interface{})) errCode, protoMsg := f(msg) if protoMsg == nil { c.Send(errCode, msg.GetHeader().GetMsgID(), nil) return } rsp, err := proto.Marshal(protoMsg.(proto.Message)) if err != nil { c.Send(-100, msg.GetHeader().GetMsgID(), nil) return } c.Send(errCode, msg.GetHeader().GetMsgID(), rsp) } func (c *Agent) OnTimer() { nextCheckTime := atomic.LoadInt64(&c.nextCheckTime) now := common.Timex() if now >= nextCheckTime { //检查心跳 c.checkHeartBeat(now) nextCheckTime = now + common.HeartTimerInterval atomic.StoreInt64(&c.nextCheckTime, nextCheckTime) } if c.Role != nil { //role 恢复数据 c.Role.OnRecoverTimer(now) } } func (c *Agent) OnClose() { c.Close() } func (c *Agent) Close() { c.Role = nil agentPool.Put(c) if c.Role == nil { return } c.Role.OnOfflineEvent() } func (c *Agent) checkHeartBeat(now int64) { lastHeartCheckTime := atomic.LoadInt64(&c.lastHeartCheckTime) //logger.Debug("checkHeartBeat ID: %d, last: %d, now: %d", c.GetID(), lastHeartCheckTime, now) if math.Abs(float64(lastHeartCheckTime - now)) > common.HeartTimerInterval { c.heartTimeoutCount++ if c.heartTimeoutCount >= common.HeartTimeoutCountMax { c.Stop() return } logger.Debug("timeout count: %d", c.heartTimeoutCount) }else { c.heartTimeoutCount = 0 } }