修改bug

This commit is contained in:
liuxiaobo 2025-06-17 18:22:26 +08:00
parent a023c28dc8
commit 94068c16d5
7 changed files with 99 additions and 20 deletions

View File

@ -25,6 +25,7 @@ func RpcGetGameUser(s service.IService, uid int64) (*user.GameUser, pb.ErrCode)
},
}
rpcMsg := ipb.MakeRpcMsg(GetGameUser, uid, us)
log.DebugF("%v call rpc:%v", s.Name(), GetGameUser)
rspMsg, err := s.CallByServiceId(int(pb.ServiceTypeId_STI_DB), timeout, rpcMsg)
if err != nil {
log.ErrorF("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error())

View File

@ -73,6 +73,10 @@ func (m *UserBindService) DelUserService(userId int64, typeId pb.ServiceTypeId)
// 保存玩家与节点的绑定关系至从redis
func (m *UserBindService) SaveUserService(userId int64, typeId pb.ServiceTypeId, serviceName string) {
if userId == 0 {
log.Error("玩家不能为0")
return
}
key := m.makeRedisKey(userId)
subKey := m.makeRedisSubKey(typeId)
m.rdb.HSet(context.Background(), key, subKey, serviceName)

View File

@ -29,6 +29,16 @@ func (s *ClientService) onLogin(cMsg *pb.ClientMsg, msg *pb.RspUserLogin) {
s.reqMatchRoom()
}
// 收到登陆成功消息,判断是否顶号
func (s *ClientService) onLogout(cMsg *pb.ClientMsg, msg *pb.RspUserLogout) {
if msg.Code != pb.ErrCode_OK {
log.ErrorF("onLogout error:%v :%v", msg.Code, msg.Code.String())
return
}
_ = cMsg
log.DebugF("user:%v logout", s.userId)
}
func (s *ClientService) reqMatchRoom() {
log.DebugF(s.Log("ready reqMatch"))
s.SendMsg(pb.ServiceTypeId_STI_Match, int32(pb.MsgId_ReqMatchRoomId), &pb.ReqMatchRoom{

View File

@ -7,8 +7,9 @@ import (
func (s *ClientService) initProcessor() {
s.processor.RegisterMessages(processor.RegisterMetas{
pb.MsgId_RspUserLoginId: {pb.RspUserLogin{}, s.onLogin},
pb.MsgId_RspMatchRoomId: {pb.RspMatchRoom{}, s.onMatchRoom},
pb.MsgId_RspEnterRoomId: {pb.RspEnterRoom{}, s.onEnterRoom},
pb.MsgId_RspUserLoginId: {pb.RspUserLogin{}, s.onLogin},
pb.MsgId_RspMatchRoomId: {pb.RspMatchRoom{}, s.onMatchRoom},
pb.MsgId_RspEnterRoomId: {pb.RspEnterRoom{}, s.onEnterRoom},
pb.MsgId_RspUserLogoutId: {pb.RspUserLogout{}, s.onLogout},
})
}

View File

@ -7,6 +7,7 @@ import (
"github.com/fox/fox/log"
"github.com/fox/fox/processor"
"github.com/fox/fox/ws"
"github.com/fox/fox/xrand"
"github.com/golang/protobuf/proto"
"time"
)
@ -47,7 +48,7 @@ func newClientService(serviceId int) *ClientService {
s.username = fmt.Sprintf("test%04d", serviceId)
s.password = "123456"
size := len(config.ClientCfg.Address)
addr := config.ClientCfg.Address[serviceId%size]
addr := config.ClientCfg.Address[xrand.RandN(size)]
wsAddr := fmt.Sprintf("ws://%v", addr)
if s.client, err = ws.NewClient(wsAddr, s); err != nil {
log.FatalF("connect url:%v err:%v", wsAddr, err.Error())

View File

@ -4,9 +4,11 @@ import (
"game/common/proto/pb"
"game/common/topicName"
"github.com/fox/fox/ipb"
"github.com/fox/fox/log"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
"github.com/fox/fox/ws"
"reflect"
"time"
)
/*
@ -16,12 +18,13 @@ func (s *GateService) initProcessor() {
s.Processor().RegisterMessages(processor.RegisterMetas{
pb.MsgId_RspUserLoginId: {pb.RspUserLogin{}, s.onUserLogin},
pb.MsgId_RspUserLogoutId: {pb.RspUserLogout{}, s.onUserLogout},
pb.MsgId_NtfUserOnlineId: {pb.NtfUserOnline{}, s.onUserOnline},
})
}
// 收到登陆成功消息,判断是否顶号
func (s *GateService) onUserLogin(iMsg *ipb.InternalMsg, conn ws.IConn, msg *pb.RspUserLogin) {
if conn == nil {
if conn == nil || reflect.ValueOf(conn).IsNil() {
return
}
// 登陆失败,回传玩家
@ -29,24 +32,61 @@ func (s *GateService) onUserLogin(iMsg *ipb.InternalMsg, conn ws.IConn, msg *pb.
s.SendClientMsg(conn, iMsg.ServiceName, int32(pb.MsgId_RspUserLoginId), msg)
return
}
s.SendClientMsg(conn, iMsg.ServiceName, int32(pb.MsgId_RspUserLoginId), msg)
s.wss.SetUserId(conn.Id(), msg.UserId)
sName := s.BindService().LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
// 网关不同,说明玩家在其它网关上登陆,
if sName != "" && sName != s.Name() {
s.SendServiceMsg(service.TopicEx(sName), conn, int32(pb.MsgId_RspUserLogoutId), &pb.RspUserLogout{Code: pb.ErrCode_LoginDiffLoc})
log.Debug(s.Log("玩家id:%v登陆成功连接:%v ", msg.UserId, conn.Id()))
if oldConn, ok := s.wss.FindConnByUserId(msg.UserId); ok {
log.Debug(s.Log("通知本网关下的旧玩家id:%v下线连接:%v 当前连接:%v", oldConn.UserId(), oldConn.Id(), conn.Id()))
s.SendClientMsg(oldConn, iMsg.ServiceName, int32(pb.MsgId_RspUserLogoutId), &pb.RspUserLogout{Code: pb.ErrCode_LoginDiffLoc})
s.wss.SetUserId(oldConn.Id(), 0)
// 登出的清理工作由WsOnDisconnect实现
s.Timer.NewTimer(time.Second, func() {
oldConn.Close()
}, false)
}
//log.Debug(s.Log("连接:%v 设置玩家id:%v", conn.Id(), msg.UserId))
s.wss.SetUserId(conn.Id(), msg.UserId)
s.SendClientMsg(conn, iMsg.ServiceName, int32(pb.MsgId_RspUserLoginId), msg)
//sName := s.BindService().LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
//// 网关不同,说明玩家在其它网关上登陆,
//if sName != "" && sName != s.Name() {
// log.Debug(s.Log("通知其它网关:%v下的旧玩家id:%v下线", sName, conn.UserId()))
// s.SendServiceMsg(service.TopicEx(sName), conn, int32(pb.MsgId_RspUserLogoutId), &pb.RspUserLogout{Code: pb.ErrCode_LoginDiffLoc})
//}
//log.Debug(s.Log("玩家:%v 绑定网关:%v", conn.UserId(), s.Name()))
s.BindService().SaveUserService(msg.UserId, pb.ServiceTypeId_STI_Gate, s.Name())
// 广播玩家上线
s.SendServiceMsg(topicName.UserOnline, conn, int32(pb.MsgId_NtfUserOnlineId), &pb.NtfUserOnline{UserId: msg.UserId})
}
// 收到登出消息
// 收到登出消息网关不会主动发登出消息异地登陆由online广播中检查自己
func (s *GateService) onUserLogout(iMsg *ipb.InternalMsg, conn ws.IConn, msg *pb.RspUserLogout) {
if conn == nil {
if conn == nil || reflect.ValueOf(conn).IsNil() {
return
}
s.SendClientMsg(conn, iMsg.ServiceName, int32(pb.MsgId_RspUserLogoutId), msg)
// 登出的清理工作由WsOnDisconnect实现
conn.Close()
s.Timer.NewTimer(time.Second, func() {
conn.Close()
}, false)
}
// 收到玩家上线广播
func (s *GateService) onUserOnline(iMsg *ipb.InternalMsg, conn ws.IConn, msg *pb.NtfUserOnline) {
//log.DebugF(s.Log("收到玩家:%v上线广播消息", msg.UserId))
if conn == nil || reflect.ValueOf(conn).IsNil() {
log.Error(s.Log("连接不存在,玩家:%v", msg.UserId))
return
}
sName := s.BindService().LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
//log.Debug(s.Log("玩家:%v 当前网关:%v", msg.UserId, sName))
// 网关不同,说明玩家在其它网关上登陆,
if sName != "" && sName != s.Name() {
log.Debug(s.Log("通知本网关:%v下的旧玩家id:%v下线", s.Name(), conn.UserId()))
s.SendClientMsg(conn, iMsg.ServiceName, int32(pb.MsgId_RspUserLogoutId), &pb.RspUserLogout{Code: pb.ErrCode_LoginDiffLoc})
s.wss.SetUserId(conn.Id(), 0)
// 登出的清理工作由WsOnDisconnect实现
s.Timer.NewTimer(time.Second, func() {
conn.Close()
}, false)
}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/fox/fox/ws"
"github.com/golang/protobuf/proto"
"github.com/nats-io/nats.go"
"reflect"
)
var Gates []*GateService
@ -55,6 +56,7 @@ func newGateService(serviceId int) *GateService {
TypeId: int(pb.ServiceTypeId_STI_Gate),
Version: config.Cfg.BuildDate,
}, &config.Cfg.Redis)
_ = s.GameService.Subscribe(topicName.UserOnline)
addressPos := serviceId - config.Command.ServiceId
if len(config.GateCfg.Address) <= addressPos {
@ -98,6 +100,20 @@ func (s *GateService) CanStop() bool {
}
func (s *GateService) OnStop() {
s.wss.Rang(func(conn ws.IConn) bool {
if conn.UserId() > 0 {
sName := s.BindService().LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
// 相同网关则为正常下线删除redis信息然后向内网广播下线
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送顶号消息(processor中处理),并主动关闭连接,不广播下线消息
if sName == s.Name() {
log.Debug(s.Log("玩家:%v 解绑网关:%v", conn.UserId(), s.Name()))
s.BindService().DelUserService(conn.UserId(), pb.ServiceTypeId_STI_Gate)
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.MsgId_NtfUserOfflineId), &pb.NtfUserOffline{UserId: conn.UserId()})
}
}
return true
})
s.NatsService.OnStop()
log.Debug("OnStop")
}
@ -120,7 +136,7 @@ func (s *GateService) connMessage(conn ws.IConn, iMsg *ipb.InternalMsg) {
} else {
s.SendClientData(conn, iMsg.ServiceName, iMsg.MsgId, iMsg.Msg)
}
//log.Debug(s.Log("received service message:%v", iMsg.MsgId))
//log.Debug(s.Log("received service message:%v", pb.MsgId(iMsg.MsgId)))
}
// 处理其它服发送过来的消息。大部分是将消息转发给玩家
@ -133,8 +149,8 @@ func (s *GateService) OnMessage(data []byte) error {
}
// conn不能为空全服广播消息走WorldMessage
var conn = s.findConn(iMsg)
if conn == nil {
log.WarnF(s.Log("client not exist.msg:%v", iMsg.MsgId))
if conn == nil || reflect.ValueOf(conn).IsNil() {
//log.Error(s.Log("玩家:%v 连接:%v 不存在.msg:%v", iMsg.UserId, iMsg.ConnId, iMsg.MsgId))
return nil
}
s.connMessage(conn, iMsg)
@ -168,6 +184,11 @@ func (s *GateService) WsOnMessage(conn ws.IConn, data []byte) {
_ = proto.Unmarshal(msg.Data, req)
req.Ip = conn.Addr()
msg.Data, _ = proto.Marshal(req)
} else {
if conn.UserId() == 0 {
log.Error(s.Log("玩家uid不能为0,连接:%v", conn.Id()))
return
}
}
s.SendServiceData(topic, conn, msg.MsgId, msg.Data)
} else {
@ -184,7 +205,7 @@ func (s *GateService) SendServiceData(topic string, conn ws.IConn, msgId int32,
// 向内部服务发送消息
func (s *GateService) SendServiceMsg(topic string, conn ws.IConn, msgId int32, msg proto.Message) {
log.DebugF("user:%v send to service:%v msg id:%v, msg:%v", conn.UserId(), topic, pb.MsgId(msgId), msg.String())
log.Debug(s.Log("user:%v send to service:%v msg id:%v, msg:%v", conn.UserId(), topic, pb.MsgId(msgId), msg.String()))
data, _ := proto.Marshal(msg)
s.SendServiceData(topic, conn, msgId, data)
}
@ -198,7 +219,7 @@ func (s *GateService) SendClientData(conn ws.IConn, serviceName string, msgId in
// 向玩家发送消息
func (s *GateService) SendClientMsg(conn ws.IConn, serviceName string, msgId int32, msg proto.Message) {
log.DebugF("send to user:%v msg id:%v, msg:%v", conn.UserId(), pb.MsgId(msgId), msg.String())
log.Debug(s.Log("send to user:%v msg id:%v, msg:%v", conn.UserId(), pb.MsgId(msgId), msg.String()))
data, _ := proto.Marshal(msg)
s.SendClientData(conn, serviceName, msgId, data)
}
@ -209,6 +230,7 @@ func (s *GateService) WsOnDisconnect(conn ws.IConn) {
// 相同网关则为正常下线删除redis信息然后向内网广播下线
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送顶号消息(processor中处理),并主动关闭连接,不广播下线消息
if sName == s.Name() {
log.Debug(s.Log("玩家:%v 解绑网关:%v", conn.UserId(), s.Name()))
s.BindService().DelUserService(conn.UserId(), pb.ServiceTypeId_STI_Gate)
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.MsgId_NtfUserOfflineId), &pb.NtfUserOffline{UserId: conn.UserId()})
}