聊天服,提供私聊及世界频道聊天

This commit is contained in:
liuxiaobo 2025-05-28 20:19:11 +08:00
parent f96715acdf
commit ae28cbb0e8
31 changed files with 1153 additions and 387 deletions

View File

@ -1,5 +1,6 @@
package config
// Common中只有Special会动态更新Special是各类服务自己需要及时更新的配置信息
type Common[T any] struct {
ServiceType int `json:"service_type"`
Logger Logger `json:"logger"`
@ -7,6 +8,9 @@ type Common[T any] struct {
Redis Redis `json:"redis"`
Nats Nats `json:"nats"`
Special *T `json:"special"`
GitCommit string `json:"git_commit"` // 服务当前的hash值
GitBranch string `json:"git_branch"` // 服务当前的版本分支
BuildDate string `json:"build_date"` // 服务构建时间用作version
}
type Logger struct {

View File

@ -44,10 +44,13 @@ type resultT[T any] struct {
Err error
}
func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) {
func LoadCommonConfig[T any](rd *redis.Client, GitCommit, GitBranch, BuildDate string) (*Common[T], error) {
var ret resultT[T]
var comm Common[T]
comm.Special = &ret.Value
comm.GitCommit = GitCommit
comm.GitBranch = GitBranch
comm.BuildDate = BuildDate
// 初始化etcd
s, err := rd.Get(context.Background(), etcdKey).Result()
if err != nil && !errors.Is(err, redis.Nil) {
@ -102,12 +105,16 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) {
return &comm, nil
}
/*
所有配置信息都存放在redis中程序启动会给配置信息的redis地址
连上后从该redis中读取所有其它的配置信息如mysqletcdnats以及玩法相关的如房间配置等信息
*/
type Command struct {
RedisHost string
RedisPort string
RedisPassword string
ServiceId int
ServiceNum int
ServiceId int // 起始服务id
ServiceNum int // 服务数量
VMod string // 区分测试服,开发服
}

View File

@ -11,19 +11,11 @@ enum MsgId
message InternalMsg
{
uint32 conn_id = 1; // user_idconn_id
int64 user_id = 2; // id
int32 msg_id = 3; // id
bytes msg = 4; //
}
//
message C2SMessage
{
int32 service_type = 1; // lobby,game,chat等内部服务
int32 msg_id = 2; // id
int32 service_name = 1; //
uint32 conn_id = 2; // user_idconn_id
int64 user_id = 3; // id
bytes msg = 4; //
int32 msg_id = 4; // id
bytes msg = 5; //
}

29
common/pb/chat.proto Normal file
View File

@ -0,0 +1,29 @@
syntax = "proto3";
package pb;
option go_package = "common/proto/pb";
import "user.proto";
import "service.proto";
//
enum ChatType
{
CT_Unknown = 0;
CT_Private = 1; //
CT_World = 2; //
CT_Marquee = 3; //
}
//
message C2SChat
{
ChatUser src_user = 1; //
ChatUser dst_user = 2; //
ChatType type = 3; //
ServiceTypeId game_id = 4; // id
string content = 5; //
}

View File

@ -8,9 +8,10 @@ import "service.proto";
message ClientMsg
{
ServiceTypeId service_tid = 1; // id
string sub_service_name = 2; // ()
int32 msg_id = 3; // id
bytes data = 4; //
string service_name = 2; // ()
int64 user_id = 3; // id
int32 msg_id = 4; // id
bytes data = 5; //
}

View File

@ -4,8 +4,8 @@ option go_package = "common/proto/pb";
enum ErrCode
{
EC_OK = 0;
EC_LoginDiffLoc = 1; //
OK = 0;
LoginDiffLoc = 1; //
}

View File

@ -4,28 +4,15 @@ option go_package = "common/proto/pb";
import "code.proto";
enum LoginMsgId
{
Unknown = 0;
C2SUserLogin = 1; //
S2CUserLogin = 2;
NtfUserOnline = 3;
C2SUserLogout = 4;
S2CUserLogout = 5;
NtfUserOffline = 6;
}
//
message C2SUserLoginMsg
message C2SUserLogin
{
string username = 1; //
string token = 2; // token
string version = 3; //
}
message S2CUserLoginMsg
message S2CUserLogin
{
ErrCode code = 1;
int64 user_id = 2;
@ -33,24 +20,24 @@ message S2CUserLoginMsg
}
// 线
message NtfUserOnlineMsg
message NtfUserOnline
{
int64 user_id = 2; // id
}
//
message C2SUserLogoutMsg
message C2SUserLogout
{
}
message S2CUserLogoutMsg
message S2CUserLogout
{
ErrCode code = 1; //
}
// 线
message NtfUserOfflineMsg
message NtfUserOffline
{
int64 user_id = 2; // id
}

27
common/pb/msgId.proto Normal file
View File

@ -0,0 +1,27 @@
syntax = "proto3";
package pb;
option go_package = "common/proto/pb";
/*
:
1. id都在msgId.proto的MsgId中定义C2S,S2C,Ntf三种之一Id
2. code.proto的ErrCode中定义
3. id去掉后缀Id组成
*/
enum MsgId
{
MI_Unknown = 0;
// 2000-2100
C2SChatId = 2000; //
S2CChatId = 2001; // C2SChatMsg
// 2100-2200
C2SUserLoginId = 2100; //
S2CUserLoginId = 2101;
NtfUserOnlineId = 2102;
C2SUserLogoutId = 2104;
S2CUserLogoutId = 2105;
NtfUserOfflineId = 2106;
}

View File

@ -5,8 +5,9 @@ option go_package = "common/proto/pb";
enum ServiceTypeId
{
STI_Unknown = 0;
STI_Gate = 1000; // id
STI_Login = 1001; //
STI_Gate = 100; // id
STI_Login = 101; //
STI_Chat = 102; //
}

17
common/pb/user.proto Normal file
View File

@ -0,0 +1,17 @@
syntax = "proto3";
package pb;
option go_package = "common/proto/pb";
//
message ChatUser
{
int64 user_id = 1;
string nickname = 2; //
string avatar = 3; //
string avatar_frame = 4; //
string vip_level = 5; // vip等级
}

View File

@ -69,10 +69,11 @@ func (MsgId) EnumDescriptor() ([]byte, []int) {
type InternalMsg struct {
state protoimpl.MessageState `protogen:"open.v1"`
ConnId uint32 `protobuf:"varint,1,opt,name=conn_id,json=connId,proto3" json:"conn_id,omitempty"` // 刚登陆时没有user_id只有conn_id
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
MsgId int32 `protobuf:"varint,3,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id
Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` // 消息
ServiceName int32 `protobuf:"varint,1,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` // 该服务类型下的具体的服务节点名,需要保证该消息是该服务节点发的。否则可能会导致客户端出现路由错误
ConnId uint32 `protobuf:"varint,2,opt,name=conn_id,json=connId,proto3" json:"conn_id,omitempty"` // 刚登陆时没有user_id只有conn_id
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
MsgId int32 `protobuf:"varint,4,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id
Msg []byte `protobuf:"bytes,5,opt,name=msg,proto3" json:"msg,omitempty"` // 消息
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -107,6 +108,13 @@ func (*InternalMsg) Descriptor() ([]byte, []int) {
return file_internal_proto_rawDescGZIP(), []int{0}
}
func (x *InternalMsg) GetServiceName() int32 {
if x != nil {
return x.ServiceName
}
return 0
}
func (x *InternalMsg) GetConnId() uint32 {
if x != nil {
return x.ConnId
@ -135,91 +143,17 @@ func (x *InternalMsg) GetMsg() []byte {
return nil
}
// 网关解包客户端消息
type C2SMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
ServiceType int32 `protobuf:"varint,1,opt,name=service_type,json=serviceType,proto3" json:"service_type,omitempty"` // 服务类型通过该值判断发往lobby,game,chat等内部服务
MsgId int32 `protobuf:"varint,2,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` // 消息
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *C2SMessage) Reset() {
*x = C2SMessage{}
mi := &file_internal_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *C2SMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*C2SMessage) ProtoMessage() {}
func (x *C2SMessage) ProtoReflect() protoreflect.Message {
mi := &file_internal_proto_msgTypes[1]
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 C2SMessage.ProtoReflect.Descriptor instead.
func (*C2SMessage) Descriptor() ([]byte, []int) {
return file_internal_proto_rawDescGZIP(), []int{1}
}
func (x *C2SMessage) GetServiceType() int32 {
if x != nil {
return x.ServiceType
}
return 0
}
func (x *C2SMessage) GetMsgId() int32 {
if x != nil {
return x.MsgId
}
return 0
}
func (x *C2SMessage) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
func (x *C2SMessage) GetMsg() []byte {
if x != nil {
return x.Msg
}
return nil
}
var File_internal_proto protoreflect.FileDescriptor
const file_internal_proto_rawDesc = "" +
"\n" +
"\x0einternal.proto\x12\x03ipb\"h\n" +
"\vInternalMsg\x12\x17\n" +
"\aconn_id\x18\x01 \x01(\rR\x06connId\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x15\n" +
"\x06msg_id\x18\x03 \x01(\x05R\x05msgId\x12\x10\n" +
"\x03msg\x18\x04 \x01(\fR\x03msg\"q\n" +
"\n" +
"C2SMessage\x12!\n" +
"\fservice_type\x18\x01 \x01(\x05R\vserviceType\x12\x15\n" +
"\x06msg_id\x18\x02 \x01(\x05R\x05msgId\x12\x17\n" +
"\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x10\n" +
"\x03msg\x18\x04 \x01(\fR\x03msg*+\n" +
"\x0einternal.proto\x12\x03ipb\"\x8b\x01\n" +
"\vInternalMsg\x12!\n" +
"\fservice_name\x18\x01 \x01(\x05R\vserviceName\x12\x17\n" +
"\aconn_id\x18\x02 \x01(\rR\x06connId\x12\x17\n" +
"\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x15\n" +
"\x06msg_id\x18\x04 \x01(\x05R\x05msgId\x12\x10\n" +
"\x03msg\x18\x05 \x01(\fR\x03msg*+\n" +
"\x05MsgId\x12\v\n" +
"\aUnknown\x10\x00\x12\x15\n" +
"\bInternal\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01B\x12Z\x10common/proto/ipbb\x06proto3"
@ -237,11 +171,10 @@ func file_internal_proto_rawDescGZIP() []byte {
}
var file_internal_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_internal_proto_goTypes = []any{
(MsgId)(0), // 0: ipb.MsgId
(*InternalMsg)(nil), // 1: ipb.InternalMsg
(*C2SMessage)(nil), // 2: ipb.C2SMessage
}
var file_internal_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
@ -262,7 +195,7 @@ func file_internal_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_proto_rawDesc), len(file_internal_proto_rawDesc)),
NumEnums: 1,
NumMessages: 2,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},

233
common/proto/pb/chat.pb.go Normal file
View File

@ -0,0 +1,233 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc v6.31.0
// source: chat.proto
package pb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// 聊天类型
type ChatType int32
const (
ChatType_CT_Unknown ChatType = 0
ChatType_CT_Private ChatType = 1 // 私聊,一对一
ChatType_CT_World ChatType = 2 // 世界频道聊天
ChatType_CT_Marquee ChatType = 3 // 跑马灯,滚动信息
)
// Enum value maps for ChatType.
var (
ChatType_name = map[int32]string{
0: "CT_Unknown",
1: "CT_Private",
2: "CT_World",
3: "CT_Marquee",
}
ChatType_value = map[string]int32{
"CT_Unknown": 0,
"CT_Private": 1,
"CT_World": 2,
"CT_Marquee": 3,
}
)
func (x ChatType) Enum() *ChatType {
p := new(ChatType)
*p = x
return p
}
func (x ChatType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ChatType) Descriptor() protoreflect.EnumDescriptor {
return file_chat_proto_enumTypes[0].Descriptor()
}
func (ChatType) Type() protoreflect.EnumType {
return &file_chat_proto_enumTypes[0]
}
func (x ChatType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ChatType.Descriptor instead.
func (ChatType) EnumDescriptor() ([]byte, []int) {
return file_chat_proto_rawDescGZIP(), []int{0}
}
// 聊天消息
type C2SChat 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"` // 接收者
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只在本玩法中显示的聊天信息
Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` // 内容
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *C2SChat) Reset() {
*x = C2SChat{}
mi := &file_chat_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *C2SChat) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*C2SChat) ProtoMessage() {}
func (x *C2SChat) ProtoReflect() protoreflect.Message {
mi := &file_chat_proto_msgTypes[0]
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 C2SChat.ProtoReflect.Descriptor instead.
func (*C2SChat) Descriptor() ([]byte, []int) {
return file_chat_proto_rawDescGZIP(), []int{0}
}
func (x *C2SChat) GetSrcUser() *ChatUser {
if x != nil {
return x.SrcUser
}
return nil
}
func (x *C2SChat) GetDstUser() *ChatUser {
if x != nil {
return x.DstUser
}
return nil
}
func (x *C2SChat) GetType() ChatType {
if x != nil {
return x.Type
}
return ChatType_CT_Unknown
}
func (x *C2SChat) GetGameId() ServiceTypeId {
if x != nil {
return x.GameId
}
return ServiceTypeId_STI_Unknown
}
func (x *C2SChat) GetContent() string {
if x != nil {
return x.Content
}
return ""
}
var File_chat_proto protoreflect.FileDescriptor
const file_chat_proto_rawDesc = "" +
"\n" +
"\n" +
"chat.proto\x12\x02pb\x1a\n" +
"user.proto\x1a\rservice.proto\"\xc3\x01\n" +
"\aC2SChat\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" +
"\acontent\x18\x05 \x01(\tR\acontent*H\n" +
"\bChatType\x12\x0e\n" +
"\n" +
"CT_Unknown\x10\x00\x12\x0e\n" +
"\n" +
"CT_Private\x10\x01\x12\f\n" +
"\bCT_World\x10\x02\x12\x0e\n" +
"\n" +
"CT_Marquee\x10\x03B\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_chat_proto_rawDescOnce sync.Once
file_chat_proto_rawDescData []byte
)
func file_chat_proto_rawDescGZIP() []byte {
file_chat_proto_rawDescOnce.Do(func() {
file_chat_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_chat_proto_rawDesc), len(file_chat_proto_rawDesc)))
})
return file_chat_proto_rawDescData
}
var file_chat_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_chat_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_chat_proto_goTypes = []any{
(ChatType)(0), // 0: pb.ChatType
(*C2SChat)(nil), // 1: pb.C2SChat
(*ChatUser)(nil), // 2: pb.ChatUser
(ServiceTypeId)(0), // 3: pb.ServiceTypeId
}
var file_chat_proto_depIdxs = []int32{
2, // 0: pb.C2SChat.src_user:type_name -> pb.ChatUser
2, // 1: pb.C2SChat.dst_user:type_name -> pb.ChatUser
0, // 2: pb.C2SChat.type:type_name -> pb.ChatType
3, // 3: pb.C2SChat.game_id: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
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_chat_proto_init() }
func file_chat_proto_init() {
if File_chat_proto != nil {
return
}
file_user_proto_init()
file_service_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_chat_proto_rawDesc), len(file_chat_proto_rawDesc)),
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_chat_proto_goTypes,
DependencyIndexes: file_chat_proto_depIdxs,
EnumInfos: file_chat_proto_enumTypes,
MessageInfos: file_chat_proto_msgTypes,
}.Build()
File_chat_proto = out.File
file_chat_proto_goTypes = nil
file_chat_proto_depIdxs = nil
}

View File

@ -22,13 +22,14 @@ const (
)
type ClientMsg struct {
state protoimpl.MessageState `protogen:"open.v1"`
ServiceTid ServiceTypeId `protobuf:"varint,1,opt,name=service_tid,json=serviceTid,proto3,enum=pb.ServiceTypeId" json:"service_tid,omitempty"` // 服务id
SubServiceName string `protobuf:"bytes,2,opt,name=sub_service_name,json=subServiceName,proto3" json:"sub_service_name,omitempty"` // 具体的服务节点名(客户端进入新的场景,保存该节点名,提高路由速度)
MsgId int32 `protobuf:"varint,3,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` // 消息体
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ServiceTid ServiceTypeId `protobuf:"varint,1,opt,name=service_tid,json=serviceTid,proto3,enum=pb.ServiceTypeId" json:"service_tid,omitempty"` // 服务id
ServiceName string `protobuf:"bytes,2,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` // 具体的服务节点名(客户端进入新的场景,保存该节点名,提高路由速度)
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
MsgId int32 `protobuf:"varint,4,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id
Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` // 消息体
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClientMsg) Reset() {
@ -68,13 +69,20 @@ func (x *ClientMsg) GetServiceTid() ServiceTypeId {
return ServiceTypeId_STI_Unknown
}
func (x *ClientMsg) GetSubServiceName() string {
func (x *ClientMsg) GetServiceName() string {
if x != nil {
return x.SubServiceName
return x.ServiceName
}
return ""
}
func (x *ClientMsg) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
func (x *ClientMsg) GetMsgId() int32 {
if x != nil {
return x.MsgId
@ -93,13 +101,14 @@ var File_client_proto protoreflect.FileDescriptor
const file_client_proto_rawDesc = "" +
"\n" +
"\fclient.proto\x12\x02pb\x1a\rservice.proto\"\x94\x01\n" +
"\fclient.proto\x12\x02pb\x1a\rservice.proto\"\xa6\x01\n" +
"\tClientMsg\x122\n" +
"\vservice_tid\x18\x01 \x01(\x0e2\x11.pb.ServiceTypeIdR\n" +
"serviceTid\x12(\n" +
"\x10sub_service_name\x18\x02 \x01(\tR\x0esubServiceName\x12\x15\n" +
"\x06msg_id\x18\x03 \x01(\x05R\x05msgId\x12\x12\n" +
"\x04data\x18\x04 \x01(\fR\x04dataB\x11Z\x0fcommon/proto/pbb\x06proto3"
"serviceTid\x12!\n" +
"\fservice_name\x18\x02 \x01(\tR\vserviceName\x12\x17\n" +
"\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x15\n" +
"\x06msg_id\x18\x04 \x01(\x05R\x05msgId\x12\x12\n" +
"\x04data\x18\x05 \x01(\fR\x04dataB\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_client_proto_rawDescOnce sync.Once

View File

@ -24,19 +24,19 @@ const (
type ErrCode int32
const (
ErrCode_EC_OK ErrCode = 0
ErrCode_EC_LoginDiffLoc ErrCode = 1 // 帐号在其它地方登陆
ErrCode_OK ErrCode = 0
ErrCode_LoginDiffLoc ErrCode = 1 // 帐号在其它地方登陆
)
// Enum value maps for ErrCode.
var (
ErrCode_name = map[int32]string{
0: "EC_OK",
1: "EC_LoginDiffLoc",
0: "OK",
1: "LoginDiffLoc",
}
ErrCode_value = map[string]int32{
"EC_OK": 0,
"EC_LoginDiffLoc": 1,
"OK": 0,
"LoginDiffLoc": 1,
}
)
@ -72,10 +72,10 @@ var File_code_proto protoreflect.FileDescriptor
const file_code_proto_rawDesc = "" +
"\n" +
"\n" +
"code.proto\x12\x02pb*)\n" +
"\aErrCode\x12\t\n" +
"\x05EC_OK\x10\x00\x12\x13\n" +
"\x0fEC_LoginDiffLoc\x10\x01B\x11Z\x0fcommon/proto/pbb\x06proto3"
"code.proto\x12\x02pb*#\n" +
"\aErrCode\x12\x06\n" +
"\x02OK\x10\x00\x12\x10\n" +
"\fLoginDiffLoc\x10\x01B\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_code_proto_rawDescOnce sync.Once

View File

@ -21,69 +21,8 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type LoginMsgId int32
const (
LoginMsgId_Unknown LoginMsgId = 0
LoginMsgId_C2SUserLogin LoginMsgId = 1 // 玩家登陆
LoginMsgId_S2CUserLogin LoginMsgId = 2
LoginMsgId_NtfUserOnline LoginMsgId = 3
LoginMsgId_C2SUserLogout LoginMsgId = 4
LoginMsgId_S2CUserLogout LoginMsgId = 5
LoginMsgId_NtfUserOffline LoginMsgId = 6
)
// Enum value maps for LoginMsgId.
var (
LoginMsgId_name = map[int32]string{
0: "Unknown",
1: "C2SUserLogin",
2: "S2CUserLogin",
3: "NtfUserOnline",
4: "C2SUserLogout",
5: "S2CUserLogout",
6: "NtfUserOffline",
}
LoginMsgId_value = map[string]int32{
"Unknown": 0,
"C2SUserLogin": 1,
"S2CUserLogin": 2,
"NtfUserOnline": 3,
"C2SUserLogout": 4,
"S2CUserLogout": 5,
"NtfUserOffline": 6,
}
)
func (x LoginMsgId) Enum() *LoginMsgId {
p := new(LoginMsgId)
*p = x
return p
}
func (x LoginMsgId) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (LoginMsgId) Descriptor() protoreflect.EnumDescriptor {
return file_login_proto_enumTypes[0].Descriptor()
}
func (LoginMsgId) Type() protoreflect.EnumType {
return &file_login_proto_enumTypes[0]
}
func (x LoginMsgId) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use LoginMsgId.Descriptor instead.
func (LoginMsgId) EnumDescriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{0}
}
// 玩家登陆
type C2SUserLoginMsg struct {
type C2SUserLogin struct {
state protoimpl.MessageState `protogen:"open.v1"`
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 用户名
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` // 密码或token
@ -92,20 +31,20 @@ type C2SUserLoginMsg struct {
sizeCache protoimpl.SizeCache
}
func (x *C2SUserLoginMsg) Reset() {
*x = C2SUserLoginMsg{}
func (x *C2SUserLogin) Reset() {
*x = C2SUserLogin{}
mi := &file_login_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *C2SUserLoginMsg) String() string {
func (x *C2SUserLogin) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*C2SUserLoginMsg) ProtoMessage() {}
func (*C2SUserLogin) ProtoMessage() {}
func (x *C2SUserLoginMsg) ProtoReflect() protoreflect.Message {
func (x *C2SUserLogin) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -117,33 +56,33 @@ func (x *C2SUserLoginMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use C2SUserLoginMsg.ProtoReflect.Descriptor instead.
func (*C2SUserLoginMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use C2SUserLogin.ProtoReflect.Descriptor instead.
func (*C2SUserLogin) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{0}
}
func (x *C2SUserLoginMsg) GetUsername() string {
func (x *C2SUserLogin) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *C2SUserLoginMsg) GetToken() string {
func (x *C2SUserLogin) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
func (x *C2SUserLoginMsg) GetVersion() string {
func (x *C2SUserLogin) GetVersion() string {
if x != nil {
return x.Version
}
return ""
}
type S2CUserLoginMsg struct {
type S2CUserLogin struct {
state protoimpl.MessageState `protogen:"open.v1"`
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
@ -152,20 +91,20 @@ type S2CUserLoginMsg struct {
sizeCache protoimpl.SizeCache
}
func (x *S2CUserLoginMsg) Reset() {
*x = S2CUserLoginMsg{}
func (x *S2CUserLogin) Reset() {
*x = S2CUserLogin{}
mi := &file_login_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *S2CUserLoginMsg) String() string {
func (x *S2CUserLogin) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*S2CUserLoginMsg) ProtoMessage() {}
func (*S2CUserLogin) ProtoMessage() {}
func (x *S2CUserLoginMsg) ProtoReflect() protoreflect.Message {
func (x *S2CUserLogin) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -177,26 +116,26 @@ func (x *S2CUserLoginMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use S2CUserLoginMsg.ProtoReflect.Descriptor instead.
func (*S2CUserLoginMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use S2CUserLogin.ProtoReflect.Descriptor instead.
func (*S2CUserLogin) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{1}
}
func (x *S2CUserLoginMsg) GetCode() ErrCode {
func (x *S2CUserLogin) GetCode() ErrCode {
if x != nil {
return x.Code
}
return ErrCode_EC_OK
return ErrCode_OK
}
func (x *S2CUserLoginMsg) GetUserId() int64 {
func (x *S2CUserLogin) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
func (x *S2CUserLoginMsg) GetToken() string {
func (x *S2CUserLogin) GetToken() string {
if x != nil {
return x.Token
}
@ -204,27 +143,27 @@ func (x *S2CUserLoginMsg) GetToken() string {
}
// 上线通知
type NtfUserOnlineMsg struct {
type NtfUserOnline struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *NtfUserOnlineMsg) Reset() {
*x = NtfUserOnlineMsg{}
func (x *NtfUserOnline) Reset() {
*x = NtfUserOnline{}
mi := &file_login_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *NtfUserOnlineMsg) String() string {
func (x *NtfUserOnline) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NtfUserOnlineMsg) ProtoMessage() {}
func (*NtfUserOnline) ProtoMessage() {}
func (x *NtfUserOnlineMsg) ProtoReflect() protoreflect.Message {
func (x *NtfUserOnline) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -236,12 +175,12 @@ func (x *NtfUserOnlineMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use NtfUserOnlineMsg.ProtoReflect.Descriptor instead.
func (*NtfUserOnlineMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use NtfUserOnline.ProtoReflect.Descriptor instead.
func (*NtfUserOnline) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{2}
}
func (x *NtfUserOnlineMsg) GetUserId() int64 {
func (x *NtfUserOnline) GetUserId() int64 {
if x != nil {
return x.UserId
}
@ -249,26 +188,26 @@ func (x *NtfUserOnlineMsg) GetUserId() int64 {
}
// 玩家登陆
type C2SUserLogoutMsg struct {
type C2SUserLogout struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *C2SUserLogoutMsg) Reset() {
*x = C2SUserLogoutMsg{}
func (x *C2SUserLogout) Reset() {
*x = C2SUserLogout{}
mi := &file_login_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *C2SUserLogoutMsg) String() string {
func (x *C2SUserLogout) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*C2SUserLogoutMsg) ProtoMessage() {}
func (*C2SUserLogout) ProtoMessage() {}
func (x *C2SUserLogoutMsg) ProtoReflect() protoreflect.Message {
func (x *C2SUserLogout) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -280,32 +219,32 @@ func (x *C2SUserLogoutMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use C2SUserLogoutMsg.ProtoReflect.Descriptor instead.
func (*C2SUserLogoutMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use C2SUserLogout.ProtoReflect.Descriptor instead.
func (*C2SUserLogout) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{3}
}
type S2CUserLogoutMsg struct {
type S2CUserLogout struct {
state protoimpl.MessageState `protogen:"open.v1"`
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"` // 登出原因
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *S2CUserLogoutMsg) Reset() {
*x = S2CUserLogoutMsg{}
func (x *S2CUserLogout) Reset() {
*x = S2CUserLogout{}
mi := &file_login_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *S2CUserLogoutMsg) String() string {
func (x *S2CUserLogout) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*S2CUserLogoutMsg) ProtoMessage() {}
func (*S2CUserLogout) ProtoMessage() {}
func (x *S2CUserLogoutMsg) ProtoReflect() protoreflect.Message {
func (x *S2CUserLogout) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -317,40 +256,40 @@ func (x *S2CUserLogoutMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use S2CUserLogoutMsg.ProtoReflect.Descriptor instead.
func (*S2CUserLogoutMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use S2CUserLogout.ProtoReflect.Descriptor instead.
func (*S2CUserLogout) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{4}
}
func (x *S2CUserLogoutMsg) GetCode() ErrCode {
func (x *S2CUserLogout) GetCode() ErrCode {
if x != nil {
return x.Code
}
return ErrCode_EC_OK
return ErrCode_OK
}
// 下线通知
type NtfUserOfflineMsg struct {
type NtfUserOffline struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *NtfUserOfflineMsg) Reset() {
*x = NtfUserOfflineMsg{}
func (x *NtfUserOffline) Reset() {
*x = NtfUserOffline{}
mi := &file_login_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *NtfUserOfflineMsg) String() string {
func (x *NtfUserOffline) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NtfUserOfflineMsg) ProtoMessage() {}
func (*NtfUserOffline) ProtoMessage() {}
func (x *NtfUserOfflineMsg) ProtoReflect() protoreflect.Message {
func (x *NtfUserOffline) ProtoReflect() protoreflect.Message {
mi := &file_login_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -362,12 +301,12 @@ func (x *NtfUserOfflineMsg) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use NtfUserOfflineMsg.ProtoReflect.Descriptor instead.
func (*NtfUserOfflineMsg) Descriptor() ([]byte, []int) {
// Deprecated: Use NtfUserOffline.ProtoReflect.Descriptor instead.
func (*NtfUserOffline) Descriptor() ([]byte, []int) {
return file_login_proto_rawDescGZIP(), []int{5}
}
func (x *NtfUserOfflineMsg) GetUserId() int64 {
func (x *NtfUserOffline) GetUserId() int64 {
if x != nil {
return x.UserId
}
@ -379,31 +318,22 @@ var File_login_proto protoreflect.FileDescriptor
const file_login_proto_rawDesc = "" +
"\n" +
"\vlogin.proto\x12\x02pb\x1a\n" +
"code.proto\"]\n" +
"\x0fC2SUserLoginMsg\x12\x1a\n" +
"code.proto\"Z\n" +
"\fC2SUserLogin\x12\x1a\n" +
"\busername\x18\x01 \x01(\tR\busername\x12\x14\n" +
"\x05token\x18\x02 \x01(\tR\x05token\x12\x18\n" +
"\aversion\x18\x03 \x01(\tR\aversion\"a\n" +
"\x0fS2CUserLoginMsg\x12\x1f\n" +
"\aversion\x18\x03 \x01(\tR\aversion\"^\n" +
"\fS2CUserLogin\x12\x1f\n" +
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" +
"\x05token\x18\x03 \x01(\tR\x05token\"+\n" +
"\x10NtfUserOnlineMsg\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\"\x12\n" +
"\x10C2SUserLogoutMsg\"3\n" +
"\x10S2CUserLogoutMsg\x12\x1f\n" +
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\",\n" +
"\x11NtfUserOfflineMsg\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId*\x8a\x01\n" +
"\n" +
"LoginMsgId\x12\v\n" +
"\aUnknown\x10\x00\x12\x10\n" +
"\fC2SUserLogin\x10\x01\x12\x10\n" +
"\fS2CUserLogin\x10\x02\x12\x11\n" +
"\rNtfUserOnline\x10\x03\x12\x11\n" +
"\rC2SUserLogout\x10\x04\x12\x11\n" +
"\rS2CUserLogout\x10\x05\x12\x12\n" +
"\x0eNtfUserOffline\x10\x06B\x11Z\x0fcommon/proto/pbb\x06proto3"
"\x05token\x18\x03 \x01(\tR\x05token\"(\n" +
"\rNtfUserOnline\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\"\x0f\n" +
"\rC2SUserLogout\"0\n" +
"\rS2CUserLogout\x12\x1f\n" +
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\")\n" +
"\x0eNtfUserOffline\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userIdB\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_login_proto_rawDescOnce sync.Once
@ -417,21 +347,19 @@ func file_login_proto_rawDescGZIP() []byte {
return file_login_proto_rawDescData
}
var file_login_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_login_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_login_proto_goTypes = []any{
(LoginMsgId)(0), // 0: pb.LoginMsgId
(*C2SUserLoginMsg)(nil), // 1: pb.C2SUserLoginMsg
(*S2CUserLoginMsg)(nil), // 2: pb.S2CUserLoginMsg
(*NtfUserOnlineMsg)(nil), // 3: pb.NtfUserOnlineMsg
(*C2SUserLogoutMsg)(nil), // 4: pb.C2SUserLogoutMsg
(*S2CUserLogoutMsg)(nil), // 5: pb.S2CUserLogoutMsg
(*NtfUserOfflineMsg)(nil), // 6: pb.NtfUserOfflineMsg
(ErrCode)(0), // 7: pb.ErrCode
(*C2SUserLogin)(nil), // 0: pb.C2SUserLogin
(*S2CUserLogin)(nil), // 1: pb.S2CUserLogin
(*NtfUserOnline)(nil), // 2: pb.NtfUserOnline
(*C2SUserLogout)(nil), // 3: pb.C2SUserLogout
(*S2CUserLogout)(nil), // 4: pb.S2CUserLogout
(*NtfUserOffline)(nil), // 5: pb.NtfUserOffline
(ErrCode)(0), // 6: pb.ErrCode
}
var file_login_proto_depIdxs = []int32{
7, // 0: pb.S2CUserLoginMsg.code:type_name -> pb.ErrCode
7, // 1: pb.S2CUserLogoutMsg.code:type_name -> pb.ErrCode
6, // 0: pb.S2CUserLogin.code:type_name -> pb.ErrCode
6, // 1: pb.S2CUserLogout.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
@ -450,14 +378,13 @@ func file_login_proto_init() {
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)),
NumEnums: 1,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_login_proto_goTypes,
DependencyIndexes: file_login_proto_depIdxs,
EnumInfos: file_login_proto_enumTypes,
MessageInfos: file_login_proto_msgTypes,
}.Build()
File_login_proto = out.File

160
common/proto/pb/msgId.pb.go Normal file
View File

@ -0,0 +1,160 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc v6.31.0
// source: msgId.proto
package pb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// 命名规则:
// 1. 所有游戏id都在msgId.proto的MsgId中定义前缀需有C2S,S2C,Ntf三种之一后缀统一为Id
// 2. 所有错误码都在code.proto的ErrCode中定义
// 3. 所有消息名为对应消息id去掉后缀Id组成
type MsgId int32
const (
MsgId_MI_Unknown MsgId = 0
// 聊天服 2000-2100
MsgId_C2SChatId MsgId = 2000 // 玩家聊天消息
MsgId_S2CChatId MsgId = 2001 // 复用C2SChatMsg
// 登陆服 2100-2200
MsgId_C2SUserLoginId MsgId = 2100 // 玩家登陆
MsgId_S2CUserLoginId MsgId = 2101
MsgId_NtfUserOnlineId MsgId = 2102
MsgId_C2SUserLogoutId MsgId = 2104
MsgId_S2CUserLogoutId MsgId = 2105
MsgId_NtfUserOfflineId MsgId = 2106
)
// Enum value maps for MsgId.
var (
MsgId_name = map[int32]string{
0: "MI_Unknown",
2000: "C2SChatId",
2001: "S2CChatId",
2100: "C2SUserLoginId",
2101: "S2CUserLoginId",
2102: "NtfUserOnlineId",
2104: "C2SUserLogoutId",
2105: "S2CUserLogoutId",
2106: "NtfUserOfflineId",
}
MsgId_value = map[string]int32{
"MI_Unknown": 0,
"C2SChatId": 2000,
"S2CChatId": 2001,
"C2SUserLoginId": 2100,
"S2CUserLoginId": 2101,
"NtfUserOnlineId": 2102,
"C2SUserLogoutId": 2104,
"S2CUserLogoutId": 2105,
"NtfUserOfflineId": 2106,
}
)
func (x MsgId) Enum() *MsgId {
p := new(MsgId)
*p = x
return p
}
func (x MsgId) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (MsgId) Descriptor() protoreflect.EnumDescriptor {
return file_msgId_proto_enumTypes[0].Descriptor()
}
func (MsgId) Type() protoreflect.EnumType {
return &file_msgId_proto_enumTypes[0]
}
func (x MsgId) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use MsgId.Descriptor instead.
func (MsgId) EnumDescriptor() ([]byte, []int) {
return file_msgId_proto_rawDescGZIP(), []int{0}
}
var File_msgId_proto protoreflect.FileDescriptor
const file_msgId_proto_rawDesc = "" +
"\n" +
"\vmsgId.proto\x12\x02pb*\xba\x01\n" +
"\x05MsgId\x12\x0e\n" +
"\n" +
"MI_Unknown\x10\x00\x12\x0e\n" +
"\tC2SChatId\x10\xd0\x0f\x12\x0e\n" +
"\tS2CChatId\x10\xd1\x0f\x12\x13\n" +
"\x0eC2SUserLoginId\x10\xb4\x10\x12\x13\n" +
"\x0eS2CUserLoginId\x10\xb5\x10\x12\x14\n" +
"\x0fNtfUserOnlineId\x10\xb6\x10\x12\x14\n" +
"\x0fC2SUserLogoutId\x10\xb8\x10\x12\x14\n" +
"\x0fS2CUserLogoutId\x10\xb9\x10\x12\x15\n" +
"\x10NtfUserOfflineId\x10\xba\x10B\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_msgId_proto_rawDescOnce sync.Once
file_msgId_proto_rawDescData []byte
)
func file_msgId_proto_rawDescGZIP() []byte {
file_msgId_proto_rawDescOnce.Do(func() {
file_msgId_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_msgId_proto_rawDesc), len(file_msgId_proto_rawDesc)))
})
return file_msgId_proto_rawDescData
}
var file_msgId_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_msgId_proto_goTypes = []any{
(MsgId)(0), // 0: pb.MsgId
}
var file_msgId_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_msgId_proto_init() }
func file_msgId_proto_init() {
if File_msgId_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_msgId_proto_rawDesc), len(file_msgId_proto_rawDesc)),
NumEnums: 1,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_msgId_proto_goTypes,
DependencyIndexes: file_msgId_proto_depIdxs,
EnumInfos: file_msgId_proto_enumTypes,
}.Build()
File_msgId_proto = out.File
file_msgId_proto_goTypes = nil
file_msgId_proto_depIdxs = nil
}

View File

@ -25,21 +25,24 @@ type ServiceTypeId int32
const (
ServiceTypeId_STI_Unknown ServiceTypeId = 0
ServiceTypeId_STI_Gate ServiceTypeId = 1000 // 网关id
ServiceTypeId_STI_Login ServiceTypeId = 1001 // 登陆服
ServiceTypeId_STI_Gate ServiceTypeId = 100 // 网关id
ServiceTypeId_STI_Login ServiceTypeId = 101 // 登陆服
ServiceTypeId_STI_Chat ServiceTypeId = 102 // 聊天服
)
// Enum value maps for ServiceTypeId.
var (
ServiceTypeId_name = map[int32]string{
0: "STI_Unknown",
1000: "STI_Gate",
1001: "STI_Login",
0: "STI_Unknown",
100: "STI_Gate",
101: "STI_Login",
102: "STI_Chat",
}
ServiceTypeId_value = map[string]int32{
"STI_Unknown": 0,
"STI_Gate": 1000,
"STI_Login": 1001,
"STI_Gate": 100,
"STI_Login": 101,
"STI_Chat": 102,
}
)
@ -74,11 +77,12 @@ var File_service_proto protoreflect.FileDescriptor
const file_service_proto_rawDesc = "" +
"\n" +
"\rservice.proto\x12\x02pb*?\n" +
"\rservice.proto\x12\x02pb*K\n" +
"\rServiceTypeId\x12\x0f\n" +
"\vSTI_Unknown\x10\x00\x12\r\n" +
"\bSTI_Gate\x10\xe8\a\x12\x0e\n" +
"\tSTI_Login\x10\xe9\aB\x11Z\x0fcommon/proto/pbb\x06proto3"
"\vSTI_Unknown\x10\x00\x12\f\n" +
"\bSTI_Gate\x10d\x12\r\n" +
"\tSTI_Login\x10e\x12\f\n" +
"\bSTI_Chat\x10fB\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_service_proto_rawDescOnce sync.Once

160
common/proto/pb/user.pb.go Normal file
View File

@ -0,0 +1,160 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc v6.31.0
// source: user.proto
package pb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// 聊天中显示的玩家基础信息
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"`
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等级
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ChatUser) Reset() {
*x = ChatUser{}
mi := &file_user_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ChatUser) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ChatUser) ProtoMessage() {}
func (x *ChatUser) ProtoReflect() protoreflect.Message {
mi := &file_user_proto_msgTypes[0]
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 ChatUser.ProtoReflect.Descriptor instead.
func (*ChatUser) Descriptor() ([]byte, []int) {
return file_user_proto_rawDescGZIP(), []int{0}
}
func (x *ChatUser) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
func (x *ChatUser) GetNickname() string {
if x != nil {
return x.Nickname
}
return ""
}
func (x *ChatUser) GetAvatar() string {
if x != nil {
return x.Avatar
}
return ""
}
func (x *ChatUser) GetAvatarFrame() string {
if x != nil {
return x.AvatarFrame
}
return ""
}
func (x *ChatUser) GetVipLevel() string {
if x != nil {
return x.VipLevel
}
return ""
}
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" +
"\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\bvipLevelB\x11Z\x0fcommon/proto/pbb\x06proto3"
var (
file_user_proto_rawDescOnce sync.Once
file_user_proto_rawDescData []byte
)
func file_user_proto_rawDescGZIP() []byte {
file_user_proto_rawDescOnce.Do(func() {
file_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_user_proto_rawDesc), len(file_user_proto_rawDesc)))
})
return file_user_proto_rawDescData
}
var file_user_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_user_proto_goTypes = []any{
(*ChatUser)(nil), // 0: pb.ChatUser
}
var file_user_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_user_proto_init() }
func file_user_proto_init() {
if File_user_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_user_proto_rawDesc), len(file_user_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_user_proto_goTypes,
DependencyIndexes: file_user_proto_depIdxs,
MessageInfos: file_user_proto_msgTypes,
}.Build()
File_user_proto = out.File
file_user_proto_goTypes = nil
file_user_proto_depIdxs = nil
}

View File

@ -2,4 +2,5 @@ package serviceName
const (
Gate = "gate"
Chat = "chat"
)

View File

@ -3,6 +3,7 @@ package topicName
const (
//extTopic = ".topic"
//extGroup = ".group"
UserOnline = "user.online.topic"
UserOffline = "user.offline.topic"
UserOnline = "user.online.topic"
UserOffline = "user.offline.topic"
WorldMessage = "world.msg.topic"
)

30
server/chat/cmd/cmd.go Normal file
View File

@ -0,0 +1,30 @@
package cmd
import (
"fmt"
"game/server/chat/config"
"game/server/chat/model"
"game/server/chat/server"
"github.com/fox/fox/log"
"os"
"os/signal"
"syscall"
)
func initRepo() {
model.InitRedis()
}
func Run(GitCommit, GitBranch, BuildDate string) {
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))
}

View File

@ -0,0 +1,35 @@
package config
import (
"fmt"
"game/common/config"
"github.com/fox/fox/db"
"github.com/fox/fox/log"
)
var Command *config.Command
var Cfg *config.Common[ChatConfig]
type ChatConfig struct {
}
func initLog() {
log.Open(fmt.Sprintf("chat_%v.log", Command.VMod), log.DebugL)
}
func LoadConfig(GitCommit, GitBranch, BuildDate string) {
Command = config.ParseCommand()
initLog()
rdb, err := db.InitRedis(Command.RedisPassword, Command.RedisHost, Command.RedisPort, 0)
if err != nil {
log.Error(err.Error())
return
}
defer func() { _ = rdb.Close() }()
Cfg, err = config.LoadCommonConfig[ChatConfig](rdb, GitCommit, GitBranch, BuildDate)
if err != nil {
log.Error(err.Error())
return
}
log.DebugF("load common config success")
}

24
server/chat/main.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"game/server/chat/cmd"
"github.com/fox/fox/ksync"
"github.com/fox/fox/log"
"time"
)
var (
GitCommit = "unknown"
GitBranch = "unknown"
BuildDate = "unknown"
)
func main() {
tm, err := time.Parse("20060102150405", BuildDate)
if err == nil {
BuildDate = tm.Format("2006-01-02 15:04:05")
}
ksync.RunSafe(func() {
cmd.Run(GitBranch, GitCommit, BuildDate)
}, func() { log.ErrorF("reset run") })
}

19
server/chat/model/db.go Normal file
View File

@ -0,0 +1,19 @@
package model
import (
"game/server/chat/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, 0)
if err != nil {
log.Fatal(err.Error())
return
}
}

View File

@ -0,0 +1,31 @@
package server
import (
"game/common/proto/pb"
"game/common/topicName"
"github.com/fox/fox/log"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
)
func (s *ChatService) initProcessor() {
s.processor.RegisterMessages(processor.RegisterMetas{
pb.MsgId_C2SChatId: {pb.C2SChat{}, s.onChat},
})
}
// 收到登陆成功消息,判断是否顶号
func (s *ChatService) onChat(uid int64, msg *pb.C2SChat) {
switch msg.Type {
case pb.ChatType_CT_Private:
sName, err := s.bindService.FindServiceName(msg.DstUser.UserId, pb.ServiceTypeId_STI_Gate)
if err != nil {
log.DebugF("find user:%v in gate err: %v", uid, err)
return
}
s.SendServiceMsg(service.TopicEx(sName), msg.DstUser.UserId, int32(pb.MsgId_S2CChatId), msg)
default:
s.SendServiceMsg(service.TopicEx(topicName.WorldMessage), uid, int32(pb.MsgId_S2CChatId), msg)
}
}

View File

@ -0,0 +1,115 @@
package server
import (
"fmt"
"game/common/proto/ipb"
"game/common/proto/pb"
"game/common/serviceName"
"game/common/userBindService"
"game/server/chat/config"
"game/server/chat/model"
"github.com/fox/fox/log"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
"github.com/golang/protobuf/proto"
)
var Chat []*ChatService
type ChatService 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 := newChatService(sid); srv != nil {
Chat = append(Chat, srv)
}
}
}
func Stop() {
for _, srv := range Chat {
srv.NotifyStop()
}
for _, srv := range Chat {
srv.WaitStop()
}
}
func newChatService(serviceId int) *ChatService {
var err error
s := new(ChatService)
sName := fmt.Sprintf("%v-%d", serviceName.Chat, serviceId)
if s.NatsService, err = service.NewNatsService(&service.InitNatsServiceParams{
EtcdAddress: config.Cfg.Etcd.Address,
EtcdUsername: "",
EtcdPassword: "",
NatsAddress: config.Cfg.Nats.Address,
ServiceType: serviceName.Chat,
ServiceName: sName,
OnFunc: s,
TypeId: int(pb.ServiceTypeId_STI_Chat),
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 *ChatService) 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 *ChatService) CanStop() bool {
return true
}
func (s *ChatService) OnStop() {
s.NatsService.OnStop()
log.Debug("OnStop")
}
// 处理其它服发送过来的消息
func (s *ChatService) 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.UserId, req)
}
//log.Debug(s.Log("on message:%v", string(msg)))
return nil
}
// 向内部服务发送消息
func (s *ChatService) SendServiceData(topic string, userId int64, msgId int32, data []byte) {
iMsg := &ipb.InternalMsg{ConnId: 0, UserId: userId, MsgId: msgId, Msg: data}
dMsg, _ := proto.Marshal(iMsg)
_ = s.Send(topic, dMsg)
}
// 向内部服务发送消息
func (s *ChatService) SendServiceMsg(topic string, userId int64, msgId int32, msg proto.Message) {
iMsg := &ipb.InternalMsg{ConnId: 0, UserId: userId, MsgId: msgId}
iMsg.Msg, _ = proto.Marshal(msg)
dMsg, _ := proto.Marshal(iMsg)
_ = s.Send(topic, dMsg)
}

View File

@ -15,9 +15,9 @@ func initRepo() {
model.InitRedis()
}
func Run(version string) {
config.LoadConfig()
log.Info(fmt.Sprintf("版本信息.%v", version))
func Run(GitCommit, GitBranch, BuildDate string) {
config.LoadConfig(GitCommit, GitBranch, BuildDate)
log.Info(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
initRepo()
server.Init()

View File

@ -19,7 +19,7 @@ var Command *config.Command
var Cfg *config.Common[GateConfig]
type GateConfig struct {
Address string `json:"address"`
Address string `json:"address"` // 网关地址
Port string `json:"port"`
}
@ -27,7 +27,7 @@ func initLog() {
log.Open(fmt.Sprintf("gate_%v.log", Command.VMod), log.DebugL)
}
func LoadConfig() {
func LoadConfig(GitCommit, GitBranch, BuildDate string) {
Command = config.ParseCommand()
initLog()
rdb, err := db.InitRedis(Command.RedisPassword, Command.RedisHost, Command.RedisPort, 0)
@ -36,7 +36,7 @@ func LoadConfig() {
return
}
defer func() { _ = rdb.Close() }()
Cfg, err = config.LoadCommonConfig[GateConfig](rdb)
Cfg, err = config.LoadCommonConfig[GateConfig](rdb, GitCommit, GitBranch, BuildDate)
if err != nil {
log.Error(err.Error())
return

View File

@ -1,7 +1,6 @@
package main
import (
"fmt"
"game/server/gate/cmd"
"github.com/fox/fox/ksync"
"github.com/fox/fox/log"
@ -20,6 +19,6 @@ func main() {
BuildDate = tm.Format("2006-01-02 15:04:05")
}
ksync.RunSafe(func() {
cmd.Run(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
}, func() { log.Debug("reset run") })
cmd.Run(GitCommit, GitBranch, BuildDate)
}, func() { log.ErrorF("reset run") })
}

View File

@ -13,38 +13,38 @@ import (
*/
func (s *GateService) initProcessor() {
s.processor.RegisterMessages(processor.RegisterMetas{
pb.LoginMsgId_NtfUserOnline: {pb.NtfUserOnlineMsg{}, s.onNtfUserOnline},
pb.LoginMsgId_S2CUserLogin: {pb.S2CUserLoginMsg{}, s.onUserLogin},
pb.LoginMsgId_S2CUserLogout: {pb.S2CUserLogoutMsg{}, s.onUserLogout},
pb.MsgId_S2CUserLoginId: {pb.S2CUserLogin{}, s.onUserLogin},
pb.MsgId_S2CUserLogoutId: {pb.S2CUserLogout{}, s.onUserLogout},
})
}
func (s *GateService) onNtfUserOnline(conn ws.IConn, _ *pb.NtfUserOnlineMsg) {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
conn.NotifyClose()
}
// 收到登陆成功消息,判断是否顶号
func (s *GateService) onUserLogin(conn ws.IConn, msg *pb.S2CUserLoginMsg) {
// 登陆失败,回传玩家
if msg.Code != pb.ErrCode_EC_OK {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
func (s *GateService) onUserLogin(conn ws.IConn, msg *pb.S2CUserLogin) {
if conn == nil {
return
}
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
// 登陆失败,回传玩家
if msg.Code != pb.ErrCode_OK {
s.SendClientMsg(conn, int32(pb.MsgId_S2CUserLoginId), msg)
return
}
s.SendClientMsg(conn, int32(pb.MsgId_S2CUserLoginId), msg)
s.wss.SetUserId(conn.Id(), msg.UserId)
sName := s.bindService.LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
// 网关不同,说明玩家在其它网关上登陆,
if sName != "" && sName != s.Name() {
s.SendServiceMsg(service.TopicEx(sName), conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
s.SendServiceMsg(service.TopicEx(sName), conn, int32(pb.MsgId_S2CUserLogoutId), &pb.S2CUserLogout{Code: pb.ErrCode_LoginDiffLoc})
}
// 广播玩家上线
s.SendServiceMsg(topicName.UserOnline, conn, int32(pb.LoginMsgId_NtfUserOnline), &pb.NtfUserOnlineMsg{UserId: msg.UserId})
s.SendServiceMsg(topicName.UserOnline, conn, int32(pb.MsgId_NtfUserOnlineId), &pb.NtfUserOnline{UserId: msg.UserId})
}
// 收到登出消息
func (s *GateService) onUserLogout(conn ws.IConn, msg *pb.S2CUserLogoutMsg) {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogout), msg)
func (s *GateService) onUserLogout(conn ws.IConn, msg *pb.S2CUserLogout) {
if conn == nil {
return
}
s.SendClientMsg(conn, int32(pb.MsgId_S2CUserLogoutId), msg)
// 登出的清理工作由WsOnDisconnect实现
conn.NotifyClose()
}

View File

@ -10,19 +10,18 @@ import (
"game/common/utils"
"game/server/gate/config"
"game/server/gate/model"
"github.com/fox/fox/etcd"
"github.com/fox/fox/log"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
"github.com/fox/fox/ws"
"github.com/golang/protobuf/proto"
"github.com/nats-io/nats.go"
)
var Gates []*GateService
type GateService struct {
*service.NatsService
etcdService *etcd.Registry[etcd.ServiceNode]
wss *ws.WsServer
processor *processor.Processor
bindService *userBindService.UserBindService
@ -51,34 +50,24 @@ func newGateService(serviceId int) *GateService {
s := new(GateService)
sName := fmt.Sprintf("%v-%d", serviceName.Gate, serviceId)
if s.NatsService, err = service.NewNatsService(serviceName.Gate, sName, s, config.Cfg.Nats.Address...); err != nil {
if s.NatsService, err = service.NewNatsService(&service.InitNatsServiceParams{
EtcdAddress: config.Cfg.Etcd.Address,
EtcdUsername: "",
EtcdPassword: "",
NatsAddress: config.Cfg.Nats.Address,
ServiceType: serviceName.Gate,
ServiceName: sName,
OnFunc: s,
TypeId: int(pb.ServiceTypeId_STI_Gate),
Version: config.Cfg.BuildDate,
}); err != nil {
log.Fatal(err.Error())
return nil
}
if s.etcdService, err = etcd.NewRegistry[etcd.ServiceNode](config.Cfg.Etcd.Address, etcd.ServiceNode{}.EtcdRootKey(), "", ""); err != nil {
log.Error(err.Error())
s.NatsService.OnStop()
return nil
}
wsAddress := fmt.Sprintf("%v:%v", config.Cfg.Special.Address, config.Cfg.Special.Port)
s.wss = ws.NewWsServer(wsAddress, s.WsOnMessage, s.WsOnDisconnect)
endpoint := &etcd.ServiceNode{
TypeId: int(pb.ServiceTypeId_STI_Gate),
Name: s.Name(),
Type: s.Type(),
Address: "",
Port: 0,
Version: "",
ServiceType: etcd.Unique,
}
if err = s.etcdService.Register(endpoint); err != nil {
log.Error(err.Error())
s.NatsService.OnStop()
return nil
}
s.bindService = userBindService.NewUserBindService(model.UserRedis, s.etcdService)
s.bindService = userBindService.NewUserBindService(model.UserRedis, s.ServiceEtcd())
s.processor = processor.NewProcessor()
s.initProcessor()
@ -87,26 +76,60 @@ func newGateService(serviceId int) *GateService {
}
func (s *GateService) OnInit() {
s.etcdService.WatchServices()
if err := s.NatsService.Subscribe(service.Topic(s)); err != nil {
err := s.NatsService.SubscribeCb(topicName.WorldMessage, func(m *nats.Msg) {
var iMsg = &ipb.InternalMsg{}
if err := proto.Unmarshal(m.Data, iMsg); err != nil {
return
}
s.RunOnce(func() {
s.wss.Rang(func(conn ws.IConn) bool {
s.connMessage(conn, iMsg)
return true
})
})
})
if err != nil {
log.Error(err.Error())
}
// if err := s.NatsService.QueueSubscribe(service.GroupTopic(s), service.GroupQueue(s)); err != nil {
// log.Error(err.Error())
// }
s.NatsService.Run()
s.wss.Run()
log.Debug("onInit")
}
func (s *GateService) CanStop() bool {
return true
}
func (s *GateService) OnStop() {
s.etcdService.UnregisterService()
s.etcdService.UnregisterService()
s.NatsService.OnStop()
log.Debug("OnStop")
}
func (s *GateService) findConn(msg *ipb.InternalMsg) ws.IConn {
switch msg.MsgId {
case int32(pb.MsgId_S2CUserLoginId):
conn, _ := s.wss.FindConnByConnId(msg.ConnId)
return conn
default:
conn, _ := s.wss.FindConnByUserId(msg.UserId)
return conn
}
}
// 处理消息
func (s *GateService) connMessage(conn ws.IConn, iMsg *ipb.InternalMsg) {
if req, err := s.processor.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
err = s.processor.Dispatch(iMsg.MsgId, conn, req)
} else {
s.SendClientData(conn, iMsg.MsgId, iMsg.Msg)
}
//log.Debug(s.Log("on message:%v", string(msg)))
}
// 处理其它服发送过来的消息。大部分是将消息转发给玩家
func (s *GateService) OnMessage(data []byte) error {
var iMsg = &ipb.InternalMsg{}
@ -115,16 +138,13 @@ func (s *GateService) OnMessage(data []byte) error {
log.Error(err.Error())
return err
}
var conn ws.IConn
if conn, _ = s.wss.FindConnByUserId(iMsg.UserId); conn == nil {
return err
// conn不能为空全服广播消息走WorldMessage
var conn = s.findConn(iMsg)
if conn == nil {
log.WarnF(s.Log("client not exist.msg:%v", iMsg.MsgId))
return nil
}
if req, err := s.processor.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
err = s.processor.Dispatch(iMsg.MsgId, conn, req)
} else {
s.SendClientData(conn, iMsg.MsgId, iMsg.Msg)
}
//log.Debug(s.Log("on message:%v", string(msg)))
s.connMessage(conn, iMsg)
return nil
}
@ -150,8 +170,8 @@ func (s *GateService) WsOnMessage(conn ws.IConn, data []byte) {
return
}
var topic string
if msg.SubServiceName != "" {
topic = service.TopicEx(msg.SubServiceName)
if msg.ServiceName != "" {
topic = service.TopicEx(msg.ServiceName)
} else {
topic = s.findTopic(conn.UserId(), msg.ServiceTid)
}
@ -200,7 +220,7 @@ func (s *GateService) WsOnDisconnect(conn ws.IConn) {
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送顶号消息(processor中处理),并主动关闭连接,不广播下线消息
if sName == s.Name() {
s.bindService.DelUserService(conn.UserId(), pb.ServiceTypeId_STI_Gate)
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.LoginMsgId_NtfUserOffline), &pb.NtfUserOfflineMsg{UserId: conn.UserId()})
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.MsgId_NtfUserOfflineId), &pb.NtfUserOffline{UserId: conn.UserId()})
}
log.Debug(s.Log("user:%v disconnect", conn.UserId()))
}