修改bug

This commit is contained in:
liuxiaobo 2025-06-17 12:48:14 +08:00
parent e7cb90ed63
commit a023c28dc8
12 changed files with 65 additions and 67 deletions

View File

@ -159,7 +159,7 @@ func (r *BaseRoom[Seat]) SendMsg(user IPlayer, msgId pb.MsgId, msg proto.Message
user.Robot().OnMessage(msgId, msg) user.Robot().OnMessage(msgId, msg)
} else { } else {
iMsg := ipb.MakeMsgEx(r.srv.Name(), 0, user.Id(), int32(msgId), msg) iMsg := ipb.MakeMsgEx(r.srv.Name(), 0, user.Id(), int32(msgId), msg)
_ = r.srv.SendByTopic(user.GateTopicName(), iMsg) _ = r.srv.SendByServiceId(int(pb.ServiceTypeId_STI_Gate), iMsg)
} }
} }

View File

@ -114,7 +114,7 @@ func (r *HundredRoom) SendMsg(user IPlayer, msgId pb.MsgId, msg proto.Message) {
user.Robot().OnMessage(msgId, msg) user.Robot().OnMessage(msgId, msg)
} else { } else {
iMsg := ipb.MakeMsgEx(r.room.srv.Name(), 0, user.Id(), int32(msgId), msg) iMsg := ipb.MakeMsgEx(r.room.srv.Name(), 0, user.Id(), int32(msgId), msg)
_ = r.room.srv.SendByTopic(user.GateTopicName(), iMsg) _ = r.room.srv.SendByServiceId(int(pb.ServiceTypeId_STI_Gate), iMsg)
} }
} }

View File

@ -31,7 +31,6 @@ type IPlayer interface {
Id() int64 Id() int64
Robot() IRobot Robot() IRobot
IsRobot() bool IsRobot() bool
GateTopicName() string
RoomId() int RoomId() int
} }

View File

@ -10,7 +10,6 @@ import (
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/fox/fox/xrand" "github.com/fox/fox/xrand"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"time"
) )
const ( const (
@ -45,7 +44,7 @@ func NewUserBindService(rdb *redis.Client, etcdRegistry *etcd.Registry[etcd.Serv
} }
func (m *UserBindService) makeRedisKey(userId int64) string { func (m *UserBindService) makeRedisKey(userId int64) string {
return fmt.Sprintf("%s:%s", prefix, userId) return fmt.Sprintf("%s:%d", prefix, userId)
} }
func (m *UserBindService) makeRedisSubKey(typeId pb.ServiceTypeId) string { func (m *UserBindService) makeRedisSubKey(typeId pb.ServiceTypeId) string {
return typeId.String() return typeId.String()
@ -76,7 +75,7 @@ func (m *UserBindService) DelUserService(userId int64, typeId pb.ServiceTypeId)
func (m *UserBindService) SaveUserService(userId int64, typeId pb.ServiceTypeId, serviceName string) { func (m *UserBindService) SaveUserService(userId int64, typeId pb.ServiceTypeId, serviceName string) {
key := m.makeRedisKey(userId) key := m.makeRedisKey(userId)
subKey := m.makeRedisSubKey(typeId) subKey := m.makeRedisSubKey(typeId)
m.rdb.HSet(context.Background(), key, subKey, serviceName, 2*24*time.Hour) m.rdb.HSet(context.Background(), key, subKey, serviceName)
} }
// 从etcd中检查节点是否有效如果有game1(旧服),game2(新服),都算有效,但是旧服会拒绝新玩家进入, // 从etcd中检查节点是否有效如果有game1(旧服),game2(新服),都算有效,但是旧服会拒绝新玩家进入,
@ -84,49 +83,53 @@ func (m *UserBindService) SaveUserService(userId int64, typeId pb.ServiceTypeId,
func (m *UserBindService) findServiceNodeByServiceName(serviceName string) (*etcd.ServiceNode, bool) { func (m *UserBindService) findServiceNodeByServiceName(serviceName string) (*etcd.ServiceNode, bool) {
var sNode *etcd.ServiceNode var sNode *etcd.ServiceNode
valid := false valid := false
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool { m.etcdRegistry.RangeNode(func(_ string, node *etcd.ServiceNode) bool {
if node, ok := v.(etcd.ServiceNode); ok {
if node.Name == serviceName { if node.Name == serviceName {
valid = true valid = true
sNode = &node sNode = node
return false return false
} }
}
return true return true
}) })
return sNode, valid return sNode, valid
} }
func (m *UserBindService) stringAllServiceNode() string { func (m *UserBindService) stringAllServiceNode() string {
var nodes []any var nodes []*etcd.ServiceNode
m.etcdRegistry.GetNodes().Range(func(_, value any) bool { m.etcdRegistry.RangeNode(func(_ string, node *etcd.ServiceNode) bool {
nodes = append(nodes, value) nodes = append(nodes, node)
return true return true
}) })
return utils.JsonMarshal(nodes) return utils.JsonMarshal(nodes)
} }
// 从etcd中找可用服务节点随机选择一个 // 获取最新的节点
func (m *UserBindService) randServiceNode(typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) { func (m *UserBindService) getLatestServiceNode(typeId pb.ServiceTypeId) []etcd.ServiceNode {
var nodes []etcd.ServiceNode var nodes []etcd.ServiceNode
var version string var version string
m.etcdRegistry.GetNodes().Range(func(_, value any) bool { // 查找最新版本号
node, ok := value.(etcd.ServiceNode) m.etcdRegistry.RangeNode(func(_ string, node *etcd.ServiceNode) bool {
if ok && node.TypeId == int(typeId) { if node.TypeId == int(typeId) {
if version < node.Version { if version < node.Version {
version = node.Version version = node.Version
} }
} }
return true return true
}) })
m.etcdRegistry.GetNodes().Range(func(_, value any) bool { m.etcdRegistry.RangeNode(func(_ string, node *etcd.ServiceNode) bool {
if node, ok := value.(etcd.ServiceNode); ok && node.TypeId == int(typeId) { if node.TypeId == int(typeId) {
if version == node.Version { if version == node.Version {
nodes = append(nodes, node) nodes = append(nodes, *node)
} }
} }
return true return true
}) })
return nodes
}
// 从etcd中找可用服务节点随机选择一个
func (m *UserBindService) randServiceNode(typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) {
var nodes = m.getLatestServiceNode(typeId)
if len(nodes) == 0 { if len(nodes) == 0 {
return nil, fmt.Errorf("not found service node.type id:%v. all node:%v", typeId, m.stringAllServiceNode()) return nil, fmt.Errorf("not found service node.type id:%v. all node:%v", typeId, m.stringAllServiceNode())
} }
@ -137,25 +140,7 @@ func (m *UserBindService) randServiceNode(typeId pb.ServiceTypeId) (*etcd.Servic
// 从etcd中hash一个服务节点。不需要保存玩家在哪个服务。 // 从etcd中hash一个服务节点。不需要保存玩家在哪个服务。
// 该服务是类似于db服这种有序操作的hash服 // 该服务是类似于db服这种有序操作的hash服
func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*etcd.ServiceNode, error) { func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*etcd.ServiceNode, error) {
var nodes []etcd.ServiceNode var nodes = m.getLatestServiceNode(typeId)
var version string
m.etcdRegistry.GetNodes().Range(func(_, value any) bool {
node, ok := value.(etcd.ServiceNode)
if ok && node.TypeId == int(typeId) {
if version < node.Version {
version = node.Version
}
}
return true
})
m.etcdRegistry.GetNodes().Range(func(_, value any) bool {
if node, ok := value.(etcd.ServiceNode); ok && node.TypeId == int(typeId) {
if version == node.Version {
nodes = append(nodes, node)
}
}
return true
})
if len(nodes) == 0 { if len(nodes) == 0 {
return nil, fmt.Errorf("not found service node.type id:%v. all node:%v", typeId, m.stringAllServiceNode()) return nil, fmt.Errorf("not found service node.type id:%v. all node:%v", typeId, m.stringAllServiceNode())
} }
@ -184,7 +169,9 @@ func (m *UserBindService) FindServiceNode(typeId pb.ServiceTypeId, userId int64)
return nil, err return nil, err
} }
// log.DebugF("etcd中随机一个服务节点:%s", node.Name) // log.DebugF("etcd中随机一个服务节点:%s", node.Name)
m.rdb.HSet(context.Background(), m.makeRedisKey(userId), node.Name, 2*24*time.Hour) if m.CheckServiceNodeStateType(typeId) == etcd.SNST_Stateful {
m.SaveUserService(userId, typeId, node.Name)
}
return node, nil return node, nil
} }
@ -196,14 +183,12 @@ func (m *UserBindService) RangeUserAllServiceNode(userId int64, proc func(node *
return return
} }
if len(maps) > 0 { if len(maps) > 0 {
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool { m.etcdRegistry.RangeNode(func(_ string, node *etcd.ServiceNode) bool {
if node, ok := v.(etcd.ServiceNode); ok { if _, ok := maps[node.Name]; ok {
if _, ok = maps[node.Name]; ok { if !proc(node) {
if !proc(&node) {
return false return false
} }
} }
}
return true return true
}) })
} }

View File

@ -3,6 +3,7 @@ package room
import ( import (
"game/common/proto/pb" "game/common/proto/pb"
"github.com/fox/fox/ipb" "github.com/fox/fox/ipb"
"github.com/fox/fox/log"
) )
func (rm *ColorRoom) checkEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqEnterRoom) pb.ErrCode { func (rm *ColorRoom) checkEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqEnterRoom) pb.ErrCode {
@ -28,6 +29,7 @@ func (rm *ColorRoom) enterRoom(user *ColorPlayer) {
user.resetData() user.resetData()
} }
rm.notifyColorRoomInfo(user) rm.notifyColorRoomInfo(user)
log.Debug(rm.Log("玩家:%v进入房间", user.ID))
} }
func (rm *ColorRoom) onEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqEnterRoom) { func (rm *ColorRoom) onEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqEnterRoom) {
@ -43,19 +45,20 @@ func (rm *ColorRoom) onEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *
func (rm *ColorRoom) checkLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) pb.ErrCode { func (rm *ColorRoom) checkLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) pb.ErrCode {
_ = iMsg _ = iMsg
_ = req _ = req
if user.totalBet == 0 {
return pb.ErrCode_OK
}
if rm.status >= pb.ColorGameStatus_CGS_Settle || rm.status < pb.ColorGameStatus_CGS_Betting { if rm.status >= pb.ColorGameStatus_CGS_Settle || rm.status < pb.ColorGameStatus_CGS_Betting {
return pb.ErrCode_OK return pb.ErrCode_OK
} }
if user.totalBet == 0 {
return pb.ErrCode_NotLeaveRoom return pb.ErrCode_NotLeaveRoom
}
return pb.ErrCode_OK
} }
func (rm *ColorRoom) leaveRoom(user *ColorPlayer) { func (rm *ColorRoom) leaveRoom(user *ColorPlayer) {
rm.DelPlayer(user.Id()) rm.DelPlayer(user.Id())
rm.userMgr.Del(user.ID) rm.userMgr.Del(user.ID)
rm.bindService.DelUserService(user.ID, pb.ServiceTypeId_STI_ColorGame) rm.bindService.DelUserService(user.ID, pb.ServiceTypeId_STI_ColorGame)
log.Debug(rm.Log("玩家:%v离开房间", user.ID))
} }
func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) { func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) {
@ -63,9 +66,15 @@ func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *
rm.SendMsg(user, pb.MsgId_RspEnterRoomId, &pb.RspEnterRoom{Code: code}) rm.SendMsg(user, pb.MsgId_RspEnterRoomId, &pb.RspEnterRoom{Code: code})
if code == pb.ErrCode_OK { if code == pb.ErrCode_OK {
rm.leaveRoom(user) rm.leaveRoom(user)
return
} }
return }
func (rm *ColorRoom) onUserOffline(user *ColorPlayer, iMsg *ipb.InternalMsg, ntf *pb.NtfUserOffline) {
_ = ntf
code := rm.checkLeaveRoom(user, iMsg, &pb.ReqLeaveRoom{})
if code == pb.ErrCode_OK {
rm.leaveRoom(user)
}
} }
func (rm *ColorRoom) checkBet(user *ColorPlayer, _ *ipb.InternalMsg, req *pb.ReqColorBetting) pb.ErrCode { func (rm *ColorRoom) checkBet(user *ColorPlayer, _ *ipb.InternalMsg, req *pb.ReqColorBetting) pb.ErrCode {

View File

@ -9,7 +9,6 @@ import (
type ColorPlayer struct { type ColorPlayer struct {
*user.User *user.User
*user.UserResources *user.UserResources
gateTopicName string
roomId int roomId int
notBetCount int // 不投注局数 notBetCount int // 不投注局数
@ -18,11 +17,10 @@ type ColorPlayer struct {
settleMsg *pb.NtfColorSettle // 本局结算消息 settleMsg *pb.NtfColorSettle // 本局结算消息
} }
func NewColorPlayer(gateTopicName string, roomId int, u *user.User, res *user.UserResources) *ColorPlayer { func NewColorPlayer(roomId int, u *user.User, res *user.UserResources) *ColorPlayer {
return &ColorPlayer{ return &ColorPlayer{
User: u, User: u,
UserResources: res, UserResources: res,
gateTopicName: gateTopicName,
roomId: roomId, roomId: roomId,
} }
} }
@ -39,10 +37,6 @@ func (p *ColorPlayer) IsRobot() bool {
return false return false
} }
func (p *ColorPlayer) GateTopicName() string {
return p.gateTopicName
}
func (p *ColorPlayer) RoomId() int { func (p *ColorPlayer) RoomId() int {
return p.roomId return p.roomId
} }

View File

@ -73,6 +73,7 @@ func (rm *ColorRoom) OnInit() {
pb.MsgId_ReqColorBettingId: {pb.ReqColorBetting{}, rm.onBet}, pb.MsgId_ReqColorBettingId: {pb.ReqColorBetting{}, rm.onBet},
pb.MsgId_ReqEnterRoomId: {pb.ReqEnterRoom{}, rm.onEnterRoom}, pb.MsgId_ReqEnterRoomId: {pb.ReqEnterRoom{}, rm.onEnterRoom},
pb.MsgId_ReqLeaveRoomId: {pb.ReqLeaveRoom{}, rm.onLeaveRoom}, pb.MsgId_ReqLeaveRoomId: {pb.ReqLeaveRoom{}, rm.onLeaveRoom},
pb.MsgId_NtfUserOfflineId: {pb.NtfUserOffline{}, rm.onUserOffline},
}) })
rm.RegisterTimerMessages(processor.RegisterTimerMetas{ rm.RegisterTimerMessages(processor.RegisterTimerMetas{
TtGameStart: rm.gameStart, TtGameStart: rm.gameStart,

View File

@ -7,7 +7,6 @@ import (
"github.com/fox/fox/ipb" "github.com/fox/fox/ipb"
"github.com/fox/fox/ksync" "github.com/fox/fox/ksync"
"github.com/fox/fox/processor" "github.com/fox/fox/processor"
"github.com/fox/fox/service"
) )
const ( const (
@ -31,7 +30,7 @@ func (s *ColorService) onEnterRoom(iMsg *ipb.InternalMsg, req *pb.ReqEnterRoom)
} }
// 切回服务协程处理业务逻辑 // 切回服务协程处理业务逻辑
s.RunOnce(func() { s.RunOnce(func() {
colorUser := room.NewColorPlayer(service.TopicEx(iMsg.ServiceName), s.room.Id(), &us.User, &us.UserResources) colorUser := room.NewColorPlayer(s.room.Id(), &us.User, &us.UserResources)
s.playerMgr.Add(colorUser) s.playerMgr.Add(colorUser)
_ = s.room.Dispatch(colorUser, iMsg.MsgId, iMsg, req) _ = s.room.Dispatch(colorUser, iMsg.MsgId, iMsg, req)
}) })

View File

@ -6,6 +6,7 @@ import (
"game/common/gameService" "game/common/gameService"
"game/common/proto/pb" "game/common/proto/pb"
"game/common/serviceName" "game/common/serviceName"
"game/common/topicName"
"game/server/colorgame/config" "game/server/colorgame/config"
"game/server/colorgame/room" "game/server/colorgame/room"
"github.com/fox/fox/ipb" "github.com/fox/fox/ipb"
@ -59,6 +60,7 @@ func newColorService(serviceId int) service.IService {
TypeId: int(pb.ServiceTypeId_STI_ColorGame), TypeId: int(pb.ServiceTypeId_STI_ColorGame),
Version: config.Cfg.BuildDate, Version: config.Cfg.BuildDate,
}, &config.Cfg.Redis) }, &config.Cfg.Redis)
_ = s.GameService.Subscribe(topicName.UserOffline)
s.initProcessor() s.initProcessor()
s.playerMgr = baseroom.NewPlayerMgr(nil) s.playerMgr = baseroom.NewPlayerMgr(nil)

View File

@ -58,3 +58,9 @@ func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom)
s.SendServiceMsg(pb.ServiceTypeId_STI_Gate, iMsg.UserId, int32(pb.MsgId_RspMatchRoomId), rsp) s.SendServiceMsg(pb.ServiceTypeId_STI_Gate, iMsg.UserId, int32(pb.MsgId_RspMatchRoomId), rsp)
}, nil) }, nil)
} }
// 匹配房间
func (s *MatchService) onUserOffline(iMsg *ipb.InternalMsg, ntf *pb.NtfUserOffline) {
_ = iMsg
log.DebugF(s.Log("收到玩家下线消息:%v从匹配队列中移除该玩家", ntf.UserId))
}

View File

@ -12,5 +12,6 @@ const (
func (s *MatchService) initProcessor() { func (s *MatchService) initProcessor() {
s.Processor().RegisterMessages(processor.RegisterMetas{ s.Processor().RegisterMessages(processor.RegisterMetas{
pb.MsgId_ReqMatchRoomId: {pb.ReqMatchRoom{}, s.onMatchRoom}, pb.MsgId_ReqMatchRoomId: {pb.ReqMatchRoom{}, s.onMatchRoom},
pb.MsgId_NtfUserOfflineId: {pb.NtfUserOffline{}, s.onUserOffline},
}) })
} }

View File

@ -5,6 +5,7 @@ import (
"game/common/gameService" "game/common/gameService"
"game/common/proto/pb" "game/common/proto/pb"
"game/common/serviceName" "game/common/serviceName"
"game/common/topicName"
"game/server/match/config" "game/server/match/config"
"game/server/match/match" "game/server/match/match"
"github.com/fox/fox/ipb" "github.com/fox/fox/ipb"
@ -56,6 +57,7 @@ func newService(serviceId int) *MatchService {
TypeId: int(pb.ServiceTypeId_STI_Match), TypeId: int(pb.ServiceTypeId_STI_Match),
Version: config.Cfg.BuildDate, Version: config.Cfg.BuildDate,
}, &config.Cfg.Redis) }, &config.Cfg.Redis)
_ = s.GameService.Subscribe(topicName.UserOffline)
s.initProcessor() s.initProcessor()
s.OnInit() s.OnInit()