添加lobby服
This commit is contained in:
parent
e44d0a510e
commit
15a4b8256a
@ -25,7 +25,7 @@ const (
|
||||
type BaseRoom[Seat ISeat] struct {
|
||||
id int
|
||||
roomType int // 房间配置id 初级,中级,高级
|
||||
playType int // 玩法配置id color玩法id
|
||||
gameId int // 玩法配置id color玩法id
|
||||
gameNo string
|
||||
seats []Seat
|
||||
processor *processor.Processor
|
||||
@ -35,11 +35,11 @@ type BaseRoom[Seat ISeat] struct {
|
||||
srv service.IService
|
||||
}
|
||||
|
||||
func NewBaseRoom[Seat ISeat](id, roomType, playType, seatNum int, srv service.IService) (*BaseRoom[Seat], pb.ErrCode) {
|
||||
func NewBaseRoom[Seat ISeat](id, roomType, gameId, seatNum int, srv service.IService) (*BaseRoom[Seat], pb.ErrCode) {
|
||||
room := &BaseRoom[Seat]{
|
||||
id: id,
|
||||
roomType: roomType,
|
||||
playType: playType,
|
||||
gameId: gameId,
|
||||
gameNo: "",
|
||||
seats: make([]Seat, seatNum),
|
||||
timeTypes: make(map[timer.ITimeType]uint32),
|
||||
@ -59,8 +59,8 @@ func (r *BaseRoom[Seat]) RoomType() int {
|
||||
return r.roomType
|
||||
}
|
||||
|
||||
func (r *BaseRoom[Seat]) PlayType() int {
|
||||
return r.playType
|
||||
func (r *BaseRoom[Seat]) GameId() int {
|
||||
return r.gameId
|
||||
}
|
||||
|
||||
// 入座玩家数量
|
||||
@ -257,10 +257,6 @@ func (r *BaseRoom[Seat]) RegisterMessages(metas processor.RegisterMetas) {
|
||||
r.processor.RegisterMessages(metas)
|
||||
}
|
||||
|
||||
func (r *BaseRoom[Seat]) TimerDispatch(cmd timer.ITimeType, params ...any) error {
|
||||
return r.timeProcessor.Dispatch(cmd, params...)
|
||||
}
|
||||
|
||||
// 注册时间事件及处理
|
||||
func (r *BaseRoom[Seat]) RegisterTimerMessages(metas processor.RegisterTimerMetas) {
|
||||
r.timeProcessor.RegisterMessages(metas)
|
||||
|
@ -18,8 +18,8 @@ type HundredRoom struct {
|
||||
users map[int64]IPlayer // 所有玩家
|
||||
}
|
||||
|
||||
func NewHundredRoom(id, roomType, playType int, srv service.IService) (*HundredRoom, pb.ErrCode) {
|
||||
baseRoom, code := NewBaseRoom[*BaseSeat](id, roomType, playType, 0, srv)
|
||||
func NewHundredRoom(id, roomType, gameId int, srv service.IService) (*HundredRoom, pb.ErrCode) {
|
||||
baseRoom, code := NewBaseRoom[*BaseSeat](id, roomType, gameId, 0, srv)
|
||||
if code != pb.ErrCode_OK {
|
||||
return nil, code
|
||||
}
|
||||
@ -37,8 +37,8 @@ func (r *HundredRoom) RoomType() int {
|
||||
return r.room.RoomType()
|
||||
}
|
||||
|
||||
func (r *HundredRoom) PlayType() int {
|
||||
return r.room.PlayType()
|
||||
func (r *HundredRoom) GameId() int {
|
||||
return r.room.GameId()
|
||||
}
|
||||
|
||||
// 房间玩家数量
|
||||
@ -169,10 +169,6 @@ func (r *HundredRoom) RegisterMessages(metas processor.RegisterMetas) {
|
||||
r.room.RegisterMessages(metas)
|
||||
}
|
||||
|
||||
func (r *HundredRoom) TimerDispatch(cmd timer.ITimeType, params ...any) error {
|
||||
return r.room.TimerDispatch(cmd, params...)
|
||||
}
|
||||
|
||||
// 注册时间事件及处理
|
||||
func (r *HundredRoom) RegisterTimerMessages(metas processor.RegisterTimerMetas) {
|
||||
r.room.RegisterTimerMessages(metas)
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
type IRoom interface {
|
||||
Id() int
|
||||
RoomType() int // 房间配置id
|
||||
PlayType() int
|
||||
GameId() int
|
||||
OnInit()
|
||||
// SeatPlayerNum() int
|
||||
// FindEmptySeat() bool
|
||||
|
@ -18,10 +18,10 @@ enum ChatType
|
||||
// 聊天消息
|
||||
message ReqChat
|
||||
{
|
||||
ChatUser src_user = 1; // 说话的人
|
||||
ChatUser dst_user = 2; // 接收者
|
||||
ChatUser srcUser = 1; // 说话的人
|
||||
ChatUser dstUser = 2; // 接收者
|
||||
ChatType type = 3; // 聊天类型
|
||||
ServiceTypeId game_id = 4; // 游戏id,只在本玩法中显示的聊天信息
|
||||
ServiceTypeId gameId = 4; // 游戏id,只在本玩法中显示的聊天信息
|
||||
string content = 5; // 内容
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ message ReqEnterRoom
|
||||
message RspEnterRoom
|
||||
{
|
||||
ErrCode code = 1;
|
||||
int32 PlayType = 2; // 玩法id
|
||||
int32 RoomType = 3; // 房间类型,低级,中级,高级等
|
||||
int32 gameId = 2; // 玩法id
|
||||
int32 roomType = 3; // 房间类型,低级,中级,高级等
|
||||
}
|
||||
|
||||
// 玩家离开房间
|
||||
|
@ -27,6 +27,12 @@ message NtfUserOnline
|
||||
int64 user_id = 2; // 玩家id
|
||||
}
|
||||
|
||||
// 通知玩家在哪些服务里,方便玩家重进这些服务,重连使用
|
||||
message NtfUserInService
|
||||
{
|
||||
repeated string serviceNames = 3; // 玩家所在玩法的服务名
|
||||
}
|
||||
|
||||
// 玩家登陆
|
||||
message ReqUserLogout
|
||||
{
|
||||
|
@ -8,8 +8,8 @@ import "user.proto";
|
||||
// 房间匹配
|
||||
message ReqMatchRoom
|
||||
{
|
||||
int32 PlayType = 1; // 玩法id
|
||||
int32 RoomType = 2; // 房间类型,低级,中级,高级等
|
||||
int32 gameId = 1; // 玩法id
|
||||
int32 roomType = 2; // 房间类型,低级,中级,高级等
|
||||
}
|
||||
|
||||
// 玩家进房间返回 匹配服返回该消息,假房间。匹配成功后发给对应玩法服,玩法服发NotifyUserEnterRoom才是真房间
|
||||
@ -22,8 +22,8 @@ message RspMatchRoom
|
||||
}
|
||||
|
||||
ErrCode code = 1;
|
||||
int32 PlayType = 2; // 玩法id
|
||||
int32 RoomType = 3; // 房间类型,低级,中级,高级等
|
||||
int32 gameId = 2; // 玩法id
|
||||
int32 roomType = 3; // 房间类型,低级,中级,高级等
|
||||
GameUser User = 4; // 玩家数据
|
||||
|
||||
ColorInfo colorInfo = 20; // color玩法配置信息
|
||||
|
@ -27,6 +27,7 @@ enum MsgId
|
||||
ReqUserLoginId = 2100; // 玩家登陆
|
||||
RspUserLoginId = 2101;
|
||||
NtfUserOnlineId = 2102;
|
||||
NtfUserInServiceId = 2103; // 将玩家之前呆的服务同步给玩家,方便玩家重连进来
|
||||
ReqUserLogoutId = 2104;
|
||||
RspUserLogoutId = 2105;
|
||||
NtfUserOfflineId = 2106;
|
||||
|
@ -10,6 +10,7 @@ enum ServiceTypeId
|
||||
STI_Chat = 102; // 聊天服
|
||||
STI_DB = 103; // db服
|
||||
STI_Match = 104; // 匹配服
|
||||
STI_Lobby = 105; // 大厅服
|
||||
|
||||
STI_ColorGame = 120; // color game
|
||||
}
|
||||
|
@ -6,22 +6,22 @@ option go_package = "common/proto/pb";
|
||||
// 聊天中显示的玩家基础信息
|
||||
message ChatUser
|
||||
{
|
||||
int64 user_id = 1;
|
||||
int64 userId = 1;
|
||||
string nickname = 2; // 昵称
|
||||
string avatar = 3; // 头像
|
||||
string avatar_frame = 4; // 头像框
|
||||
string vip_level = 5; // vip等级
|
||||
string avatarFrame = 4; // 头像框
|
||||
string vipLevel = 5; // vip等级
|
||||
}
|
||||
|
||||
// 房间内的玩家数据
|
||||
message GameUser
|
||||
{
|
||||
int64 user_id = 1;
|
||||
int64 userId = 1;
|
||||
string nickname = 2; // 昵称
|
||||
string avatar = 3; // 头像
|
||||
string avatar_frame = 4; // 头像框
|
||||
int32 vip_level = 5; // vip等级
|
||||
int32 vip_exp = 6; // vip经验
|
||||
string avatarFrame = 4; // 头像框
|
||||
int32 vipLevel = 5; // vip等级
|
||||
int32 vipExp = 6; // vip经验
|
||||
int64 seat = 20; // 座位
|
||||
int64 gold = 25; // 金币
|
||||
}
|
||||
|
@ -77,10 +77,10 @@ func (ChatType) EnumDescriptor() ([]byte, []int) {
|
||||
// 聊天消息
|
||||
type ReqChat struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
SrcUser *ChatUser `protobuf:"bytes,1,opt,name=src_user,json=srcUser,proto3" json:"src_user,omitempty"` // 说话的人
|
||||
DstUser *ChatUser `protobuf:"bytes,2,opt,name=dst_user,json=dstUser,proto3" json:"dst_user,omitempty"` // 接收者
|
||||
SrcUser *ChatUser `protobuf:"bytes,1,opt,name=srcUser,proto3" json:"srcUser,omitempty"` // 说话的人
|
||||
DstUser *ChatUser `protobuf:"bytes,2,opt,name=dstUser,proto3" json:"dstUser,omitempty"` // 接收者
|
||||
Type ChatType `protobuf:"varint,3,opt,name=type,proto3,enum=pb.ChatType" json:"type,omitempty"` // 聊天类型
|
||||
GameId ServiceTypeId `protobuf:"varint,4,opt,name=game_id,json=gameId,proto3,enum=pb.ServiceTypeId" json:"game_id,omitempty"` // 游戏id,只在本玩法中显示的聊天信息
|
||||
GameId ServiceTypeId `protobuf:"varint,4,opt,name=gameId,proto3,enum=pb.ServiceTypeId" json:"gameId,omitempty"` // 游戏id,只在本玩法中显示的聊天信息
|
||||
Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` // 内容
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -157,12 +157,12 @@ const file_chat_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"chat.proto\x12\x02pb\x1a\n" +
|
||||
"user.proto\x1a\rservice.proto\"\xc3\x01\n" +
|
||||
"\aReqChat\x12'\n" +
|
||||
"\bsrc_user\x18\x01 \x01(\v2\f.pb.ChatUserR\asrcUser\x12'\n" +
|
||||
"\bdst_user\x18\x02 \x01(\v2\f.pb.ChatUserR\adstUser\x12 \n" +
|
||||
"\x04type\x18\x03 \x01(\x0e2\f.pb.ChatTypeR\x04type\x12*\n" +
|
||||
"\agame_id\x18\x04 \x01(\x0e2\x11.pb.ServiceTypeIdR\x06gameId\x12\x18\n" +
|
||||
"user.proto\x1a\rservice.proto\"\xc0\x01\n" +
|
||||
"\aReqChat\x12&\n" +
|
||||
"\asrcUser\x18\x01 \x01(\v2\f.pb.ChatUserR\asrcUser\x12&\n" +
|
||||
"\adstUser\x18\x02 \x01(\v2\f.pb.ChatUserR\adstUser\x12 \n" +
|
||||
"\x04type\x18\x03 \x01(\x0e2\f.pb.ChatTypeR\x04type\x12)\n" +
|
||||
"\x06gameId\x18\x04 \x01(\x0e2\x11.pb.ServiceTypeIdR\x06gameId\x12\x18\n" +
|
||||
"\acontent\x18\x05 \x01(\tR\acontent*H\n" +
|
||||
"\bChatType\x12\x0e\n" +
|
||||
"\n" +
|
||||
@ -194,10 +194,10 @@ var file_chat_proto_goTypes = []any{
|
||||
(ServiceTypeId)(0), // 3: pb.ServiceTypeId
|
||||
}
|
||||
var file_chat_proto_depIdxs = []int32{
|
||||
2, // 0: pb.ReqChat.src_user:type_name -> pb.ChatUser
|
||||
2, // 1: pb.ReqChat.dst_user:type_name -> pb.ChatUser
|
||||
2, // 0: pb.ReqChat.srcUser:type_name -> pb.ChatUser
|
||||
2, // 1: pb.ReqChat.dstUser:type_name -> pb.ChatUser
|
||||
0, // 2: pb.ReqChat.type:type_name -> pb.ChatType
|
||||
3, // 3: pb.ReqChat.game_id:type_name -> pb.ServiceTypeId
|
||||
3, // 3: pb.ReqChat.gameId:type_name -> pb.ServiceTypeId
|
||||
4, // [4:4] is the sub-list for method output_type
|
||||
4, // [4:4] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
|
@ -109,8 +109,8 @@ func (*ReqEnterRoom) Descriptor() ([]byte, []int) {
|
||||
type RspEnterRoom struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
|
||||
PlayType int32 `protobuf:"varint,2,opt,name=PlayType,proto3" json:"PlayType,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,3,opt,name=RoomType,proto3" json:"RoomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
GameId int32 `protobuf:"varint,2,opt,name=gameId,proto3" json:"gameId,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,3,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -152,9 +152,9 @@ func (x *RspEnterRoom) GetCode() ErrCode {
|
||||
return ErrCode_OK
|
||||
}
|
||||
|
||||
func (x *RspEnterRoom) GetPlayType() int32 {
|
||||
func (x *RspEnterRoom) GetGameId() int32 {
|
||||
if x != nil {
|
||||
return x.PlayType
|
||||
return x.GameId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -255,11 +255,11 @@ const file_common_proto_rawDesc = "" +
|
||||
"code.proto\"1\n" +
|
||||
"\x0eNtfKickOutUser\x12\x1f\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\"\x0e\n" +
|
||||
"\fReqEnterRoom\"g\n" +
|
||||
"\fReqEnterRoom\"c\n" +
|
||||
"\fRspEnterRoom\x12\x1f\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x1a\n" +
|
||||
"\bPlayType\x18\x02 \x01(\x05R\bPlayType\x12\x1a\n" +
|
||||
"\bRoomType\x18\x03 \x01(\x05R\bRoomType\"\x0e\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x16\n" +
|
||||
"\x06gameId\x18\x02 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||
"\broomType\x18\x03 \x01(\x05R\broomType\"\x0e\n" +
|
||||
"\fReqLeaveRoom\"/\n" +
|
||||
"\fRspLeaveRoom\x12\x1f\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04codeB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
|
@ -203,6 +203,51 @@ func (x *NtfUserOnline) GetUserId() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// 通知玩家在哪些服务里,方便玩家重进这些服务,重连使用
|
||||
type NtfUserInService struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ServiceNames []string `protobuf:"bytes,3,rep,name=serviceNames,proto3" json:"serviceNames,omitempty"` // 玩家所在玩法的服务名
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NtfUserInService) Reset() {
|
||||
*x = NtfUserInService{}
|
||||
mi := &file_login_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NtfUserInService) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NtfUserInService) ProtoMessage() {}
|
||||
|
||||
func (x *NtfUserInService) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_login_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NtfUserInService.ProtoReflect.Descriptor instead.
|
||||
func (*NtfUserInService) Descriptor() ([]byte, []int) {
|
||||
return file_login_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *NtfUserInService) GetServiceNames() []string {
|
||||
if x != nil {
|
||||
return x.ServiceNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 玩家登陆
|
||||
type ReqUserLogout struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@ -212,7 +257,7 @@ type ReqUserLogout struct {
|
||||
|
||||
func (x *ReqUserLogout) Reset() {
|
||||
*x = ReqUserLogout{}
|
||||
mi := &file_login_proto_msgTypes[3]
|
||||
mi := &file_login_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -224,7 +269,7 @@ func (x *ReqUserLogout) String() string {
|
||||
func (*ReqUserLogout) ProtoMessage() {}
|
||||
|
||||
func (x *ReqUserLogout) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_login_proto_msgTypes[3]
|
||||
mi := &file_login_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -237,7 +282,7 @@ func (x *ReqUserLogout) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ReqUserLogout.ProtoReflect.Descriptor instead.
|
||||
func (*ReqUserLogout) Descriptor() ([]byte, []int) {
|
||||
return file_login_proto_rawDescGZIP(), []int{3}
|
||||
return file_login_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
type RspUserLogout struct {
|
||||
@ -249,7 +294,7 @@ type RspUserLogout struct {
|
||||
|
||||
func (x *RspUserLogout) Reset() {
|
||||
*x = RspUserLogout{}
|
||||
mi := &file_login_proto_msgTypes[4]
|
||||
mi := &file_login_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -261,7 +306,7 @@ func (x *RspUserLogout) String() string {
|
||||
func (*RspUserLogout) ProtoMessage() {}
|
||||
|
||||
func (x *RspUserLogout) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_login_proto_msgTypes[4]
|
||||
mi := &file_login_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -274,7 +319,7 @@ func (x *RspUserLogout) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use RspUserLogout.ProtoReflect.Descriptor instead.
|
||||
func (*RspUserLogout) Descriptor() ([]byte, []int) {
|
||||
return file_login_proto_rawDescGZIP(), []int{4}
|
||||
return file_login_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *RspUserLogout) GetCode() ErrCode {
|
||||
@ -294,7 +339,7 @@ type NtfUserOffline struct {
|
||||
|
||||
func (x *NtfUserOffline) Reset() {
|
||||
*x = NtfUserOffline{}
|
||||
mi := &file_login_proto_msgTypes[5]
|
||||
mi := &file_login_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -306,7 +351,7 @@ func (x *NtfUserOffline) String() string {
|
||||
func (*NtfUserOffline) ProtoMessage() {}
|
||||
|
||||
func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_login_proto_msgTypes[5]
|
||||
mi := &file_login_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -319,7 +364,7 @@ func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use NtfUserOffline.ProtoReflect.Descriptor instead.
|
||||
func (*NtfUserOffline) Descriptor() ([]byte, []int) {
|
||||
return file_login_proto_rawDescGZIP(), []int{5}
|
||||
return file_login_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *NtfUserOffline) GetUserId() int64 {
|
||||
@ -347,7 +392,9 @@ const file_login_proto_rawDesc = "" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" +
|
||||
"\x05token\x18\x03 \x01(\tR\x05token\"(\n" +
|
||||
"\rNtfUserOnline\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\"\x0f\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\"6\n" +
|
||||
"\x10NtfUserInService\x12\"\n" +
|
||||
"\fserviceNames\x18\x03 \x03(\tR\fserviceNames\"\x0f\n" +
|
||||
"\rReqUserLogout\"0\n" +
|
||||
"\rRspUserLogout\x12\x1f\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\")\n" +
|
||||
@ -366,19 +413,20 @@ func file_login_proto_rawDescGZIP() []byte {
|
||||
return file_login_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_login_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_login_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_login_proto_goTypes = []any{
|
||||
(*ReqUserLogin)(nil), // 0: pb.ReqUserLogin
|
||||
(*RspUserLogin)(nil), // 1: pb.RspUserLogin
|
||||
(*NtfUserOnline)(nil), // 2: pb.NtfUserOnline
|
||||
(*ReqUserLogout)(nil), // 3: pb.ReqUserLogout
|
||||
(*RspUserLogout)(nil), // 4: pb.RspUserLogout
|
||||
(*NtfUserOffline)(nil), // 5: pb.NtfUserOffline
|
||||
(ErrCode)(0), // 6: pb.ErrCode
|
||||
(*NtfUserInService)(nil), // 3: pb.NtfUserInService
|
||||
(*ReqUserLogout)(nil), // 4: pb.ReqUserLogout
|
||||
(*RspUserLogout)(nil), // 5: pb.RspUserLogout
|
||||
(*NtfUserOffline)(nil), // 6: pb.NtfUserOffline
|
||||
(ErrCode)(0), // 7: pb.ErrCode
|
||||
}
|
||||
var file_login_proto_depIdxs = []int32{
|
||||
6, // 0: pb.RspUserLogin.code:type_name -> pb.ErrCode
|
||||
6, // 1: pb.RspUserLogout.code:type_name -> pb.ErrCode
|
||||
7, // 0: pb.RspUserLogin.code:type_name -> pb.ErrCode
|
||||
7, // 1: pb.RspUserLogout.code:type_name -> pb.ErrCode
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
@ -398,7 +446,7 @@ func file_login_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 6,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
@ -24,8 +24,8 @@ const (
|
||||
// 房间匹配
|
||||
type ReqMatchRoom struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PlayType int32 `protobuf:"varint,1,opt,name=PlayType,proto3" json:"PlayType,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,2,opt,name=RoomType,proto3" json:"RoomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
GameId int32 `protobuf:"varint,1,opt,name=gameId,proto3" json:"gameId,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,2,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -60,9 +60,9 @@ func (*ReqMatchRoom) Descriptor() ([]byte, []int) {
|
||||
return file_match_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ReqMatchRoom) GetPlayType() int32 {
|
||||
func (x *ReqMatchRoom) GetGameId() int32 {
|
||||
if x != nil {
|
||||
return x.PlayType
|
||||
return x.GameId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -78,8 +78,8 @@ func (x *ReqMatchRoom) GetRoomType() int32 {
|
||||
type RspMatchRoom struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
|
||||
PlayType int32 `protobuf:"varint,2,opt,name=PlayType,proto3" json:"PlayType,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,3,opt,name=RoomType,proto3" json:"RoomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
GameId int32 `protobuf:"varint,2,opt,name=gameId,proto3" json:"gameId,omitempty"` // 玩法id
|
||||
RoomType int32 `protobuf:"varint,3,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||
User *GameUser `protobuf:"bytes,4,opt,name=User,proto3" json:"User,omitempty"` // 玩家数据
|
||||
ColorInfo *RspMatchRoom_ColorInfo `protobuf:"bytes,20,opt,name=colorInfo,proto3" json:"colorInfo,omitempty"` // color玩法配置信息
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@ -123,9 +123,9 @@ func (x *RspMatchRoom) GetCode() ErrCode {
|
||||
return ErrCode_OK
|
||||
}
|
||||
|
||||
func (x *RspMatchRoom) GetPlayType() int32 {
|
||||
func (x *RspMatchRoom) GetGameId() int32 {
|
||||
if x != nil {
|
||||
return x.PlayType
|
||||
return x.GameId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -238,14 +238,14 @@ const file_match_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\vmatch.proto\x12\x02pb\x1a\n" +
|
||||
"code.proto\x1a\n" +
|
||||
"user.proto\"F\n" +
|
||||
"\fReqMatchRoom\x12\x1a\n" +
|
||||
"\bPlayType\x18\x01 \x01(\x05R\bPlayType\x12\x1a\n" +
|
||||
"\bRoomType\x18\x02 \x01(\x05R\bRoomType\"\xd0\x01\n" +
|
||||
"user.proto\"B\n" +
|
||||
"\fReqMatchRoom\x12\x16\n" +
|
||||
"\x06gameId\x18\x01 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||
"\broomType\x18\x02 \x01(\x05R\broomType\"\xcc\x01\n" +
|
||||
"\fRspMatchRoom\x12\x1f\n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x1a\n" +
|
||||
"\bPlayType\x18\x02 \x01(\x05R\bPlayType\x12\x1a\n" +
|
||||
"\bRoomType\x18\x03 \x01(\x05R\bRoomType\x12 \n" +
|
||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x16\n" +
|
||||
"\x06gameId\x18\x02 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||
"\broomType\x18\x03 \x01(\x05R\broomType\x12 \n" +
|
||||
"\x04User\x18\x04 \x01(\v2\f.pb.GameUserR\x04User\x128\n" +
|
||||
"\tcolorInfo\x18\x14 \x01(\v2\x1a.pb.RspMatchRoom.ColorInfoR\tcolorInfo\x1a\v\n" +
|
||||
"\tColorInfo\"7\n" +
|
||||
|
@ -42,6 +42,7 @@ const (
|
||||
MsgId_ReqUserLoginId MsgId = 2100 // 玩家登陆
|
||||
MsgId_RspUserLoginId MsgId = 2101
|
||||
MsgId_NtfUserOnlineId MsgId = 2102
|
||||
MsgId_NtfUserInServiceId MsgId = 2103 // 将玩家之前呆的服务同步给玩家,方便玩家重连进来
|
||||
MsgId_ReqUserLogoutId MsgId = 2104
|
||||
MsgId_RspUserLogoutId MsgId = 2105
|
||||
MsgId_NtfUserOfflineId MsgId = 2106
|
||||
@ -78,6 +79,7 @@ var (
|
||||
2100: "ReqUserLoginId",
|
||||
2101: "RspUserLoginId",
|
||||
2102: "NtfUserOnlineId",
|
||||
2103: "NtfUserInServiceId",
|
||||
2104: "ReqUserLogoutId",
|
||||
2105: "RspUserLogoutId",
|
||||
2106: "NtfUserOfflineId",
|
||||
@ -109,6 +111,7 @@ var (
|
||||
"ReqUserLoginId": 2100,
|
||||
"RspUserLoginId": 2101,
|
||||
"NtfUserOnlineId": 2102,
|
||||
"NtfUserInServiceId": 2103,
|
||||
"ReqUserLogoutId": 2104,
|
||||
"RspUserLogoutId": 2105,
|
||||
"NtfUserOfflineId": 2106,
|
||||
@ -160,7 +163,7 @@ var File_msgId_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_msgId_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\vmsgId.proto\x12\x02pb*\x91\x05\n" +
|
||||
"\vmsgId.proto\x12\x02pb*\xaa\x05\n" +
|
||||
"\x05MsgId\x12\x0e\n" +
|
||||
"\n" +
|
||||
"MI_Unknown\x10\x00\x12\x12\n" +
|
||||
@ -174,7 +177,8 @@ const file_msgId_proto_rawDesc = "" +
|
||||
"\tRspChatId\x10\xd1\x0f\x12\x13\n" +
|
||||
"\x0eReqUserLoginId\x10\xb4\x10\x12\x13\n" +
|
||||
"\x0eRspUserLoginId\x10\xb5\x10\x12\x14\n" +
|
||||
"\x0fNtfUserOnlineId\x10\xb6\x10\x12\x14\n" +
|
||||
"\x0fNtfUserOnlineId\x10\xb6\x10\x12\x17\n" +
|
||||
"\x12NtfUserInServiceId\x10\xb7\x10\x12\x14\n" +
|
||||
"\x0fReqUserLogoutId\x10\xb8\x10\x12\x14\n" +
|
||||
"\x0fRspUserLogoutId\x10\xb9\x10\x12\x15\n" +
|
||||
"\x10NtfUserOfflineId\x10\xba\x10\x12\x13\n" +
|
||||
|
@ -30,6 +30,7 @@ const (
|
||||
ServiceTypeId_STI_Chat ServiceTypeId = 102 // 聊天服
|
||||
ServiceTypeId_STI_DB ServiceTypeId = 103 // db服
|
||||
ServiceTypeId_STI_Match ServiceTypeId = 104 // 匹配服
|
||||
ServiceTypeId_STI_Lobby ServiceTypeId = 105 // 大厅服
|
||||
ServiceTypeId_STI_ColorGame ServiceTypeId = 120 // color game
|
||||
)
|
||||
|
||||
@ -42,6 +43,7 @@ var (
|
||||
102: "STI_Chat",
|
||||
103: "STI_DB",
|
||||
104: "STI_Match",
|
||||
105: "STI_Lobby",
|
||||
120: "STI_ColorGame",
|
||||
}
|
||||
ServiceTypeId_value = map[string]int32{
|
||||
@ -51,6 +53,7 @@ var (
|
||||
"STI_Chat": 102,
|
||||
"STI_DB": 103,
|
||||
"STI_Match": 104,
|
||||
"STI_Lobby": 105,
|
||||
"STI_ColorGame": 120,
|
||||
}
|
||||
)
|
||||
@ -86,7 +89,7 @@ var File_service_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_service_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\rservice.proto\x12\x02pb*y\n" +
|
||||
"\rservice.proto\x12\x02pb*\x88\x01\n" +
|
||||
"\rServiceTypeId\x12\x0f\n" +
|
||||
"\vSTI_Unknown\x10\x00\x12\f\n" +
|
||||
"\bSTI_Gate\x10d\x12\r\n" +
|
||||
@ -94,7 +97,8 @@ const file_service_proto_rawDesc = "" +
|
||||
"\bSTI_Chat\x10f\x12\n" +
|
||||
"\n" +
|
||||
"\x06STI_DB\x10g\x12\r\n" +
|
||||
"\tSTI_Match\x10h\x12\x11\n" +
|
||||
"\tSTI_Match\x10h\x12\r\n" +
|
||||
"\tSTI_Lobby\x10i\x12\x11\n" +
|
||||
"\rSTI_ColorGame\x10xB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
|
||||
var (
|
||||
|
@ -24,11 +24,11 @@ const (
|
||||
// 聊天中显示的玩家基础信息
|
||||
type ChatUser struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||
Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` // 昵称
|
||||
Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` // 头像
|
||||
AvatarFrame string `protobuf:"bytes,4,opt,name=avatar_frame,json=avatarFrame,proto3" json:"avatar_frame,omitempty"` // 头像框
|
||||
VipLevel string `protobuf:"bytes,5,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` // vip等级
|
||||
AvatarFrame string `protobuf:"bytes,4,opt,name=avatarFrame,proto3" json:"avatarFrame,omitempty"` // 头像框
|
||||
VipLevel string `protobuf:"bytes,5,opt,name=vipLevel,proto3" json:"vipLevel,omitempty"` // vip等级
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -101,12 +101,12 @@ func (x *ChatUser) GetVipLevel() string {
|
||||
// 房间内的玩家数据
|
||||
type GameUser struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||
Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` // 昵称
|
||||
Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` // 头像
|
||||
AvatarFrame string `protobuf:"bytes,4,opt,name=avatar_frame,json=avatarFrame,proto3" json:"avatar_frame,omitempty"` // 头像框
|
||||
VipLevel int32 `protobuf:"varint,5,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` // vip等级
|
||||
VipExp int32 `protobuf:"varint,6,opt,name=vip_exp,json=vipExp,proto3" json:"vip_exp,omitempty"` // vip经验
|
||||
AvatarFrame string `protobuf:"bytes,4,opt,name=avatarFrame,proto3" json:"avatarFrame,omitempty"` // 头像框
|
||||
VipLevel int32 `protobuf:"varint,5,opt,name=vipLevel,proto3" json:"vipLevel,omitempty"` // vip等级
|
||||
VipExp int32 `protobuf:"varint,6,opt,name=vipExp,proto3" json:"vipExp,omitempty"` // vip经验
|
||||
Seat int64 `protobuf:"varint,20,opt,name=seat,proto3" json:"seat,omitempty"` // 座位
|
||||
Gold int64 `protobuf:"varint,25,opt,name=gold,proto3" json:"gold,omitempty"` // 金币
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@ -204,20 +204,20 @@ var File_user_proto protoreflect.FileDescriptor
|
||||
const file_user_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"user.proto\x12\x02pb\"\x97\x01\n" +
|
||||
"\bChatUser\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||
"user.proto\x12\x02pb\"\x94\x01\n" +
|
||||
"\bChatUser\x12\x16\n" +
|
||||
"\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12!\n" +
|
||||
"\favatar_frame\x18\x04 \x01(\tR\vavatarFrame\x12\x1b\n" +
|
||||
"\tvip_level\x18\x05 \x01(\tR\bvipLevel\"\xd8\x01\n" +
|
||||
"\bGameUser\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12 \n" +
|
||||
"\vavatarFrame\x18\x04 \x01(\tR\vavatarFrame\x12\x1a\n" +
|
||||
"\bvipLevel\x18\x05 \x01(\tR\bvipLevel\"\xd4\x01\n" +
|
||||
"\bGameUser\x12\x16\n" +
|
||||
"\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12!\n" +
|
||||
"\favatar_frame\x18\x04 \x01(\tR\vavatarFrame\x12\x1b\n" +
|
||||
"\tvip_level\x18\x05 \x01(\x05R\bvipLevel\x12\x17\n" +
|
||||
"\avip_exp\x18\x06 \x01(\x05R\x06vipExp\x12\x12\n" +
|
||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12 \n" +
|
||||
"\vavatarFrame\x18\x04 \x01(\tR\vavatarFrame\x12\x1a\n" +
|
||||
"\bvipLevel\x18\x05 \x01(\x05R\bvipLevel\x12\x16\n" +
|
||||
"\x06vipExp\x18\x06 \x01(\x05R\x06vipExp\x12\x12\n" +
|
||||
"\x04seat\x18\x14 \x01(\x03R\x04seat\x12\x12\n" +
|
||||
"\x04gold\x18\x19 \x01(\x03R\x04goldB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
|
||||
|
@ -6,6 +6,7 @@ const (
|
||||
Login = "login"
|
||||
Db = "db"
|
||||
Match = "match"
|
||||
Lobby = "lobby"
|
||||
|
||||
// 下面是具体玩法服
|
||||
ColorGame = "color_game"
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"game/common/utils"
|
||||
"github.com/fox/fox/etcd"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/fox/fox/service"
|
||||
"github.com/fox/fox/xrand"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"time"
|
||||
@ -24,6 +23,14 @@ const (
|
||||
客户端没有指定路由节点,则服务器从redis查找曾经的绑定节点,并验证有效然后转发到对应的节点。
|
||||
如果redis信息已经失效(服务有更新),则从etcd中获取该玩法下所有最新版本的节点(game1,game2),然后随机发送到其中一个节点,并在redis中保存绑定关系。
|
||||
如果客户端所有消息都不指定具体的节点名,则每次都需要从redis拉取绑定关系,会影响路由速度。
|
||||
|
||||
服务分为3种类型:
|
||||
1.有状态服,如各玩法服,需要保存玩家在哪个状态服里。
|
||||
--1.1 这一类服务需要使用UserBindService.HashServiceNode来获取节点
|
||||
2.无状态服,如大厅服,登陆服,聊天服,这些服务不持有任何状态,包括玩家数据。无需保存玩家在哪个服务。直接通过group.topic随机路由即可。
|
||||
--2.1 这一类服务无需走UserBindService,直接通过group.topic路由即可。
|
||||
3.有序hash服,如db服,需要根据玩家id hash到固定的db服以保证操作的一致性。
|
||||
--3.1 这一类服务需要使用UserBindService.HashServiceNode来获取节点
|
||||
*/
|
||||
type UserBindService struct {
|
||||
rdb *redis.Client
|
||||
@ -37,14 +44,18 @@ func NewUserBindService(rdb *redis.Client, etcdRegistry *etcd.Registry[etcd.Serv
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UserBindService) makeRedisKey(userId int64, typeId pb.ServiceTypeId) string {
|
||||
return fmt.Sprintf("%s_%d:%d", prefix, userId, int(typeId))
|
||||
func (m *UserBindService) makeRedisKey(userId int64) string {
|
||||
return fmt.Sprintf("%s:%s", prefix, userId)
|
||||
}
|
||||
func (m *UserBindService) makeRedisSubKey(typeId pb.ServiceTypeId) string {
|
||||
return typeId.String()
|
||||
}
|
||||
|
||||
// 从redis中加载玩家曾经访问过的服务节点名
|
||||
func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) string {
|
||||
k := m.makeRedisKey(userId, typeId)
|
||||
if sName, err := m.rdb.Get(context.Background(), k).Result(); err != nil {
|
||||
key := m.makeRedisKey(userId)
|
||||
subKey := m.makeRedisSubKey(typeId)
|
||||
if sName, err := m.rdb.HGet(context.Background(), key, subKey).Result(); err != nil {
|
||||
if !errors.Is(err, redis.Nil) {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
@ -56,24 +67,34 @@ func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) s
|
||||
|
||||
// 从redis中解除玩家与节点的绑定关系
|
||||
func (m *UserBindService) DelUserService(userId int64, typeId pb.ServiceTypeId) {
|
||||
k := m.makeRedisKey(userId, typeId)
|
||||
_, _ = m.rdb.Del(context.Background(), k).Result()
|
||||
key := m.makeRedisKey(userId)
|
||||
subKey := m.makeRedisSubKey(typeId)
|
||||
_, _ = m.rdb.HDel(context.Background(), key, subKey).Result()
|
||||
}
|
||||
|
||||
// 保存玩家与节点的绑定关系至从redis
|
||||
func (m *UserBindService) SaveUserService(userId int64, typeId pb.ServiceTypeId, serviceName string) {
|
||||
key := m.makeRedisKey(userId)
|
||||
subKey := m.makeRedisSubKey(typeId)
|
||||
m.rdb.HSet(context.Background(), key, subKey, serviceName, 2*24*time.Hour)
|
||||
}
|
||||
|
||||
// 从etcd中检查节点是否有效,如果有game1(旧服),game2(新服),都算有效,但是旧服会拒绝新玩家进入,
|
||||
// 此时旧服不止要拒绝新玩家,还要删除redis中的绑定关系。方便客户端重新发消息时路由到新的服务。
|
||||
func (m *UserBindService) serviceIsValid(serviceName string) bool {
|
||||
func (m *UserBindService) findServiceNodeByServiceName(serviceName string) (*etcd.ServiceNode, bool) {
|
||||
var sNode *etcd.ServiceNode
|
||||
valid := false
|
||||
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
||||
if node, ok := v.(etcd.ServiceNode); ok {
|
||||
if node.Name == serviceName {
|
||||
valid = true
|
||||
sNode = &node
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return valid
|
||||
return sNode, valid
|
||||
}
|
||||
|
||||
func (m *UserBindService) stringAllServiceNode() string {
|
||||
@ -86,7 +107,7 @@ func (m *UserBindService) stringAllServiceNode() string {
|
||||
}
|
||||
|
||||
// 从etcd中找可用服务节点随机选择一个
|
||||
func (m *UserBindService) RandServiceNode(typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) {
|
||||
func (m *UserBindService) randServiceNode(typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) {
|
||||
var nodes []etcd.ServiceNode
|
||||
var version string
|
||||
m.etcdRegistry.GetNodes().Range(func(_, value any) bool {
|
||||
@ -109,47 +130,12 @@ func (m *UserBindService) RandServiceNode(typeId pb.ServiceTypeId) (*etcd.Servic
|
||||
if len(nodes) == 0 {
|
||||
return nil, fmt.Errorf("not found service node.type id:%v. all node:%v", typeId, m.stringAllServiceNode())
|
||||
}
|
||||
n := xrand.IntN(len(nodes))
|
||||
n := xrand.RandN(len(nodes))
|
||||
return &nodes[n], nil
|
||||
}
|
||||
|
||||
// 根据服务类型,路由到对应的服务节点
|
||||
func (m *UserBindService) findServiceName(userId int64, typeId pb.ServiceTypeId) (string, error) {
|
||||
if userId > 0 {
|
||||
// 向redis中查询。redis中保留的服务节点不一定是可用的,还需要向etcd中验证
|
||||
sName := m.LoadFromRedis(userId, typeId)
|
||||
// log.DebugF("user:%v查找到服务节点:%s", userId, sName)
|
||||
if sName != "" && m.serviceIsValid(sName) {
|
||||
return sName, nil
|
||||
}
|
||||
}
|
||||
|
||||
// log.DebugF("user:%v查找到服务节点:%s为无效节点", userId, sName)
|
||||
// redis也没有玩家的服务节点信息,从etcd中找可用服务节点随机选择一个
|
||||
node, err := m.RandServiceNode(typeId)
|
||||
if err != nil {
|
||||
log.ErrorF("etcd中随机一个服务节点时,错误:%v", err)
|
||||
return "", err
|
||||
}
|
||||
// log.DebugF("etcd中随机一个服务节点:%s", node.Name)
|
||||
m.rdb.Set(context.Background(), m.makeRedisKey(userId, typeId), node.Name, 2*24*time.Hour)
|
||||
return node.Name, nil
|
||||
}
|
||||
|
||||
/*
|
||||
查找topic,根据serviceTypeId以及玩家id查找玩家过往访问该服务的节点,优先使用原节点
|
||||
*/
|
||||
func (m *UserBindService) FindTopic(userId int64, serviceTypeId pb.ServiceTypeId) (topic, sName string) {
|
||||
var err error
|
||||
if sName, err = m.findServiceName(userId, serviceTypeId); err == nil {
|
||||
return service.TopicEx(sName), sName
|
||||
} else {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
return "", sName
|
||||
}
|
||||
|
||||
// 从etcd中hash一个服务节点
|
||||
// 从etcd中hash一个服务节点。不需要保存玩家在哪个服务。
|
||||
// 该服务是类似于db服这种有序操作的hash服
|
||||
func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*etcd.ServiceNode, error) {
|
||||
var nodes []etcd.ServiceNode
|
||||
var version string
|
||||
@ -176,3 +162,51 @@ func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*
|
||||
n := uid % int64(len(nodes))
|
||||
return &nodes[n], nil
|
||||
}
|
||||
|
||||
// 要查找的服务必须是状态服,无状态服不需要查找指定服务。
|
||||
// 如果玩家是首次使用该服务,则随机一个服务并保存玩家该服务节点。下次查找时返回该节点。
|
||||
func (m *UserBindService) FindServiceNode(userId int64, typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) {
|
||||
if userId > 0 {
|
||||
// 向redis中查询。redis中保留的服务节点不一定是可用的,还需要向etcd中验证
|
||||
sName := m.LoadFromRedis(userId, typeId)
|
||||
// log.DebugF("user:%v查找到服务节点:%s", userId, sName)
|
||||
if node, ok := m.findServiceNodeByServiceName(sName); ok {
|
||||
return node, nil
|
||||
}
|
||||
}
|
||||
|
||||
// log.DebugF("user:%v查找到服务节点:%s为无效节点", userId, sName)
|
||||
// redis也没有玩家的服务节点信息,从etcd中找可用服务节点随机选择一个
|
||||
node, err := m.randServiceNode(typeId)
|
||||
if err != nil {
|
||||
log.ErrorF("etcd中随机一个服务节点时,错误:%v", err)
|
||||
return nil, err
|
||||
}
|
||||
// log.DebugF("etcd中随机一个服务节点:%s", node.Name)
|
||||
m.rdb.HSet(context.Background(), m.makeRedisKey(userId), node.Name, 2*24*time.Hour)
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// 查找玩家所有的玩法节点
|
||||
func (m *UserBindService) GetAllUserInGameServiceNode(userId int64) ([]*etcd.ServiceNode, error) {
|
||||
if userId > 0 {
|
||||
maps, err := m.rdb.HGetAll(context.Background(), m.makeRedisKey(userId)).Result()
|
||||
if err != nil && err != redis.Nil {
|
||||
log.ErrorF("user:%v get all service error:%v", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
if len(maps) > 0 {
|
||||
inGames := make([]*etcd.ServiceNode, 0)
|
||||
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
||||
if node, ok := v.(etcd.ServiceNode); ok {
|
||||
if _, ok = maps[node.Name]; ok && node.TypeId != int(pb.ServiceTypeId_STI_Gate) {
|
||||
inGames = append(inGames, &node)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return inGames, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package room
|
||||
|
||||
import (
|
||||
"game/common/proto/pb"
|
||||
"game/common/userBindService"
|
||||
"game/server/colorgame/model"
|
||||
"github.com/fox/fox/ipb"
|
||||
)
|
||||
|
||||
@ -53,6 +55,9 @@ func (rm *ColorRoom) checkLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, re
|
||||
func (rm *ColorRoom) leaveRoom(user *ColorPlayer) {
|
||||
rm.DelPlayer(user.Id())
|
||||
rm.userMgr.Del(user.ID)
|
||||
// 移除redis中玩家与本服务绑定关系
|
||||
userService := userBindService.NewUserBindService(model.UserBindServiceRedis, nil)
|
||||
userService.DelUserService(user.ID, pb.ServiceTypeId_STI_ColorGame)
|
||||
}
|
||||
|
||||
func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) {
|
||||
|
@ -33,7 +33,7 @@ type ColorRoom struct {
|
||||
}
|
||||
|
||||
func newColorRoom(id, roomType int, srv service.IService, userMgr *baseroom.PlayerMgr) (baseroom.IRoom, pb.ErrCode) {
|
||||
playType := int(pb.ServiceTypeId_STI_ColorGame)
|
||||
gameId := int(pb.ServiceTypeId_STI_ColorGame)
|
||||
rm := &ColorRoom{
|
||||
HundredRoom: nil,
|
||||
userMgr: userMgr,
|
||||
@ -44,13 +44,13 @@ func newColorRoom(id, roomType int, srv service.IService, userMgr *baseroom.Play
|
||||
jackpotValue: 0,
|
||||
endBetAreaMul: make([]*pb.ColorBetAreaMul, 0, len(pb.ColorBetArea_name)),
|
||||
winBetAreaMul: nil,
|
||||
jackpotMgr: jackpot.NewJackpotMgr(playType, model.UserRedis),
|
||||
jackpotMgr: jackpot.NewJackpotMgr(gameId, model.UserRedis),
|
||||
}
|
||||
rm.trend = rm.initGameTrend()
|
||||
rm.resetGameData()
|
||||
|
||||
code := pb.ErrCode_OK
|
||||
rm.HundredRoom, code = baseroom.NewHundredRoom(id, roomType, playType, srv)
|
||||
rm.HundredRoom, code = baseroom.NewHundredRoom(id, roomType, gameId, srv)
|
||||
if code != pb.ErrCode_OK {
|
||||
log.ErrorF("new color room err code:%v", code)
|
||||
return nil, code
|
||||
|
@ -1,47 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fox/fox/log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// func initLog(command *config.Command) {
|
||||
// log.Open(fmt.Sprintf("%v/%v/%v.log", command.LogPath, servername.Money, servername.Money), command.LogLevel)
|
||||
// }
|
||||
|
||||
func initLog() {
|
||||
log.Open("hilo.log", log.DebugL)
|
||||
}
|
||||
|
||||
func initRepo() {
|
||||
// model.InitUserDB(&config.Config.DBConfig)
|
||||
// model.InitConfigDB(&config.Config.DBConfig)
|
||||
// model.InitRedis(&config.Config.Redis)
|
||||
// model.InitStub()
|
||||
// RobotMgr.Load()
|
||||
// ClubRobotMgr.Load()
|
||||
// //log.Debug(fmt.Sprintf("%+v", stub.GGlobal))
|
||||
}
|
||||
|
||||
func Run(version string) {
|
||||
// command := config.ParseCommand()
|
||||
// initLog(command)
|
||||
initLog()
|
||||
log.Info(fmt.Sprintf("版本信息.%v", version))
|
||||
// err := config.Load(command.ConfigPath)
|
||||
// if err != nil {
|
||||
// log.Error(fmt.Sprintf("load config err: %v", err))
|
||||
// }
|
||||
// initRepo()
|
||||
|
||||
// handler.InitService()
|
||||
// 截获 SIGINT 和 SIGTERM 信号
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
sig := <-c
|
||||
// handler.StopService()
|
||||
log.Info(fmt.Sprintf("received %s, initiating shutdown...", sig))
|
||||
}
|
31
server/lobby/cmd/cmd.go
Normal file
31
server/lobby/cmd/cmd.go
Normal file
@ -0,0 +1,31 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"game/server/lobby/config"
|
||||
"game/server/lobby/model"
|
||||
"game/server/lobby/server"
|
||||
"github.com/fox/fox/log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func initRepo() {
|
||||
model.InitRedis()
|
||||
}
|
||||
|
||||
func Run(GitCommit, GitBranch, BuildDate string) {
|
||||
config.InitLog()
|
||||
config.LoadConfig(GitCommit, GitBranch, BuildDate)
|
||||
log.Info(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
|
||||
initRepo()
|
||||
|
||||
server.Init()
|
||||
// 截获 SIGINT 和 SIGTERM 信号
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
sig := <-c
|
||||
server.Stop()
|
||||
log.Info(fmt.Sprintf("received %s, initiating shutdown...", sig))
|
||||
}
|
38
server/lobby/config/config.go
Normal file
38
server/lobby/config/config.go
Normal file
@ -0,0 +1,38 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"game/common/config"
|
||||
"game/common/constant"
|
||||
"github.com/fox/fox/db"
|
||||
"github.com/fox/fox/log"
|
||||
)
|
||||
|
||||
var Command *config.Command
|
||||
var Cfg *config.Common
|
||||
|
||||
type LobbyConfig struct {
|
||||
}
|
||||
|
||||
func InitLog() {
|
||||
log.Open("./log/chat.log", log.DebugL)
|
||||
log.Info("")
|
||||
log.Info("")
|
||||
log.Info("")
|
||||
log.Info("-----init log success-----")
|
||||
}
|
||||
|
||||
func LoadConfig(GitCommit, GitBranch, BuildDate string) {
|
||||
Command = config.ParseCommand()
|
||||
rdb, err := db.InitRedis(Command.RedisPassword, Command.RedisHost, Command.RedisPort, constant.Redis0Config)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
defer func() { _ = rdb.Close() }()
|
||||
Cfg, err = config.LoadCommonConfig[LobbyConfig](rdb, GitCommit, GitBranch, BuildDate)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.DebugF("load common config success")
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"game/server/hilo/cmd"
|
||||
"game/server/lobby/cmd"
|
||||
"github.com/fox/fox/ksync"
|
||||
"github.com/fox/fox/log"
|
||||
"time"
|
||||
@ -19,7 +18,8 @@ func main() {
|
||||
if err == nil {
|
||||
BuildDate = tm.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
//BuildDate = "2025-05-31 09:56:06"
|
||||
ksync.RunSafe(func() {
|
||||
cmd.Run(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
|
||||
}, func() { log.Debug("reset run") })
|
||||
cmd.Run(GitBranch, GitCommit, BuildDate)
|
||||
}, func() { log.ErrorF("reset run") })
|
||||
}
|
20
server/lobby/model/db.go
Normal file
20
server/lobby/model/db.go
Normal file
@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"game/common/constant"
|
||||
"game/server/lobby/config"
|
||||
"github.com/fox/fox/db"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
var UserRedis *redis.Client
|
||||
var err error
|
||||
|
||||
func InitRedis() {
|
||||
UserRedis, err = db.InitRedis(config.Cfg.Redis.Password, config.Cfg.Redis.Host, config.Cfg.Redis.Port, constant.Redis1User)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
25
server/lobby/server/processor.go
Normal file
25
server/lobby/server/processor.go
Normal file
@ -0,0 +1,25 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"game/common/proto/pb"
|
||||
"github.com/fox/fox/ipb"
|
||||
"github.com/fox/fox/processor"
|
||||
"github.com/fox/fox/service"
|
||||
)
|
||||
|
||||
func (s *LobbyService) initProcessor() {
|
||||
s.processor.RegisterMessages(processor.RegisterMetas{
|
||||
pb.MsgId_NtfUserOnlineId: {pb.NtfUserOnline{}, s.onUserOnline},
|
||||
})
|
||||
}
|
||||
|
||||
// 玩家上线,告诉玩家在哪个玩法中
|
||||
func (s *LobbyService) onUserOnline(iMsg *ipb.InternalMsg, msg *pb.NtfUserOnline) {
|
||||
nodes, _ := s.bindService.GetAllUserInGameServiceNode(msg.UserId)
|
||||
ntf := &pb.NtfUserInService{}
|
||||
for _, node := range nodes {
|
||||
ntf.ServiceNames = append(ntf.ServiceNames, node.Name)
|
||||
}
|
||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.UserId, int32(pb.MsgId_NtfUserInServiceId), ntf)
|
||||
|
||||
}
|
116
server/lobby/server/service.go
Normal file
116
server/lobby/server/service.go
Normal file
@ -0,0 +1,116 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"game/common/proto/pb"
|
||||
"game/common/serviceName"
|
||||
"game/common/userBindService"
|
||||
"game/server/lobby/config"
|
||||
"game/server/lobby/model"
|
||||
"github.com/fox/fox/ipb"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/fox/fox/processor"
|
||||
"github.com/fox/fox/service"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// 大厅服-无状态服,自身不持有任何状态包括玩家数据
|
||||
var lobby []*LobbyService
|
||||
|
||||
type LobbyService struct {
|
||||
*service.NatsService
|
||||
processor *processor.Processor
|
||||
bindService *userBindService.UserBindService
|
||||
}
|
||||
|
||||
func Init() {
|
||||
for i := 0; i < config.Command.ServiceNum; i++ {
|
||||
sid := config.Command.ServiceId + i
|
||||
if srv := newLobbyService(sid); srv != nil {
|
||||
lobby = append(lobby, srv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Stop() {
|
||||
for _, srv := range lobby {
|
||||
srv.NotifyStop()
|
||||
}
|
||||
for _, srv := range lobby {
|
||||
srv.WaitStop()
|
||||
}
|
||||
}
|
||||
|
||||
func newLobbyService(serviceId int) *LobbyService {
|
||||
var err error
|
||||
s := new(LobbyService)
|
||||
|
||||
sName := fmt.Sprintf("%v-%d", serviceName.Lobby, serviceId)
|
||||
if s.NatsService, err = service.NewNatsService(&service.InitNatsServiceParams{
|
||||
EtcdAddress: config.Cfg.Etcd.Address,
|
||||
EtcdUsername: "",
|
||||
EtcdPassword: "",
|
||||
NatsAddress: config.Cfg.Nats.Address,
|
||||
ServiceType: serviceName.Lobby,
|
||||
ServiceName: sName,
|
||||
OnFunc: s,
|
||||
TypeId: int(pb.ServiceTypeId_STI_Lobby),
|
||||
Version: config.Cfg.BuildDate,
|
||||
}); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
s.bindService = userBindService.NewUserBindService(model.UserRedis, s.ServiceEtcd())
|
||||
s.processor = processor.NewProcessor()
|
||||
s.initProcessor()
|
||||
s.OnInit()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *LobbyService) OnInit() {
|
||||
if err := s.NatsService.QueueSubscribe(service.GroupTopic(s), service.GroupQueue(s)); err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
s.NatsService.Run()
|
||||
log.Debug("onInit")
|
||||
}
|
||||
|
||||
func (s *LobbyService) CanStop() bool {
|
||||
//log.Debug("chatService.CanStop")
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *LobbyService) OnStop() {
|
||||
s.NatsService.OnStop()
|
||||
log.Debug("OnStop")
|
||||
}
|
||||
|
||||
// 处理其它服发送过来的消息
|
||||
func (s *LobbyService) OnMessage(data []byte) error {
|
||||
var iMsg = &ipb.InternalMsg{}
|
||||
var err error
|
||||
if err = proto.Unmarshal(data, iMsg); err != nil {
|
||||
log.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
if req, err := s.processor.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
|
||||
err = s.processor.Dispatch(iMsg.MsgId, iMsg, req)
|
||||
} else {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
//log.Debug(s.Log("received message:%v", iMsg.MsgId))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 向内部服务发送消息
|
||||
func (s *LobbyService) SendServiceData(topic string, userId int64, msgId int32, data []byte) {
|
||||
iMsg := ipb.MakeMsg(s.Name(), 0, userId, msgId, data)
|
||||
_ = s.Send(topic, iMsg)
|
||||
}
|
||||
|
||||
// 向内部服务发送消息
|
||||
func (s *LobbyService) SendServiceMsg(topic string, userId int64, msgId int32, msg proto.Message) {
|
||||
data, _ := proto.Marshal(msg)
|
||||
s.SendServiceData(topic, userId, msgId, data)
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/fox/fox/processor"
|
||||
"github.com/fox/fox/service"
|
||||
"github.com/fox/fox/xrand"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -27,7 +28,7 @@ func (s *LoginService) initProcessor() {
|
||||
|
||||
func (s *LoginService) checkLoginOrRegister(req *pb.ReqUserLogin) (us *user.UserAccount, code pb.ErrCode, node *etcd.ServiceNode) {
|
||||
var err error
|
||||
node, err = s.bindService.RandServiceNode(pb.ServiceTypeId_STI_DB)
|
||||
node, err = s.bindService.HashServiceNode(pb.ServiceTypeId_STI_DB, xrand.RandN[int64](100))
|
||||
if err != nil {
|
||||
log.ErrorF(s.Log("not find db service.err:%s ", err.Error()))
|
||||
return nil, pb.ErrCode_SystemErr, node
|
||||
|
@ -15,10 +15,10 @@ import (
|
||||
func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom) {
|
||||
ksync.GoSafe(func() {
|
||||
// color game无需进入匹配队列
|
||||
playType := pb.ServiceTypeId(req.PlayType)
|
||||
switch playType {
|
||||
gameId := pb.ServiceTypeId(req.GameId)
|
||||
switch gameId {
|
||||
case pb.ServiceTypeId_STI_ColorGame:
|
||||
node, err := s.bindService.RandServiceNode(playType)
|
||||
node, err := s.bindService.FindServiceNode(iMsg.UserId, gameId)
|
||||
if err != nil {
|
||||
log.ErrorF("db service node error:%v", err)
|
||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, iMsg.UserId,
|
||||
@ -47,9 +47,9 @@ func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom)
|
||||
Seat: 0,
|
||||
Gold: us.Gold,
|
||||
}
|
||||
rsp.PlayType = req.PlayType
|
||||
rsp.GameId = req.GameId
|
||||
rsp.RoomType = req.RoomType
|
||||
switch pb.ServiceTypeId(rsp.PlayType) {
|
||||
switch pb.ServiceTypeId(rsp.GameId) {
|
||||
case pb.ServiceTypeId_STI_ColorGame:
|
||||
rsp.ColorInfo = &pb.RspMatchRoom_ColorInfo{}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user