实现跨服加入世界&玩家跨服在线迁移功能(部分完成)

This commit is contained in:
flswld
2022-12-25 20:09:19 +08:00
parent 9feeb4eafa
commit c7ba154ab4
15 changed files with 437 additions and 136 deletions

View File

@@ -153,28 +153,33 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session)
// 从GS接收消息
func (k *KcpConnectManager) sendMsgHandle() {
logger.Debug("send msg handle start")
kcpRawSendChanMap := make(map[uint64]chan *ProtoMsg)
convSessionMap := make(map[uint64]*Session)
userIdConvMap := make(map[uint32]uint64)
sendToClientFn := func(protoMsg *ProtoMsg) {
// 分发到每个连接具体的发送协程
kcpRawSendChan := kcpRawSendChanMap[protoMsg.ConvId]
if kcpRawSendChan != nil {
select {
case kcpRawSendChan <- protoMsg:
default:
logger.Error("kcpRawSendChan is full, convId: %v", protoMsg.ConvId)
}
} else {
logger.Error("kcpRawSendChan is nil, convId: %v", protoMsg.ConvId)
session := convSessionMap[protoMsg.ConvId]
if session == nil {
logger.Error("session is nil, convId: %v", protoMsg.ConvId)
return
}
kcpRawSendChan := session.kcpRawSendChan
if kcpRawSendChan == nil {
logger.Error("kcpRawSendChan is nil, session: %v", session)
return
}
select {
case kcpRawSendChan <- protoMsg:
default:
logger.Error("kcpRawSendChan is full, session: %v", session)
}
}
for {
select {
case session := <-k.createSessionChan:
kcpRawSendChanMap[session.conn.GetConv()] = session.kcpRawSendChan
convSessionMap[session.conn.GetConv()] = session
userIdConvMap[session.userId] = session.conn.GetConv()
case session := <-k.destroySessionChan:
delete(kcpRawSendChanMap, session.conn.GetConv())
delete(convSessionMap, session.conn.GetConv())
delete(userIdConvMap, session.userId)
close(session.kcpRawSendChan)
case protoMsg := <-k.localMsgOutput:
@@ -182,36 +187,65 @@ func (k *KcpConnectManager) sendMsgHandle() {
case netMsg := <-k.messageQueue.GetNetMsg():
switch netMsg.MsgType {
case mq.MsgTypeGame:
if netMsg.EventId != mq.NormalMsg {
logger.Error("recv unknown event from game server, event id: %v", netMsg.EventId)
continue
}
gameMsg := netMsg.GameMsg
convId, exist := userIdConvMap[gameMsg.UserId]
if !exist {
logger.Error("can not find convId by userId")
continue
switch netMsg.EventId {
case mq.NormalMsg:
convId, exist := userIdConvMap[gameMsg.UserId]
if !exist {
logger.Error("can not find convId by userId")
continue
}
protoMsg := new(ProtoMsg)
protoMsg.ConvId = convId
protoMsg.CmdId = gameMsg.CmdId
protoMsg.HeadMessage = k.getHeadMsg(gameMsg.ClientSeq)
protoMsg.PayloadMessage = gameMsg.PayloadMessage
sendToClientFn(protoMsg)
}
protoMsg := new(ProtoMsg)
protoMsg.ConvId = convId
protoMsg.CmdId = gameMsg.CmdId
protoMsg.HeadMessage = k.getHeadMsg(gameMsg.ClientSeq)
protoMsg.PayloadMessage = gameMsg.PayloadMessage
sendToClientFn(protoMsg)
case mq.MsgTypeConnCtrl:
if netMsg.EventId != mq.KickPlayerNotify {
continue
}
connCtrlMsg := netMsg.ConnCtrlMsg
convId, exist := userIdConvMap[connCtrlMsg.KickUserId]
if !exist {
logger.Error("can not find convId by userId")
continue
switch netMsg.EventId {
case mq.KickPlayerNotify:
convId, exist := userIdConvMap[connCtrlMsg.KickUserId]
if !exist {
logger.Error("can not find convId by userId")
continue
}
k.kcpEventInput <- &KcpEvent{
ConvId: convId,
EventId: KcpConnForceClose,
EventMessage: connCtrlMsg.KickReason,
}
}
k.kcpEventInput <- &KcpEvent{
ConvId: convId,
EventId: KcpConnForceClose,
EventMessage: connCtrlMsg.KickReason,
case mq.MsgTypeServer:
serverMsg := netMsg.ServerMsg
switch netMsg.EventId {
case mq.ServerUserGsChangeNotify:
convId, exist := userIdConvMap[serverMsg.UserId]
if !exist {
logger.Error("can not find convId by userId")
continue
}
session := convSessionMap[convId]
if session == nil {
logger.Error("session is nil, convId: %v", convId)
return
}
session.gsServerAppId = serverMsg.GameServerAppId
session.fightServerAppId = ""
session.changeGameServer = true
session.joinHostUserId = serverMsg.JoinHostUserId
// 网关代发登录请求到新的GS
gameMsg := new(mq.GameMsg)
gameMsg.UserId = serverMsg.UserId
gameMsg.CmdId = cmd.PlayerLoginReq
gameMsg.ClientSeq = 0
gameMsg.PayloadMessage = new(proto.PlayerLoginReq)
k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg,
GameMsg: gameMsg,
})
}
}
}

View File

@@ -117,13 +117,18 @@ func (k *KcpConnectManager) acceptHandle(listener *kcp.Listener) {
logger.Debug("client connect, convId: %v", convId)
kcpRawSendChan := make(chan *ProtoMsg, 1000)
session := &Session{
conn: conn,
connState: ConnEst,
userId: 0,
kcpRawSendChan: kcpRawSendChan,
seed: 0,
xorKey: k.dispatchKey,
changeXorKeyFin: false,
conn: conn,
connState: ConnEst,
userId: 0,
kcpRawSendChan: kcpRawSendChan,
seed: 0,
xorKey: k.dispatchKey,
changeXorKeyFin: false,
gsServerAppId: "",
fightServerAppId: "",
pathfindingServerAppId: "",
changeGameServer: false,
joinHostUserId: 0,
}
go k.recvHandle(session)
go k.sendHandle(session)
@@ -221,6 +226,8 @@ type Session struct {
gsServerAppId string
fightServerAppId string
pathfindingServerAppId string
changeGameServer bool
joinHostUserId uint32
}
// 接收
@@ -301,14 +308,20 @@ func (k *KcpConnectManager) sendHandle(session *Session) {
if protoMsg.CmdId == cmd.PlayerLoginRsp {
logger.Debug("session active, convId: %v", convId)
session.connState = ConnActive
// 通知GS玩家战斗服务器的appid
connCtrlMsg := new(mq.ConnCtrlMsg)
connCtrlMsg.UserId = session.userId
connCtrlMsg.FightServerAppId = session.fightServerAppId
// 通知GS玩家各个服务器的appid
serverMsg := new(mq.ServerMsg)
serverMsg.UserId = session.userId
if session.changeGameServer {
serverMsg.JoinHostUserId = session.joinHostUserId
session.changeGameServer = false
session.joinHostUserId = 0
} else {
serverMsg.FightServerAppId = session.fightServerAppId
}
k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl,
EventId: mq.FightServerSelectNotify,
ConnCtrlMsg: connCtrlMsg,
MsgType: mq.MsgTypeServer,
EventId: mq.ServerAppidBindNotify,
ServerMsg: serverMsg,
})
}
}