添加lobby服
This commit is contained in:
parent
e44d0a510e
commit
15a4b8256a
@ -25,7 +25,7 @@ const (
|
|||||||
type BaseRoom[Seat ISeat] struct {
|
type BaseRoom[Seat ISeat] struct {
|
||||||
id int
|
id int
|
||||||
roomType int // 房间配置id 初级,中级,高级
|
roomType int // 房间配置id 初级,中级,高级
|
||||||
playType int // 玩法配置id color玩法id
|
gameId int // 玩法配置id color玩法id
|
||||||
gameNo string
|
gameNo string
|
||||||
seats []Seat
|
seats []Seat
|
||||||
processor *processor.Processor
|
processor *processor.Processor
|
||||||
@ -35,11 +35,11 @@ type BaseRoom[Seat ISeat] struct {
|
|||||||
srv service.IService
|
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]{
|
room := &BaseRoom[Seat]{
|
||||||
id: id,
|
id: id,
|
||||||
roomType: roomType,
|
roomType: roomType,
|
||||||
playType: playType,
|
gameId: gameId,
|
||||||
gameNo: "",
|
gameNo: "",
|
||||||
seats: make([]Seat, seatNum),
|
seats: make([]Seat, seatNum),
|
||||||
timeTypes: make(map[timer.ITimeType]uint32),
|
timeTypes: make(map[timer.ITimeType]uint32),
|
||||||
@ -59,8 +59,8 @@ func (r *BaseRoom[Seat]) RoomType() int {
|
|||||||
return r.roomType
|
return r.roomType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *BaseRoom[Seat]) PlayType() int {
|
func (r *BaseRoom[Seat]) GameId() int {
|
||||||
return r.playType
|
return r.gameId
|
||||||
}
|
}
|
||||||
|
|
||||||
// 入座玩家数量
|
// 入座玩家数量
|
||||||
@ -257,10 +257,6 @@ func (r *BaseRoom[Seat]) RegisterMessages(metas processor.RegisterMetas) {
|
|||||||
r.processor.RegisterMessages(metas)
|
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) {
|
func (r *BaseRoom[Seat]) RegisterTimerMessages(metas processor.RegisterTimerMetas) {
|
||||||
r.timeProcessor.RegisterMessages(metas)
|
r.timeProcessor.RegisterMessages(metas)
|
||||||
|
@ -18,8 +18,8 @@ type HundredRoom struct {
|
|||||||
users map[int64]IPlayer // 所有玩家
|
users map[int64]IPlayer // 所有玩家
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHundredRoom(id, roomType, playType int, srv service.IService) (*HundredRoom, pb.ErrCode) {
|
func NewHundredRoom(id, roomType, gameId int, srv service.IService) (*HundredRoom, pb.ErrCode) {
|
||||||
baseRoom, code := NewBaseRoom[*BaseSeat](id, roomType, playType, 0, srv)
|
baseRoom, code := NewBaseRoom[*BaseSeat](id, roomType, gameId, 0, srv)
|
||||||
if code != pb.ErrCode_OK {
|
if code != pb.ErrCode_OK {
|
||||||
return nil, code
|
return nil, code
|
||||||
}
|
}
|
||||||
@ -37,8 +37,8 @@ func (r *HundredRoom) RoomType() int {
|
|||||||
return r.room.RoomType()
|
return r.room.RoomType()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HundredRoom) PlayType() int {
|
func (r *HundredRoom) GameId() int {
|
||||||
return r.room.PlayType()
|
return r.room.GameId()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 房间玩家数量
|
// 房间玩家数量
|
||||||
@ -169,10 +169,6 @@ func (r *HundredRoom) RegisterMessages(metas processor.RegisterMetas) {
|
|||||||
r.room.RegisterMessages(metas)
|
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) {
|
func (r *HundredRoom) RegisterTimerMessages(metas processor.RegisterTimerMetas) {
|
||||||
r.room.RegisterTimerMessages(metas)
|
r.room.RegisterTimerMessages(metas)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
type IRoom interface {
|
type IRoom interface {
|
||||||
Id() int
|
Id() int
|
||||||
RoomType() int // 房间配置id
|
RoomType() int // 房间配置id
|
||||||
PlayType() int
|
GameId() int
|
||||||
OnInit()
|
OnInit()
|
||||||
// SeatPlayerNum() int
|
// SeatPlayerNum() int
|
||||||
// FindEmptySeat() bool
|
// FindEmptySeat() bool
|
||||||
|
@ -18,10 +18,10 @@ enum ChatType
|
|||||||
// 聊天消息
|
// 聊天消息
|
||||||
message ReqChat
|
message ReqChat
|
||||||
{
|
{
|
||||||
ChatUser src_user = 1; // 说话的人
|
ChatUser srcUser = 1; // 说话的人
|
||||||
ChatUser dst_user = 2; // 接收者
|
ChatUser dstUser = 2; // 接收者
|
||||||
ChatType type = 3; // 聊天类型
|
ChatType type = 3; // 聊天类型
|
||||||
ServiceTypeId game_id = 4; // 游戏id,只在本玩法中显示的聊天信息
|
ServiceTypeId gameId = 4; // 游戏id,只在本玩法中显示的聊天信息
|
||||||
string content = 5; // 内容
|
string content = 5; // 内容
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ message ReqEnterRoom
|
|||||||
message RspEnterRoom
|
message RspEnterRoom
|
||||||
{
|
{
|
||||||
ErrCode code = 1;
|
ErrCode code = 1;
|
||||||
int32 PlayType = 2; // 玩法id
|
int32 gameId = 2; // 玩法id
|
||||||
int32 RoomType = 3; // 房间类型,低级,中级,高级等
|
int32 roomType = 3; // 房间类型,低级,中级,高级等
|
||||||
}
|
}
|
||||||
|
|
||||||
// 玩家离开房间
|
// 玩家离开房间
|
||||||
|
@ -27,6 +27,12 @@ message NtfUserOnline
|
|||||||
int64 user_id = 2; // 玩家id
|
int64 user_id = 2; // 玩家id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知玩家在哪些服务里,方便玩家重进这些服务,重连使用
|
||||||
|
message NtfUserInService
|
||||||
|
{
|
||||||
|
repeated string serviceNames = 3; // 玩家所在玩法的服务名
|
||||||
|
}
|
||||||
|
|
||||||
// 玩家登陆
|
// 玩家登陆
|
||||||
message ReqUserLogout
|
message ReqUserLogout
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,8 @@ import "user.proto";
|
|||||||
// 房间匹配
|
// 房间匹配
|
||||||
message ReqMatchRoom
|
message ReqMatchRoom
|
||||||
{
|
{
|
||||||
int32 PlayType = 1; // 玩法id
|
int32 gameId = 1; // 玩法id
|
||||||
int32 RoomType = 2; // 房间类型,低级,中级,高级等
|
int32 roomType = 2; // 房间类型,低级,中级,高级等
|
||||||
}
|
}
|
||||||
|
|
||||||
// 玩家进房间返回 匹配服返回该消息,假房间。匹配成功后发给对应玩法服,玩法服发NotifyUserEnterRoom才是真房间
|
// 玩家进房间返回 匹配服返回该消息,假房间。匹配成功后发给对应玩法服,玩法服发NotifyUserEnterRoom才是真房间
|
||||||
@ -22,8 +22,8 @@ message RspMatchRoom
|
|||||||
}
|
}
|
||||||
|
|
||||||
ErrCode code = 1;
|
ErrCode code = 1;
|
||||||
int32 PlayType = 2; // 玩法id
|
int32 gameId = 2; // 玩法id
|
||||||
int32 RoomType = 3; // 房间类型,低级,中级,高级等
|
int32 roomType = 3; // 房间类型,低级,中级,高级等
|
||||||
GameUser User = 4; // 玩家数据
|
GameUser User = 4; // 玩家数据
|
||||||
|
|
||||||
ColorInfo colorInfo = 20; // color玩法配置信息
|
ColorInfo colorInfo = 20; // color玩法配置信息
|
||||||
|
@ -27,6 +27,7 @@ enum MsgId
|
|||||||
ReqUserLoginId = 2100; // 玩家登陆
|
ReqUserLoginId = 2100; // 玩家登陆
|
||||||
RspUserLoginId = 2101;
|
RspUserLoginId = 2101;
|
||||||
NtfUserOnlineId = 2102;
|
NtfUserOnlineId = 2102;
|
||||||
|
NtfUserInServiceId = 2103; // 将玩家之前呆的服务同步给玩家,方便玩家重连进来
|
||||||
ReqUserLogoutId = 2104;
|
ReqUserLogoutId = 2104;
|
||||||
RspUserLogoutId = 2105;
|
RspUserLogoutId = 2105;
|
||||||
NtfUserOfflineId = 2106;
|
NtfUserOfflineId = 2106;
|
||||||
|
@ -10,6 +10,7 @@ enum ServiceTypeId
|
|||||||
STI_Chat = 102; // 聊天服
|
STI_Chat = 102; // 聊天服
|
||||||
STI_DB = 103; // db服
|
STI_DB = 103; // db服
|
||||||
STI_Match = 104; // 匹配服
|
STI_Match = 104; // 匹配服
|
||||||
|
STI_Lobby = 105; // 大厅服
|
||||||
|
|
||||||
STI_ColorGame = 120; // color game
|
STI_ColorGame = 120; // color game
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,22 @@ option go_package = "common/proto/pb";
|
|||||||
// 聊天中显示的玩家基础信息
|
// 聊天中显示的玩家基础信息
|
||||||
message ChatUser
|
message ChatUser
|
||||||
{
|
{
|
||||||
int64 user_id = 1;
|
int64 userId = 1;
|
||||||
string nickname = 2; // 昵称
|
string nickname = 2; // 昵称
|
||||||
string avatar = 3; // 头像
|
string avatar = 3; // 头像
|
||||||
string avatar_frame = 4; // 头像框
|
string avatarFrame = 4; // 头像框
|
||||||
string vip_level = 5; // vip等级
|
string vipLevel = 5; // vip等级
|
||||||
}
|
}
|
||||||
|
|
||||||
// 房间内的玩家数据
|
// 房间内的玩家数据
|
||||||
message GameUser
|
message GameUser
|
||||||
{
|
{
|
||||||
int64 user_id = 1;
|
int64 userId = 1;
|
||||||
string nickname = 2; // 昵称
|
string nickname = 2; // 昵称
|
||||||
string avatar = 3; // 头像
|
string avatar = 3; // 头像
|
||||||
string avatar_frame = 4; // 头像框
|
string avatarFrame = 4; // 头像框
|
||||||
int32 vip_level = 5; // vip等级
|
int32 vipLevel = 5; // vip等级
|
||||||
int32 vip_exp = 6; // vip经验
|
int32 vipExp = 6; // vip经验
|
||||||
int64 seat = 20; // 座位
|
int64 seat = 20; // 座位
|
||||||
int64 gold = 25; // 金币
|
int64 gold = 25; // 金币
|
||||||
}
|
}
|
||||||
|
@ -77,10 +77,10 @@ func (ChatType) EnumDescriptor() ([]byte, []int) {
|
|||||||
// 聊天消息
|
// 聊天消息
|
||||||
type ReqChat struct {
|
type ReqChat struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
SrcUser *ChatUser `protobuf:"bytes,1,opt,name=src_user,json=srcUser,proto3" json:"src_user,omitempty"` // 说话的人
|
SrcUser *ChatUser `protobuf:"bytes,1,opt,name=srcUser,proto3" json:"srcUser,omitempty"` // 说话的人
|
||||||
DstUser *ChatUser `protobuf:"bytes,2,opt,name=dst_user,json=dstUser,proto3" json:"dst_user,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"` // 聊天类型
|
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"` // 内容
|
Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` // 内容
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -157,12 +157,12 @@ const file_chat_proto_rawDesc = "" +
|
|||||||
"\n" +
|
"\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"chat.proto\x12\x02pb\x1a\n" +
|
"chat.proto\x12\x02pb\x1a\n" +
|
||||||
"user.proto\x1a\rservice.proto\"\xc3\x01\n" +
|
"user.proto\x1a\rservice.proto\"\xc0\x01\n" +
|
||||||
"\aReqChat\x12'\n" +
|
"\aReqChat\x12&\n" +
|
||||||
"\bsrc_user\x18\x01 \x01(\v2\f.pb.ChatUserR\asrcUser\x12'\n" +
|
"\asrcUser\x18\x01 \x01(\v2\f.pb.ChatUserR\asrcUser\x12&\n" +
|
||||||
"\bdst_user\x18\x02 \x01(\v2\f.pb.ChatUserR\adstUser\x12 \n" +
|
"\adstUser\x18\x02 \x01(\v2\f.pb.ChatUserR\adstUser\x12 \n" +
|
||||||
"\x04type\x18\x03 \x01(\x0e2\f.pb.ChatTypeR\x04type\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" +
|
"\x06gameId\x18\x04 \x01(\x0e2\x11.pb.ServiceTypeIdR\x06gameId\x12\x18\n" +
|
||||||
"\acontent\x18\x05 \x01(\tR\acontent*H\n" +
|
"\acontent\x18\x05 \x01(\tR\acontent*H\n" +
|
||||||
"\bChatType\x12\x0e\n" +
|
"\bChatType\x12\x0e\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
@ -194,10 +194,10 @@ var file_chat_proto_goTypes = []any{
|
|||||||
(ServiceTypeId)(0), // 3: pb.ServiceTypeId
|
(ServiceTypeId)(0), // 3: pb.ServiceTypeId
|
||||||
}
|
}
|
||||||
var file_chat_proto_depIdxs = []int32{
|
var file_chat_proto_depIdxs = []int32{
|
||||||
2, // 0: pb.ReqChat.src_user:type_name -> pb.ChatUser
|
2, // 0: pb.ReqChat.srcUser:type_name -> pb.ChatUser
|
||||||
2, // 1: pb.ReqChat.dst_user:type_name -> pb.ChatUser
|
2, // 1: pb.ReqChat.dstUser:type_name -> pb.ChatUser
|
||||||
0, // 2: pb.ReqChat.type:type_name -> pb.ChatType
|
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 output_type
|
||||||
4, // [4:4] is the sub-list for method input_type
|
4, // [4:4] is the sub-list for method input_type
|
||||||
4, // [4:4] is the sub-list for extension type_name
|
4, // [4:4] is the sub-list for extension type_name
|
||||||
|
@ -109,8 +109,8 @@ func (*ReqEnterRoom) Descriptor() ([]byte, []int) {
|
|||||||
type RspEnterRoom struct {
|
type RspEnterRoom struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
|
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
|
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"` // 房间类型,低级,中级,高级等
|
RoomType int32 `protobuf:"varint,3,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -152,9 +152,9 @@ func (x *RspEnterRoom) GetCode() ErrCode {
|
|||||||
return ErrCode_OK
|
return ErrCode_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RspEnterRoom) GetPlayType() int32 {
|
func (x *RspEnterRoom) GetGameId() int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PlayType
|
return x.GameId
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -255,11 +255,11 @@ const file_common_proto_rawDesc = "" +
|
|||||||
"code.proto\"1\n" +
|
"code.proto\"1\n" +
|
||||||
"\x0eNtfKickOutUser\x12\x1f\n" +
|
"\x0eNtfKickOutUser\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\"\x0e\n" +
|
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\"\x0e\n" +
|
||||||
"\fReqEnterRoom\"g\n" +
|
"\fReqEnterRoom\"c\n" +
|
||||||
"\fRspEnterRoom\x12\x1f\n" +
|
"\fRspEnterRoom\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x1a\n" +
|
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x16\n" +
|
||||||
"\bPlayType\x18\x02 \x01(\x05R\bPlayType\x12\x1a\n" +
|
"\x06gameId\x18\x02 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||||
"\bRoomType\x18\x03 \x01(\x05R\bRoomType\"\x0e\n" +
|
"\broomType\x18\x03 \x01(\x05R\broomType\"\x0e\n" +
|
||||||
"\fReqLeaveRoom\"/\n" +
|
"\fReqLeaveRoom\"/\n" +
|
||||||
"\fRspLeaveRoom\x12\x1f\n" +
|
"\fRspLeaveRoom\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04codeB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
"\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
|
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 {
|
type ReqUserLogout struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
@ -212,7 +257,7 @@ type ReqUserLogout struct {
|
|||||||
|
|
||||||
func (x *ReqUserLogout) Reset() {
|
func (x *ReqUserLogout) Reset() {
|
||||||
*x = ReqUserLogout{}
|
*x = ReqUserLogout{}
|
||||||
mi := &file_login_proto_msgTypes[3]
|
mi := &file_login_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -224,7 +269,7 @@ func (x *ReqUserLogout) String() string {
|
|||||||
func (*ReqUserLogout) ProtoMessage() {}
|
func (*ReqUserLogout) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ReqUserLogout) ProtoReflect() protoreflect.Message {
|
func (x *ReqUserLogout) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_login_proto_msgTypes[3]
|
mi := &file_login_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -237,7 +282,7 @@ func (x *ReqUserLogout) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ReqUserLogout.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ReqUserLogout.ProtoReflect.Descriptor instead.
|
||||||
func (*ReqUserLogout) Descriptor() ([]byte, []int) {
|
func (*ReqUserLogout) Descriptor() ([]byte, []int) {
|
||||||
return file_login_proto_rawDescGZIP(), []int{3}
|
return file_login_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
type RspUserLogout struct {
|
type RspUserLogout struct {
|
||||||
@ -249,7 +294,7 @@ type RspUserLogout struct {
|
|||||||
|
|
||||||
func (x *RspUserLogout) Reset() {
|
func (x *RspUserLogout) Reset() {
|
||||||
*x = RspUserLogout{}
|
*x = RspUserLogout{}
|
||||||
mi := &file_login_proto_msgTypes[4]
|
mi := &file_login_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -261,7 +306,7 @@ func (x *RspUserLogout) String() string {
|
|||||||
func (*RspUserLogout) ProtoMessage() {}
|
func (*RspUserLogout) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RspUserLogout) ProtoReflect() protoreflect.Message {
|
func (x *RspUserLogout) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_login_proto_msgTypes[4]
|
mi := &file_login_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -274,7 +319,7 @@ func (x *RspUserLogout) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RspUserLogout.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RspUserLogout.ProtoReflect.Descriptor instead.
|
||||||
func (*RspUserLogout) Descriptor() ([]byte, []int) {
|
func (*RspUserLogout) Descriptor() ([]byte, []int) {
|
||||||
return file_login_proto_rawDescGZIP(), []int{4}
|
return file_login_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RspUserLogout) GetCode() ErrCode {
|
func (x *RspUserLogout) GetCode() ErrCode {
|
||||||
@ -294,7 +339,7 @@ type NtfUserOffline struct {
|
|||||||
|
|
||||||
func (x *NtfUserOffline) Reset() {
|
func (x *NtfUserOffline) Reset() {
|
||||||
*x = NtfUserOffline{}
|
*x = NtfUserOffline{}
|
||||||
mi := &file_login_proto_msgTypes[5]
|
mi := &file_login_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -306,7 +351,7 @@ func (x *NtfUserOffline) String() string {
|
|||||||
func (*NtfUserOffline) ProtoMessage() {}
|
func (*NtfUserOffline) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
|
func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_login_proto_msgTypes[5]
|
mi := &file_login_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -319,7 +364,7 @@ func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use NtfUserOffline.ProtoReflect.Descriptor instead.
|
// Deprecated: Use NtfUserOffline.ProtoReflect.Descriptor instead.
|
||||||
func (*NtfUserOffline) Descriptor() ([]byte, []int) {
|
func (*NtfUserOffline) Descriptor() ([]byte, []int) {
|
||||||
return file_login_proto_rawDescGZIP(), []int{5}
|
return file_login_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NtfUserOffline) GetUserId() int64 {
|
func (x *NtfUserOffline) GetUserId() int64 {
|
||||||
@ -347,7 +392,9 @@ const file_login_proto_rawDesc = "" +
|
|||||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" +
|
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" +
|
||||||
"\x05token\x18\x03 \x01(\tR\x05token\"(\n" +
|
"\x05token\x18\x03 \x01(\tR\x05token\"(\n" +
|
||||||
"\rNtfUserOnline\x12\x17\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" +
|
"\rReqUserLogout\"0\n" +
|
||||||
"\rRspUserLogout\x12\x1f\n" +
|
"\rRspUserLogout\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\")\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
|
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{
|
var file_login_proto_goTypes = []any{
|
||||||
(*ReqUserLogin)(nil), // 0: pb.ReqUserLogin
|
(*ReqUserLogin)(nil), // 0: pb.ReqUserLogin
|
||||||
(*RspUserLogin)(nil), // 1: pb.RspUserLogin
|
(*RspUserLogin)(nil), // 1: pb.RspUserLogin
|
||||||
(*NtfUserOnline)(nil), // 2: pb.NtfUserOnline
|
(*NtfUserOnline)(nil), // 2: pb.NtfUserOnline
|
||||||
(*ReqUserLogout)(nil), // 3: pb.ReqUserLogout
|
(*NtfUserInService)(nil), // 3: pb.NtfUserInService
|
||||||
(*RspUserLogout)(nil), // 4: pb.RspUserLogout
|
(*ReqUserLogout)(nil), // 4: pb.ReqUserLogout
|
||||||
(*NtfUserOffline)(nil), // 5: pb.NtfUserOffline
|
(*RspUserLogout)(nil), // 5: pb.RspUserLogout
|
||||||
(ErrCode)(0), // 6: pb.ErrCode
|
(*NtfUserOffline)(nil), // 6: pb.NtfUserOffline
|
||||||
|
(ErrCode)(0), // 7: pb.ErrCode
|
||||||
}
|
}
|
||||||
var file_login_proto_depIdxs = []int32{
|
var file_login_proto_depIdxs = []int32{
|
||||||
6, // 0: pb.RspUserLogin.code:type_name -> pb.ErrCode
|
7, // 0: pb.RspUserLogin.code:type_name -> pb.ErrCode
|
||||||
6, // 1: pb.RspUserLogout.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 output_type
|
||||||
2, // [2:2] is the sub-list for method input_type
|
2, // [2:2] is the sub-list for method input_type
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
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(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 6,
|
NumMessages: 7,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@ -24,8 +24,8 @@ const (
|
|||||||
// 房间匹配
|
// 房间匹配
|
||||||
type ReqMatchRoom struct {
|
type ReqMatchRoom struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
PlayType int32 `protobuf:"varint,1,opt,name=PlayType,proto3" json:"PlayType,omitempty"` // 玩法id
|
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"` // 房间类型,低级,中级,高级等
|
RoomType int32 `protobuf:"varint,2,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -60,9 +60,9 @@ func (*ReqMatchRoom) Descriptor() ([]byte, []int) {
|
|||||||
return file_match_proto_rawDescGZIP(), []int{0}
|
return file_match_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReqMatchRoom) GetPlayType() int32 {
|
func (x *ReqMatchRoom) GetGameId() int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PlayType
|
return x.GameId
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ func (x *ReqMatchRoom) GetRoomType() int32 {
|
|||||||
type RspMatchRoom struct {
|
type RspMatchRoom struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
|
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
|
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"` // 房间类型,低级,中级,高级等
|
RoomType int32 `protobuf:"varint,3,opt,name=roomType,proto3" json:"roomType,omitempty"` // 房间类型,低级,中级,高级等
|
||||||
User *GameUser `protobuf:"bytes,4,opt,name=User,proto3" json:"User,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玩法配置信息
|
ColorInfo *RspMatchRoom_ColorInfo `protobuf:"bytes,20,opt,name=colorInfo,proto3" json:"colorInfo,omitempty"` // color玩法配置信息
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
@ -123,9 +123,9 @@ func (x *RspMatchRoom) GetCode() ErrCode {
|
|||||||
return ErrCode_OK
|
return ErrCode_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RspMatchRoom) GetPlayType() int32 {
|
func (x *RspMatchRoom) GetGameId() int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PlayType
|
return x.GameId
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -238,14 +238,14 @@ const file_match_proto_rawDesc = "" +
|
|||||||
"\n" +
|
"\n" +
|
||||||
"\vmatch.proto\x12\x02pb\x1a\n" +
|
"\vmatch.proto\x12\x02pb\x1a\n" +
|
||||||
"code.proto\x1a\n" +
|
"code.proto\x1a\n" +
|
||||||
"user.proto\"F\n" +
|
"user.proto\"B\n" +
|
||||||
"\fReqMatchRoom\x12\x1a\n" +
|
"\fReqMatchRoom\x12\x16\n" +
|
||||||
"\bPlayType\x18\x01 \x01(\x05R\bPlayType\x12\x1a\n" +
|
"\x06gameId\x18\x01 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||||
"\bRoomType\x18\x02 \x01(\x05R\bRoomType\"\xd0\x01\n" +
|
"\broomType\x18\x02 \x01(\x05R\broomType\"\xcc\x01\n" +
|
||||||
"\fRspMatchRoom\x12\x1f\n" +
|
"\fRspMatchRoom\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x1a\n" +
|
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x16\n" +
|
||||||
"\bPlayType\x18\x02 \x01(\x05R\bPlayType\x12\x1a\n" +
|
"\x06gameId\x18\x02 \x01(\x05R\x06gameId\x12\x1a\n" +
|
||||||
"\bRoomType\x18\x03 \x01(\x05R\bRoomType\x12 \n" +
|
"\broomType\x18\x03 \x01(\x05R\broomType\x12 \n" +
|
||||||
"\x04User\x18\x04 \x01(\v2\f.pb.GameUserR\x04User\x128\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\x18\x14 \x01(\v2\x1a.pb.RspMatchRoom.ColorInfoR\tcolorInfo\x1a\v\n" +
|
||||||
"\tColorInfo\"7\n" +
|
"\tColorInfo\"7\n" +
|
||||||
|
@ -42,6 +42,7 @@ const (
|
|||||||
MsgId_ReqUserLoginId MsgId = 2100 // 玩家登陆
|
MsgId_ReqUserLoginId MsgId = 2100 // 玩家登陆
|
||||||
MsgId_RspUserLoginId MsgId = 2101
|
MsgId_RspUserLoginId MsgId = 2101
|
||||||
MsgId_NtfUserOnlineId MsgId = 2102
|
MsgId_NtfUserOnlineId MsgId = 2102
|
||||||
|
MsgId_NtfUserInServiceId MsgId = 2103 // 将玩家之前呆的服务同步给玩家,方便玩家重连进来
|
||||||
MsgId_ReqUserLogoutId MsgId = 2104
|
MsgId_ReqUserLogoutId MsgId = 2104
|
||||||
MsgId_RspUserLogoutId MsgId = 2105
|
MsgId_RspUserLogoutId MsgId = 2105
|
||||||
MsgId_NtfUserOfflineId MsgId = 2106
|
MsgId_NtfUserOfflineId MsgId = 2106
|
||||||
@ -78,6 +79,7 @@ var (
|
|||||||
2100: "ReqUserLoginId",
|
2100: "ReqUserLoginId",
|
||||||
2101: "RspUserLoginId",
|
2101: "RspUserLoginId",
|
||||||
2102: "NtfUserOnlineId",
|
2102: "NtfUserOnlineId",
|
||||||
|
2103: "NtfUserInServiceId",
|
||||||
2104: "ReqUserLogoutId",
|
2104: "ReqUserLogoutId",
|
||||||
2105: "RspUserLogoutId",
|
2105: "RspUserLogoutId",
|
||||||
2106: "NtfUserOfflineId",
|
2106: "NtfUserOfflineId",
|
||||||
@ -109,6 +111,7 @@ var (
|
|||||||
"ReqUserLoginId": 2100,
|
"ReqUserLoginId": 2100,
|
||||||
"RspUserLoginId": 2101,
|
"RspUserLoginId": 2101,
|
||||||
"NtfUserOnlineId": 2102,
|
"NtfUserOnlineId": 2102,
|
||||||
|
"NtfUserInServiceId": 2103,
|
||||||
"ReqUserLogoutId": 2104,
|
"ReqUserLogoutId": 2104,
|
||||||
"RspUserLogoutId": 2105,
|
"RspUserLogoutId": 2105,
|
||||||
"NtfUserOfflineId": 2106,
|
"NtfUserOfflineId": 2106,
|
||||||
@ -160,7 +163,7 @@ var File_msgId_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_msgId_proto_rawDesc = "" +
|
const file_msgId_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\vmsgId.proto\x12\x02pb*\x91\x05\n" +
|
"\vmsgId.proto\x12\x02pb*\xaa\x05\n" +
|
||||||
"\x05MsgId\x12\x0e\n" +
|
"\x05MsgId\x12\x0e\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"MI_Unknown\x10\x00\x12\x12\n" +
|
"MI_Unknown\x10\x00\x12\x12\n" +
|
||||||
@ -174,7 +177,8 @@ const file_msgId_proto_rawDesc = "" +
|
|||||||
"\tRspChatId\x10\xd1\x0f\x12\x13\n" +
|
"\tRspChatId\x10\xd1\x0f\x12\x13\n" +
|
||||||
"\x0eReqUserLoginId\x10\xb4\x10\x12\x13\n" +
|
"\x0eReqUserLoginId\x10\xb4\x10\x12\x13\n" +
|
||||||
"\x0eRspUserLoginId\x10\xb5\x10\x12\x14\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" +
|
"\x0fReqUserLogoutId\x10\xb8\x10\x12\x14\n" +
|
||||||
"\x0fRspUserLogoutId\x10\xb9\x10\x12\x15\n" +
|
"\x0fRspUserLogoutId\x10\xb9\x10\x12\x15\n" +
|
||||||
"\x10NtfUserOfflineId\x10\xba\x10\x12\x13\n" +
|
"\x10NtfUserOfflineId\x10\xba\x10\x12\x13\n" +
|
||||||
|
@ -30,6 +30,7 @@ const (
|
|||||||
ServiceTypeId_STI_Chat ServiceTypeId = 102 // 聊天服
|
ServiceTypeId_STI_Chat ServiceTypeId = 102 // 聊天服
|
||||||
ServiceTypeId_STI_DB ServiceTypeId = 103 // db服
|
ServiceTypeId_STI_DB ServiceTypeId = 103 // db服
|
||||||
ServiceTypeId_STI_Match ServiceTypeId = 104 // 匹配服
|
ServiceTypeId_STI_Match ServiceTypeId = 104 // 匹配服
|
||||||
|
ServiceTypeId_STI_Lobby ServiceTypeId = 105 // 大厅服
|
||||||
ServiceTypeId_STI_ColorGame ServiceTypeId = 120 // color game
|
ServiceTypeId_STI_ColorGame ServiceTypeId = 120 // color game
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ var (
|
|||||||
102: "STI_Chat",
|
102: "STI_Chat",
|
||||||
103: "STI_DB",
|
103: "STI_DB",
|
||||||
104: "STI_Match",
|
104: "STI_Match",
|
||||||
|
105: "STI_Lobby",
|
||||||
120: "STI_ColorGame",
|
120: "STI_ColorGame",
|
||||||
}
|
}
|
||||||
ServiceTypeId_value = map[string]int32{
|
ServiceTypeId_value = map[string]int32{
|
||||||
@ -51,6 +53,7 @@ var (
|
|||||||
"STI_Chat": 102,
|
"STI_Chat": 102,
|
||||||
"STI_DB": 103,
|
"STI_DB": 103,
|
||||||
"STI_Match": 104,
|
"STI_Match": 104,
|
||||||
|
"STI_Lobby": 105,
|
||||||
"STI_ColorGame": 120,
|
"STI_ColorGame": 120,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -86,7 +89,7 @@ var File_service_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_service_proto_rawDesc = "" +
|
const file_service_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\rservice.proto\x12\x02pb*y\n" +
|
"\rservice.proto\x12\x02pb*\x88\x01\n" +
|
||||||
"\rServiceTypeId\x12\x0f\n" +
|
"\rServiceTypeId\x12\x0f\n" +
|
||||||
"\vSTI_Unknown\x10\x00\x12\f\n" +
|
"\vSTI_Unknown\x10\x00\x12\f\n" +
|
||||||
"\bSTI_Gate\x10d\x12\r\n" +
|
"\bSTI_Gate\x10d\x12\r\n" +
|
||||||
@ -94,7 +97,8 @@ const file_service_proto_rawDesc = "" +
|
|||||||
"\bSTI_Chat\x10f\x12\n" +
|
"\bSTI_Chat\x10f\x12\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x06STI_DB\x10g\x12\r\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"
|
"\rSTI_ColorGame\x10xB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -24,11 +24,11 @@ const (
|
|||||||
// 聊天中显示的玩家基础信息
|
// 聊天中显示的玩家基础信息
|
||||||
type ChatUser struct {
|
type ChatUser struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
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"` // 昵称
|
Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` // 昵称
|
||||||
Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,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"` // 头像框
|
AvatarFrame string `protobuf:"bytes,4,opt,name=avatarFrame,proto3" json:"avatarFrame,omitempty"` // 头像框
|
||||||
VipLevel string `protobuf:"bytes,5,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` // vip等级
|
VipLevel string `protobuf:"bytes,5,opt,name=vipLevel,proto3" json:"vipLevel,omitempty"` // vip等级
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -101,12 +101,12 @@ func (x *ChatUser) GetVipLevel() string {
|
|||||||
// 房间内的玩家数据
|
// 房间内的玩家数据
|
||||||
type GameUser struct {
|
type GameUser struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
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"` // 昵称
|
Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` // 昵称
|
||||||
Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,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"` // 头像框
|
AvatarFrame string `protobuf:"bytes,4,opt,name=avatarFrame,proto3" json:"avatarFrame,omitempty"` // 头像框
|
||||||
VipLevel int32 `protobuf:"varint,5,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` // vip等级
|
VipLevel int32 `protobuf:"varint,5,opt,name=vipLevel,proto3" json:"vipLevel,omitempty"` // vip等级
|
||||||
VipExp int32 `protobuf:"varint,6,opt,name=vip_exp,json=vipExp,proto3" json:"vip_exp,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"` // 座位
|
Seat int64 `protobuf:"varint,20,opt,name=seat,proto3" json:"seat,omitempty"` // 座位
|
||||||
Gold int64 `protobuf:"varint,25,opt,name=gold,proto3" json:"gold,omitempty"` // 金币
|
Gold int64 `protobuf:"varint,25,opt,name=gold,proto3" json:"gold,omitempty"` // 金币
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
@ -204,20 +204,20 @@ var File_user_proto protoreflect.FileDescriptor
|
|||||||
const file_user_proto_rawDesc = "" +
|
const file_user_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"user.proto\x12\x02pb\"\x97\x01\n" +
|
"user.proto\x12\x02pb\"\x94\x01\n" +
|
||||||
"\bChatUser\x12\x17\n" +
|
"\bChatUser\x12\x16\n" +
|
||||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
"\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||||
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
||||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12!\n" +
|
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12 \n" +
|
||||||
"\favatar_frame\x18\x04 \x01(\tR\vavatarFrame\x12\x1b\n" +
|
"\vavatarFrame\x18\x04 \x01(\tR\vavatarFrame\x12\x1a\n" +
|
||||||
"\tvip_level\x18\x05 \x01(\tR\bvipLevel\"\xd8\x01\n" +
|
"\bvipLevel\x18\x05 \x01(\tR\bvipLevel\"\xd4\x01\n" +
|
||||||
"\bGameUser\x12\x17\n" +
|
"\bGameUser\x12\x16\n" +
|
||||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
"\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||||
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
"\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" +
|
||||||
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12!\n" +
|
"\x06avatar\x18\x03 \x01(\tR\x06avatar\x12 \n" +
|
||||||
"\favatar_frame\x18\x04 \x01(\tR\vavatarFrame\x12\x1b\n" +
|
"\vavatarFrame\x18\x04 \x01(\tR\vavatarFrame\x12\x1a\n" +
|
||||||
"\tvip_level\x18\x05 \x01(\x05R\bvipLevel\x12\x17\n" +
|
"\bvipLevel\x18\x05 \x01(\x05R\bvipLevel\x12\x16\n" +
|
||||||
"\avip_exp\x18\x06 \x01(\x05R\x06vipExp\x12\x12\n" +
|
"\x06vipExp\x18\x06 \x01(\x05R\x06vipExp\x12\x12\n" +
|
||||||
"\x04seat\x18\x14 \x01(\x03R\x04seat\x12\x12\n" +
|
"\x04seat\x18\x14 \x01(\x03R\x04seat\x12\x12\n" +
|
||||||
"\x04gold\x18\x19 \x01(\x03R\x04goldB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
"\x04gold\x18\x19 \x01(\x03R\x04goldB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ const (
|
|||||||
Login = "login"
|
Login = "login"
|
||||||
Db = "db"
|
Db = "db"
|
||||||
Match = "match"
|
Match = "match"
|
||||||
|
Lobby = "lobby"
|
||||||
|
|
||||||
// 下面是具体玩法服
|
// 下面是具体玩法服
|
||||||
ColorGame = "color_game"
|
ColorGame = "color_game"
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"game/common/utils"
|
"game/common/utils"
|
||||||
"github.com/fox/fox/etcd"
|
"github.com/fox/fox/etcd"
|
||||||
"github.com/fox/fox/log"
|
"github.com/fox/fox/log"
|
||||||
"github.com/fox/fox/service"
|
|
||||||
"github.com/fox/fox/xrand"
|
"github.com/fox/fox/xrand"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"time"
|
"time"
|
||||||
@ -24,6 +23,14 @@ const (
|
|||||||
客户端没有指定路由节点,则服务器从redis查找曾经的绑定节点,并验证有效然后转发到对应的节点。
|
客户端没有指定路由节点,则服务器从redis查找曾经的绑定节点,并验证有效然后转发到对应的节点。
|
||||||
如果redis信息已经失效(服务有更新),则从etcd中获取该玩法下所有最新版本的节点(game1,game2),然后随机发送到其中一个节点,并在redis中保存绑定关系。
|
如果redis信息已经失效(服务有更新),则从etcd中获取该玩法下所有最新版本的节点(game1,game2),然后随机发送到其中一个节点,并在redis中保存绑定关系。
|
||||||
如果客户端所有消息都不指定具体的节点名,则每次都需要从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 {
|
type UserBindService struct {
|
||||||
rdb *redis.Client
|
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 {
|
func (m *UserBindService) makeRedisKey(userId int64) string {
|
||||||
return fmt.Sprintf("%s_%d:%d", prefix, userId, int(typeId))
|
return fmt.Sprintf("%s:%s", prefix, userId)
|
||||||
|
}
|
||||||
|
func (m *UserBindService) makeRedisSubKey(typeId pb.ServiceTypeId) string {
|
||||||
|
return typeId.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从redis中加载玩家曾经访问过的服务节点名
|
// 从redis中加载玩家曾经访问过的服务节点名
|
||||||
func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) string {
|
func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) string {
|
||||||
k := m.makeRedisKey(userId, typeId)
|
key := m.makeRedisKey(userId)
|
||||||
if sName, err := m.rdb.Get(context.Background(), k).Result(); err != nil {
|
subKey := m.makeRedisSubKey(typeId)
|
||||||
|
if sName, err := m.rdb.HGet(context.Background(), key, subKey).Result(); err != nil {
|
||||||
if !errors.Is(err, redis.Nil) {
|
if !errors.Is(err, redis.Nil) {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
}
|
}
|
||||||
@ -56,24 +67,34 @@ func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) s
|
|||||||
|
|
||||||
// 从redis中解除玩家与节点的绑定关系
|
// 从redis中解除玩家与节点的绑定关系
|
||||||
func (m *UserBindService) DelUserService(userId int64, typeId pb.ServiceTypeId) {
|
func (m *UserBindService) DelUserService(userId int64, typeId pb.ServiceTypeId) {
|
||||||
k := m.makeRedisKey(userId, typeId)
|
key := m.makeRedisKey(userId)
|
||||||
_, _ = m.rdb.Del(context.Background(), k).Result()
|
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(新服),都算有效,但是旧服会拒绝新玩家进入,
|
// 从etcd中检查节点是否有效,如果有game1(旧服),game2(新服),都算有效,但是旧服会拒绝新玩家进入,
|
||||||
// 此时旧服不止要拒绝新玩家,还要删除redis中的绑定关系。方便客户端重新发消息时路由到新的服务。
|
// 此时旧服不止要拒绝新玩家,还要删除redis中的绑定关系。方便客户端重新发消息时路由到新的服务。
|
||||||
func (m *UserBindService) serviceIsValid(serviceName string) bool {
|
func (m *UserBindService) findServiceNodeByServiceName(serviceName string) (*etcd.ServiceNode, bool) {
|
||||||
|
var sNode *etcd.ServiceNode
|
||||||
valid := false
|
valid := false
|
||||||
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
||||||
if node, ok := v.(etcd.ServiceNode); ok {
|
if node, ok := v.(etcd.ServiceNode); ok {
|
||||||
if node.Name == serviceName {
|
if node.Name == serviceName {
|
||||||
valid = true
|
valid = true
|
||||||
|
sNode = &node
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return valid
|
return sNode, valid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserBindService) stringAllServiceNode() string {
|
func (m *UserBindService) stringAllServiceNode() string {
|
||||||
@ -86,7 +107,7 @@ func (m *UserBindService) stringAllServiceNode() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从etcd中找可用服务节点随机选择一个
|
// 从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 nodes []etcd.ServiceNode
|
||||||
var version string
|
var version string
|
||||||
m.etcdRegistry.GetNodes().Range(func(_, value any) bool {
|
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 {
|
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())
|
||||||
}
|
}
|
||||||
n := xrand.IntN(len(nodes))
|
n := xrand.RandN(len(nodes))
|
||||||
return &nodes[n], nil
|
return &nodes[n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据服务类型,路由到对应的服务节点
|
// 从etcd中hash一个服务节点。不需要保存玩家在哪个服务。
|
||||||
func (m *UserBindService) findServiceName(userId int64, typeId pb.ServiceTypeId) (string, error) {
|
// 该服务是类似于db服这种有序操作的hash服
|
||||||
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一个服务节点
|
|
||||||
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 []etcd.ServiceNode
|
||||||
var version string
|
var version string
|
||||||
@ -176,3 +162,51 @@ func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*
|
|||||||
n := uid % int64(len(nodes))
|
n := uid % int64(len(nodes))
|
||||||
return &nodes[n], nil
|
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 (
|
import (
|
||||||
"game/common/proto/pb"
|
"game/common/proto/pb"
|
||||||
|
"game/common/userBindService"
|
||||||
|
"game/server/colorgame/model"
|
||||||
"github.com/fox/fox/ipb"
|
"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) {
|
func (rm *ColorRoom) leaveRoom(user *ColorPlayer) {
|
||||||
rm.DelPlayer(user.Id())
|
rm.DelPlayer(user.Id())
|
||||||
rm.userMgr.Del(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) {
|
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) {
|
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{
|
rm := &ColorRoom{
|
||||||
HundredRoom: nil,
|
HundredRoom: nil,
|
||||||
userMgr: userMgr,
|
userMgr: userMgr,
|
||||||
@ -44,13 +44,13 @@ func newColorRoom(id, roomType int, srv service.IService, userMgr *baseroom.Play
|
|||||||
jackpotValue: 0,
|
jackpotValue: 0,
|
||||||
endBetAreaMul: make([]*pb.ColorBetAreaMul, 0, len(pb.ColorBetArea_name)),
|
endBetAreaMul: make([]*pb.ColorBetAreaMul, 0, len(pb.ColorBetArea_name)),
|
||||||
winBetAreaMul: nil,
|
winBetAreaMul: nil,
|
||||||
jackpotMgr: jackpot.NewJackpotMgr(playType, model.UserRedis),
|
jackpotMgr: jackpot.NewJackpotMgr(gameId, model.UserRedis),
|
||||||
}
|
}
|
||||||
rm.trend = rm.initGameTrend()
|
rm.trend = rm.initGameTrend()
|
||||||
rm.resetGameData()
|
rm.resetGameData()
|
||||||
|
|
||||||
code := pb.ErrCode_OK
|
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 {
|
if code != pb.ErrCode_OK {
|
||||||
log.ErrorF("new color room err code:%v", code)
|
log.ErrorF("new color room err code:%v", code)
|
||||||
return nil, 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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"game/server/lobby/cmd"
|
||||||
"game/server/hilo/cmd"
|
|
||||||
"github.com/fox/fox/ksync"
|
"github.com/fox/fox/ksync"
|
||||||
"github.com/fox/fox/log"
|
"github.com/fox/fox/log"
|
||||||
"time"
|
"time"
|
||||||
@ -19,7 +18,8 @@ func main() {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
BuildDate = tm.Format("2006-01-02 15:04:05")
|
BuildDate = tm.Format("2006-01-02 15:04:05")
|
||||||
}
|
}
|
||||||
|
//BuildDate = "2025-05-31 09:56:06"
|
||||||
ksync.RunSafe(func() {
|
ksync.RunSafe(func() {
|
||||||
cmd.Run(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
|
cmd.Run(GitBranch, GitCommit, BuildDate)
|
||||||
}, func() { log.Debug("reset run") })
|
}, 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/log"
|
||||||
"github.com/fox/fox/processor"
|
"github.com/fox/fox/processor"
|
||||||
"github.com/fox/fox/service"
|
"github.com/fox/fox/service"
|
||||||
|
"github.com/fox/fox/xrand"
|
||||||
"time"
|
"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) {
|
func (s *LoginService) checkLoginOrRegister(req *pb.ReqUserLogin) (us *user.UserAccount, code pb.ErrCode, node *etcd.ServiceNode) {
|
||||||
var err error
|
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 {
|
if err != nil {
|
||||||
log.ErrorF(s.Log("not find db service.err:%s ", err.Error()))
|
log.ErrorF(s.Log("not find db service.err:%s ", err.Error()))
|
||||||
return nil, pb.ErrCode_SystemErr, node
|
return nil, pb.ErrCode_SystemErr, node
|
||||||
|
@ -15,10 +15,10 @@ import (
|
|||||||
func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom) {
|
func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom) {
|
||||||
ksync.GoSafe(func() {
|
ksync.GoSafe(func() {
|
||||||
// color game无需进入匹配队列
|
// color game无需进入匹配队列
|
||||||
playType := pb.ServiceTypeId(req.PlayType)
|
gameId := pb.ServiceTypeId(req.GameId)
|
||||||
switch playType {
|
switch gameId {
|
||||||
case pb.ServiceTypeId_STI_ColorGame:
|
case pb.ServiceTypeId_STI_ColorGame:
|
||||||
node, err := s.bindService.RandServiceNode(playType)
|
node, err := s.bindService.FindServiceNode(iMsg.UserId, gameId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorF("db service node error:%v", err)
|
log.ErrorF("db service node error:%v", err)
|
||||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, iMsg.UserId,
|
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,
|
Seat: 0,
|
||||||
Gold: us.Gold,
|
Gold: us.Gold,
|
||||||
}
|
}
|
||||||
rsp.PlayType = req.PlayType
|
rsp.GameId = req.GameId
|
||||||
rsp.RoomType = req.RoomType
|
rsp.RoomType = req.RoomType
|
||||||
switch pb.ServiceTypeId(rsp.PlayType) {
|
switch pb.ServiceTypeId(rsp.GameId) {
|
||||||
case pb.ServiceTypeId_STI_ColorGame:
|
case pb.ServiceTypeId_STI_ColorGame:
|
||||||
rsp.ColorInfo = &pb.RspMatchRoom_ColorInfo{}
|
rsp.ColorInfo = &pb.RspMatchRoom_ColorInfo{}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user