diff --git a/common/config/config.go b/common/config/config.go index c6f3e76..10f783c 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -4,6 +4,7 @@ type Common[T any] struct { ServiceType int `json:"service_type"` Logger Logger `json:"logger"` Etcd Etcd `json:"etcd"` + Redis Redis `json:"redis"` Nats Nats `json:"nats"` Special *T `json:"special"` } diff --git a/common/config/loadConfig.go b/common/config/loadConfig.go index 9c06ce9..4f8e454 100644 --- a/common/config/loadConfig.go +++ b/common/config/loadConfig.go @@ -6,16 +6,21 @@ import ( "errors" "flag" "fmt" + "game/common/testHelper" "github.com/fox/fox/log" "github.com/go-redis/redis/v8" ) const ( //ModeDev = "dev" // 开发服 - etcdKey = "etcd_config" - etcdAddress = "114.132.124.145:2379" - natsKey = "nats_config" - natsAddress = "nats://114.132.124.145:4222" + etcdKey = "etcd_config" + etcdAddress = "114.132.124.145:2379" + natsKey = "nats_config" + natsAddress = "nats://114.132.124.145:4222" + redisKey = "redis_config" + redisAddress = testHelper.Host + redisPort = testHelper.RedisPort + redisPassword = testHelper.RedisPassword ) func LoadSpecialConfig[T any](rd *redis.Client, specialKey string, comm *Common[T]) error { @@ -43,6 +48,7 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) { var ret resultT[T] var comm Common[T] comm.Special = &ret.Value + // 初始化etcd s, err := rd.Get(context.Background(), etcdKey).Result() if err != nil && !errors.Is(err, redis.Nil) { log.FatalF("init config:%v", err) @@ -61,6 +67,8 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) { } else { err = json.Unmarshal([]byte(s), &comm.Etcd) } + + // 初始化nats s, err = rd.Get(context.Background(), natsKey).Result() if err != nil && !errors.Is(err, redis.Nil) { log.FatalF("init config:%v", err) @@ -75,6 +83,22 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) { } else { err = json.Unmarshal([]byte(s), &comm.Nats) } + + // 初始化redis + s, err = rd.Get(context.Background(), redisKey).Result() + if err != nil && !errors.Is(err, redis.Nil) { + log.FatalF("init config:%v", err) + return nil, err + } + if s == "" { + log.DebugF("load config:empty redis key") + comm.Redis = Redis{Host: redisAddress, Port: redisPort, Password: redisPassword} + if bs, err := json.Marshal(&comm.Redis); err == nil { + err = rd.Set(context.Background(), redisKey, string(bs), 0).Err() + } + } else { + err = json.Unmarshal([]byte(s), &comm.Redis) + } return &comm, nil } diff --git a/common/internalPb/internal.proto b/common/internalPb/internal.proto index db4b512..08dc7fc 100644 --- a/common/internalPb/internal.proto +++ b/common/internalPb/internal.proto @@ -1,19 +1,20 @@ syntax = "proto3"; -package internal; -option go_package = "common/proto/internal"; +package ipb; +option go_package = "common/proto/ipb"; enum MsgId { Unknown = 0; - Internal = -1; // 玩家申请进入房间 + Internal = -1; // 内部消息id } message InternalMsg { - int64 user_id = 1; // 玩家id - int32 msg_id = 2; // 消息id - bytes msg = 3; // 消息 + uint32 conn_id = 1; // 刚登陆时没有user_id,只有conn_id + int64 user_id = 2; // 玩家id + int32 msg_id = 3; // 消息id + bytes msg = 4; // 消息 } // 网关解包客户端消息 diff --git a/common/pb/client.proto b/common/pb/client.proto new file mode 100644 index 0000000..93ac7ba --- /dev/null +++ b/common/pb/client.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package pb; +option go_package = "common/proto/pb"; + +import "service.proto"; + + +message ClientMsg +{ + ServiceTypeId service_id = 1; // 服务id + int32 msg_id = 2; // 消息id + bytes data = 3; // 消息体 +} + + diff --git a/common/pb/code.proto b/common/pb/code.proto index 9404067..4c277ae 100644 --- a/common/pb/code.proto +++ b/common/pb/code.proto @@ -1,11 +1,11 @@ syntax = "proto3"; -package internal; -option go_package = "common/proto"; +package pb; +option go_package = "common/proto/pb"; enum ErrCode { - OK = 0; - LoginFail = 1; // 登陆失败 + EC_OK = 0; + EC_LoginDiffLoc = 1; // 帐号在其它地方登陆 } diff --git a/common/pb/login.proto b/common/pb/login.proto index 1a2d573..c3cb69d 100644 --- a/common/pb/login.proto +++ b/common/pb/login.proto @@ -1,27 +1,55 @@ syntax = "proto3"; -package internal; -option go_package = "common/proto"; +package pb; +option go_package = "common/proto/pb"; import "code.proto"; enum LoginMsgId { Unknown = 0; - C2SLogin = 1; // 玩家登陆 + C2SUserLogin = 1; // 玩家登陆 + S2SUserLogin = 2; + NtfUserOnline = 3; + C2SUserLogout = 4; + S2CUserLogout = 5; + NtfUserOffline = 6; } // 玩家登陆 -message C2SLoginMsg +message C2SUserLoginMsg { string username = 1; // 用户名 string token = 2; // 密码或token string version = 3; // 版本 } -message S2CLoginMsg +message S2CUserLoginMsg { ErrCode code = 1; + int64 user_id = 2; } +// 上线通知 +message NtfUserOnlineMsg +{ + int64 user_id = 2; // 玩家id +} + +// 玩家登陆 +message C2SUserLogoutMsg +{ + +} + +message S2CUserLogoutMsg +{ + ErrCode code = 1; // 登出原因 +} + +// 下线通知 +message NtfUserOfflineMsg +{ + int64 user_id = 2; // 玩家id +} \ No newline at end of file diff --git a/common/pb/service.proto b/common/pb/service.proto new file mode 100644 index 0000000..e41c012 --- /dev/null +++ b/common/pb/service.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package pb; +option go_package = "common/proto/pb"; + +enum ServiceTypeId +{ + STI_Unknown = 0; + STI_Gate = 1000; // 网关id + STI_Login = 1001; // 登陆服 +} + + diff --git a/common/proto/internal/internal.pb.go b/common/proto/ipb/internal.pb.go similarity index 87% rename from common/proto/internal/internal.pb.go rename to common/proto/ipb/internal.pb.go index d406a17..0df1e37 100644 --- a/common/proto/internal/internal.pb.go +++ b/common/proto/ipb/internal.pb.go @@ -4,7 +4,7 @@ // protoc v6.31.0 // source: internal.proto -package internal +package ipb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -25,7 +25,7 @@ type MsgId int32 const ( MsgId_Unknown MsgId = 0 - MsgId_Internal MsgId = -1 // 玩家申请进入房间 + MsgId_Internal MsgId = -1 // 内部消息id ) // Enum value maps for MsgId. @@ -69,9 +69,10 @@ func (MsgId) EnumDescriptor() ([]byte, []int) { type InternalMsg struct { state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id - MsgId int32 `protobuf:"varint,2,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id - Msg []byte `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` // 消息 + 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"` // 消息 unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -106,6 +107,13 @@ func (*InternalMsg) Descriptor() ([]byte, []int) { return file_internal_proto_rawDescGZIP(), []int{0} } +func (x *InternalMsg) GetConnId() uint32 { + if x != nil { + return x.ConnId + } + return 0 +} + func (x *InternalMsg) GetUserId() int64 { if x != nil { return x.UserId @@ -200,11 +208,12 @@ var File_internal_proto protoreflect.FileDescriptor const file_internal_proto_rawDesc = "" + "\n" + - "\x0einternal.proto\x12\binternal\"O\n" + + "\x0einternal.proto\x12\x03ipb\"h\n" + "\vInternalMsg\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x15\n" + - "\x06msg_id\x18\x02 \x01(\x05R\x05msgId\x12\x10\n" + - "\x03msg\x18\x03 \x01(\fR\x03msg\"q\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" + @@ -213,7 +222,7 @@ const file_internal_proto_rawDesc = "" + "\x03msg\x18\x04 \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\x17Z\x15common/proto/internalb\x06proto3" + "\bInternal\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01B\x12Z\x10common/proto/ipbb\x06proto3" var ( file_internal_proto_rawDescOnce sync.Once @@ -230,9 +239,9 @@ 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_goTypes = []any{ - (MsgId)(0), // 0: internal.MsgId - (*InternalMsg)(nil), // 1: internal.InternalMsg - (*C2SMessage)(nil), // 2: internal.C2SMessage + (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 diff --git a/common/proto/login.pb.go b/common/proto/login.pb.go deleted file mode 100644 index d77b8f6..0000000 --- a/common/proto/login.pb.go +++ /dev/null @@ -1,245 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.6 -// protoc v6.31.0 -// source: login.proto - -package proto - -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 LoginMsgId int32 - -const ( - LoginMsgId_Unknown LoginMsgId = 0 - LoginMsgId_C2SLogin LoginMsgId = 1 // 玩家登陆 -) - -// Enum value maps for LoginMsgId. -var ( - LoginMsgId_name = map[int32]string{ - 0: "Unknown", - 1: "C2SLogin", - } - LoginMsgId_value = map[string]int32{ - "Unknown": 0, - "C2SLogin": 1, - } -) - -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 C2SLoginMsg 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 - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` // 版本 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *C2SLoginMsg) Reset() { - *x = C2SLoginMsg{} - mi := &file_login_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *C2SLoginMsg) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*C2SLoginMsg) ProtoMessage() {} - -func (x *C2SLoginMsg) ProtoReflect() protoreflect.Message { - mi := &file_login_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 C2SLoginMsg.ProtoReflect.Descriptor instead. -func (*C2SLoginMsg) Descriptor() ([]byte, []int) { - return file_login_proto_rawDescGZIP(), []int{0} -} - -func (x *C2SLoginMsg) GetUsername() string { - if x != nil { - return x.Username - } - return "" -} - -func (x *C2SLoginMsg) GetToken() string { - if x != nil { - return x.Token - } - return "" -} - -func (x *C2SLoginMsg) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type S2CLoginMsg struct { - state protoimpl.MessageState `protogen:"open.v1"` - Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=internal.ErrCode" json:"code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *S2CLoginMsg) Reset() { - *x = S2CLoginMsg{} - mi := &file_login_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *S2CLoginMsg) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*S2CLoginMsg) ProtoMessage() {} - -func (x *S2CLoginMsg) ProtoReflect() protoreflect.Message { - mi := &file_login_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 S2CLoginMsg.ProtoReflect.Descriptor instead. -func (*S2CLoginMsg) Descriptor() ([]byte, []int) { - return file_login_proto_rawDescGZIP(), []int{1} -} - -func (x *S2CLoginMsg) GetCode() ErrCode { - if x != nil { - return x.Code - } - return ErrCode_OK -} - -var File_login_proto protoreflect.FileDescriptor - -const file_login_proto_rawDesc = "" + - "\n" + - "\vlogin.proto\x12\binternal\x1a\n" + - "code.proto\"Y\n" + - "\vC2SLoginMsg\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\"4\n" + - "\vS2CLoginMsg\x12%\n" + - "\x04code\x18\x01 \x01(\x0e2\x11.internal.ErrCodeR\x04code*'\n" + - "\n" + - "LoginMsgId\x12\v\n" + - "\aUnknown\x10\x00\x12\f\n" + - "\bC2SLogin\x10\x01B\x0eZ\fcommon/protob\x06proto3" - -var ( - file_login_proto_rawDescOnce sync.Once - file_login_proto_rawDescData []byte -) - -func file_login_proto_rawDescGZIP() []byte { - file_login_proto_rawDescOnce.Do(func() { - file_login_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc))) - }) - return file_login_proto_rawDescData -} - -var file_login_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_login_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_login_proto_goTypes = []any{ - (LoginMsgId)(0), // 0: internal.LoginMsgId - (*C2SLoginMsg)(nil), // 1: internal.C2SLoginMsg - (*S2CLoginMsg)(nil), // 2: internal.S2CLoginMsg - (ErrCode)(0), // 3: internal.ErrCode -} -var file_login_proto_depIdxs = []int32{ - 3, // 0: internal.S2CLoginMsg.code:type_name -> internal.ErrCode - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_login_proto_init() } -func file_login_proto_init() { - if File_login_proto != nil { - return - } - file_code_proto_init() - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)), - NumEnums: 1, - NumMessages: 2, - 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 - file_login_proto_goTypes = nil - file_login_proto_depIdxs = nil -} diff --git a/common/proto/pb/client.pb.go b/common/proto/pb/client.pb.go new file mode 100644 index 0000000..7263c76 --- /dev/null +++ b/common/proto/pb/client.pb.go @@ -0,0 +1,144 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v6.31.0 +// source: client.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 ClientMsg struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServiceId ServiceTypeId `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3,enum=pb.ServiceTypeId" json:"service_id,omitempty"` // 服务id + MsgId int32 `protobuf:"varint,2,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` // 消息体 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClientMsg) Reset() { + *x = ClientMsg{} + mi := &file_client_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClientMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientMsg) ProtoMessage() {} + +func (x *ClientMsg) ProtoReflect() protoreflect.Message { + mi := &file_client_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 ClientMsg.ProtoReflect.Descriptor instead. +func (*ClientMsg) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{0} +} + +func (x *ClientMsg) GetServiceId() ServiceTypeId { + if x != nil { + return x.ServiceId + } + return ServiceTypeId_STI_Unknown +} + +func (x *ClientMsg) GetMsgId() int32 { + if x != nil { + return x.MsgId + } + return 0 +} + +func (x *ClientMsg) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +var File_client_proto protoreflect.FileDescriptor + +const file_client_proto_rawDesc = "" + + "\n" + + "\fclient.proto\x12\x02pb\x1a\rservice.proto\"h\n" + + "\tClientMsg\x120\n" + + "\n" + + "service_id\x18\x01 \x01(\x0e2\x11.pb.ServiceTypeIdR\tserviceId\x12\x15\n" + + "\x06msg_id\x18\x02 \x01(\x05R\x05msgId\x12\x12\n" + + "\x04data\x18\x03 \x01(\fR\x04dataB\x11Z\x0fcommon/proto/pbb\x06proto3" + +var ( + file_client_proto_rawDescOnce sync.Once + file_client_proto_rawDescData []byte +) + +func file_client_proto_rawDescGZIP() []byte { + file_client_proto_rawDescOnce.Do(func() { + file_client_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_client_proto_rawDesc), len(file_client_proto_rawDesc))) + }) + return file_client_proto_rawDescData +} + +var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_client_proto_goTypes = []any{ + (*ClientMsg)(nil), // 0: pb.ClientMsg + (ServiceTypeId)(0), // 1: pb.ServiceTypeId +} +var file_client_proto_depIdxs = []int32{ + 1, // 0: pb.ClientMsg.service_id:type_name -> pb.ServiceTypeId + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_client_proto_init() } +func file_client_proto_init() { + if File_client_proto != nil { + return + } + file_service_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_client_proto_rawDesc), len(file_client_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_client_proto_goTypes, + DependencyIndexes: file_client_proto_depIdxs, + MessageInfos: file_client_proto_msgTypes, + }.Build() + File_client_proto = out.File + file_client_proto_goTypes = nil + file_client_proto_depIdxs = nil +} diff --git a/common/proto/code.pb.go b/common/proto/pb/code.pb.go similarity index 88% rename from common/proto/code.pb.go rename to common/proto/pb/code.pb.go index 27f17ce..f4dcb2d 100644 --- a/common/proto/code.pb.go +++ b/common/proto/pb/code.pb.go @@ -4,7 +4,7 @@ // protoc v6.31.0 // source: code.proto -package proto +package pb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -24,19 +24,19 @@ const ( type ErrCode int32 const ( - ErrCode_OK ErrCode = 0 - ErrCode_LoginFail ErrCode = 1 // 登陆失败 + ErrCode_EC_OK ErrCode = 0 + ErrCode_EC_LoginDiffLoc ErrCode = 1 // 帐号在其它地方登陆 ) // Enum value maps for ErrCode. var ( ErrCode_name = map[int32]string{ - 0: "OK", - 1: "LoginFail", + 0: "EC_OK", + 1: "EC_LoginDiffLoc", } ErrCode_value = map[string]int32{ - "OK": 0, - "LoginFail": 1, + "EC_OK": 0, + "EC_LoginDiffLoc": 1, } ) @@ -72,10 +72,10 @@ var File_code_proto protoreflect.FileDescriptor const file_code_proto_rawDesc = "" + "\n" + "\n" + - "code.proto\x12\binternal* \n" + - "\aErrCode\x12\x06\n" + - "\x02OK\x10\x00\x12\r\n" + - "\tLoginFail\x10\x01B\x0eZ\fcommon/protob\x06proto3" + "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" var ( file_code_proto_rawDescOnce sync.Once @@ -91,7 +91,7 @@ func file_code_proto_rawDescGZIP() []byte { var file_code_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_code_proto_goTypes = []any{ - (ErrCode)(0), // 0: internal.ErrCode + (ErrCode)(0), // 0: pb.ErrCode } var file_code_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type diff --git a/common/proto/pb/login.pb.go b/common/proto/pb/login.pb.go new file mode 100644 index 0000000..6d06fef --- /dev/null +++ b/common/proto/pb/login.pb.go @@ -0,0 +1,457 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v6.31.0 +// source: login.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 LoginMsgId int32 + +const ( + LoginMsgId_Unknown LoginMsgId = 0 + LoginMsgId_C2SUserLogin LoginMsgId = 1 // 玩家登陆 + LoginMsgId_S2SUserLogin 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: "S2SUserLogin", + 3: "NtfUserOnline", + 4: "C2SUserLogout", + 5: "S2CUserLogout", + 6: "NtfUserOffline", + } + LoginMsgId_value = map[string]int32{ + "Unknown": 0, + "C2SUserLogin": 1, + "S2SUserLogin": 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 { + 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 + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` // 版本 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *C2SUserLoginMsg) Reset() { + *x = C2SUserLoginMsg{} + mi := &file_login_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *C2SUserLoginMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*C2SUserLoginMsg) ProtoMessage() {} + +func (x *C2SUserLoginMsg) ProtoReflect() protoreflect.Message { + mi := &file_login_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 C2SUserLoginMsg.ProtoReflect.Descriptor instead. +func (*C2SUserLoginMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{0} +} + +func (x *C2SUserLoginMsg) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *C2SUserLoginMsg) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +func (x *C2SUserLoginMsg) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +type S2CUserLoginMsg 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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *S2CUserLoginMsg) Reset() { + *x = S2CUserLoginMsg{} + mi := &file_login_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *S2CUserLoginMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*S2CUserLoginMsg) ProtoMessage() {} + +func (x *S2CUserLoginMsg) ProtoReflect() protoreflect.Message { + mi := &file_login_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 S2CUserLoginMsg.ProtoReflect.Descriptor instead. +func (*S2CUserLoginMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{1} +} + +func (x *S2CUserLoginMsg) GetCode() ErrCode { + if x != nil { + return x.Code + } + return ErrCode_EC_OK +} + +func (x *S2CUserLoginMsg) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +// 上线通知 +type NtfUserOnlineMsg 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{} + mi := &file_login_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NtfUserOnlineMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NtfUserOnlineMsg) ProtoMessage() {} + +func (x *NtfUserOnlineMsg) ProtoReflect() protoreflect.Message { + mi := &file_login_proto_msgTypes[2] + 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 NtfUserOnlineMsg.ProtoReflect.Descriptor instead. +func (*NtfUserOnlineMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{2} +} + +func (x *NtfUserOnlineMsg) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +// 玩家登陆 +type C2SUserLogoutMsg struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *C2SUserLogoutMsg) Reset() { + *x = C2SUserLogoutMsg{} + mi := &file_login_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *C2SUserLogoutMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*C2SUserLogoutMsg) ProtoMessage() {} + +func (x *C2SUserLogoutMsg) 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 C2SUserLogoutMsg.ProtoReflect.Descriptor instead. +func (*C2SUserLogoutMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{3} +} + +type S2CUserLogoutMsg 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{} + mi := &file_login_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *S2CUserLogoutMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*S2CUserLogoutMsg) ProtoMessage() {} + +func (x *S2CUserLogoutMsg) ProtoReflect() protoreflect.Message { + mi := &file_login_proto_msgTypes[4] + 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 S2CUserLogoutMsg.ProtoReflect.Descriptor instead. +func (*S2CUserLogoutMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{4} +} + +func (x *S2CUserLogoutMsg) GetCode() ErrCode { + if x != nil { + return x.Code + } + return ErrCode_EC_OK +} + +// 下线通知 +type NtfUserOfflineMsg 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{} + mi := &file_login_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NtfUserOfflineMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NtfUserOfflineMsg) ProtoMessage() {} + +func (x *NtfUserOfflineMsg) ProtoReflect() protoreflect.Message { + mi := &file_login_proto_msgTypes[5] + 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 NtfUserOfflineMsg.ProtoReflect.Descriptor instead. +func (*NtfUserOfflineMsg) Descriptor() ([]byte, []int) { + return file_login_proto_rawDescGZIP(), []int{5} +} + +func (x *NtfUserOfflineMsg) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +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" + + "\busername\x18\x01 \x01(\tR\busername\x12\x14\n" + + "\x05token\x18\x02 \x01(\tR\x05token\x12\x18\n" + + "\aversion\x18\x03 \x01(\tR\aversion\"K\n" + + "\x0fS2CUserLoginMsg\x12\x1f\n" + + "\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"+\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" + + "\fS2SUserLogin\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" + +var ( + file_login_proto_rawDescOnce sync.Once + file_login_proto_rawDescData []byte +) + +func file_login_proto_rawDescGZIP() []byte { + file_login_proto_rawDescOnce.Do(func() { + file_login_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc))) + }) + 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 +} +var file_login_proto_depIdxs = []int32{ + 7, // 0: pb.S2CUserLoginMsg.code:type_name -> pb.ErrCode + 7, // 1: pb.S2CUserLogoutMsg.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 + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_login_proto_init() } +func file_login_proto_init() { + if File_login_proto != nil { + return + } + file_code_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_login_proto_rawDesc), len(file_login_proto_rawDesc)), + NumEnums: 1, + 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 + file_login_proto_goTypes = nil + file_login_proto_depIdxs = nil +} diff --git a/common/proto/pb/service.pb.go b/common/proto/pb/service.pb.go new file mode 100644 index 0000000..be5fc08 --- /dev/null +++ b/common/proto/pb/service.pb.go @@ -0,0 +1,129 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v6.31.0 +// source: service.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 ServiceTypeId int32 + +const ( + ServiceTypeId_STI_Unknown ServiceTypeId = 0 + ServiceTypeId_STI_Gate ServiceTypeId = 1000 // 网关id + ServiceTypeId_STI_Login ServiceTypeId = 1001 // 登陆服 +) + +// Enum value maps for ServiceTypeId. +var ( + ServiceTypeId_name = map[int32]string{ + 0: "STI_Unknown", + 1000: "STI_Gate", + 1001: "STI_Login", + } + ServiceTypeId_value = map[string]int32{ + "STI_Unknown": 0, + "STI_Gate": 1000, + "STI_Login": 1001, + } +) + +func (x ServiceTypeId) Enum() *ServiceTypeId { + p := new(ServiceTypeId) + *p = x + return p +} + +func (x ServiceTypeId) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ServiceTypeId) Descriptor() protoreflect.EnumDescriptor { + return file_service_proto_enumTypes[0].Descriptor() +} + +func (ServiceTypeId) Type() protoreflect.EnumType { + return &file_service_proto_enumTypes[0] +} + +func (x ServiceTypeId) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ServiceTypeId.Descriptor instead. +func (ServiceTypeId) EnumDescriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{0} +} + +var File_service_proto protoreflect.FileDescriptor + +const file_service_proto_rawDesc = "" + + "\n" + + "\rservice.proto\x12\x02pb*?\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" + +var ( + file_service_proto_rawDescOnce sync.Once + file_service_proto_rawDescData []byte +) + +func file_service_proto_rawDescGZIP() []byte { + file_service_proto_rawDescOnce.Do(func() { + file_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_proto_rawDesc), len(file_service_proto_rawDesc))) + }) + return file_service_proto_rawDescData +} + +var file_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_service_proto_goTypes = []any{ + (ServiceTypeId)(0), // 0: pb.ServiceTypeId +} +var file_service_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_service_proto_init() } +func file_service_proto_init() { + if File_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_proto_rawDesc), len(file_service_proto_rawDesc)), + NumEnums: 1, + NumMessages: 0, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_service_proto_goTypes, + DependencyIndexes: file_service_proto_depIdxs, + EnumInfos: file_service_proto_enumTypes, + }.Build() + File_service_proto = out.File + file_service_proto_goTypes = nil + file_service_proto_depIdxs = nil +} diff --git a/common/testHelper/testHelper.go b/common/testHelper/testHelper.go new file mode 100644 index 0000000..9240d40 --- /dev/null +++ b/common/testHelper/testHelper.go @@ -0,0 +1,7 @@ +package testHelper + +const ( + Host = "114.132.124.145" + RedisPort = "6379" + RedisPassword = "fox379@@zyxi" +) diff --git a/common/topicName/topicName.go b/common/topicName/topicName.go index e793272..b9f02e5 100644 --- a/common/topicName/topicName.go +++ b/common/topicName/topicName.go @@ -1,6 +1,8 @@ package topicName const ( - UserLogin = "user.login" - UserOffline = "user.offline" + //extTopic = ".topic" + //extGroup = ".group" + UserLogin = "user.login.topic" + UserOffline = "user.offline.topic" ) diff --git a/common/utils/marshal.go b/common/utils/marshal.go new file mode 100644 index 0000000..00e428e --- /dev/null +++ b/common/utils/marshal.go @@ -0,0 +1,29 @@ +package utils + +import ( + "encoding/json" + "fmt" + "time" +) + +const ( + timeFormat = "2006-01-02 15:04:05" +) + +func Marshal(a any) string { + s, _ := json.Marshal(a) + return string(s) +} + +type Time time.Time + +func (t Time) MarshalJSON() ([]byte, error) { + var stamp = fmt.Sprintf("\"%s\"", time.Time(t).Format(timeFormat)) + return []byte(stamp), nil +} + +func (t *Time) UnmarshalJSON(data []byte) error { + now, err := time.ParseInLocation(`"`+timeFormat+`"`, string(data), time.Local) + *t = Time(now) + return err +} diff --git a/server/gate/model/db.go b/server/gate/model/db.go new file mode 100644 index 0000000..478e9b3 --- /dev/null +++ b/server/gate/model/db.go @@ -0,0 +1,19 @@ +package model + +import ( + "game/server/gate/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 + } +} diff --git a/server/gate/model/userGate.go b/server/gate/model/userGate.go new file mode 100644 index 0000000..69ecdf5 --- /dev/null +++ b/server/gate/model/userGate.go @@ -0,0 +1,45 @@ +package model + +import ( + "context" + "encoding/json" + "fmt" + "game/common/utils" + "github.com/go-redis/redis/v8" + "time" +) + +type UserGate struct { + GateName string `json:"gate_name"` + Token string `json:"token"` + OnlineTime utils.Time `json:"online"` + rdb *redis.Client +} + +func NewUserGate() *UserGate { + return &UserGate{rdb: UserRedis} +} + +func (u *UserGate) key(userId int64, gateId string) string { + return fmt.Sprintf("gateway:%v:%v", gateId, userId) +} + +func (u *UserGate) Set(userId int64, gateId string, token string) { + u.GateName = gateId + u.Token = token + u.OnlineTime = utils.Time(time.Now()) + u.rdb.Set(context.Background(), u.key(userId, gateId), utils.Marshal(u), time.Hour*24) +} + +func (u *UserGate) Get(userId int64, gateId string) (*UserGate, error) { + s, err := u.rdb.Get(context.Background(), u.key(userId, gateId)).Result() + if err != nil { + return u, err + } + err = json.Unmarshal([]byte(s), u) + return u, err +} + +func (u *UserGate) Del(userId int64, gateId string) { + _, _ = u.rdb.Del(context.Background(), u.key(userId, gateId)).Result() +} diff --git a/server/gate/model/userGate_test.go b/server/gate/model/userGate_test.go new file mode 100644 index 0000000..46216ea --- /dev/null +++ b/server/gate/model/userGate_test.go @@ -0,0 +1,29 @@ +package model + +import ( + "game/common/testHelper" + "game/common/utils" + "github.com/fox/fox/db" + "testing" +) + +const ( + userId = 1111 + gateId = "gate-1" + token = "token" +) + +func TestUserGate(t *testing.T) { + UserRedis, err = db.InitRedis(testHelper.RedisPassword, testHelper.Host, testHelper.RedisPort, 0) + if err != nil { + t.Fatal(err) + } + var ug *UserGate + ug, err = NewUserGate().Get(userId, gateId) + if err != nil { + t.Log(err) + ug.Set(userId, gateId, token) + ug, _ = NewUserGate().Get(userId, gateId) + } + t.Logf("user_gate:%v", utils.Marshal(ug)) +} diff --git a/server/gate/server/service.go b/server/gate/server/service.go index a9a62ee..1b75dbb 100644 --- a/server/gate/server/service.go +++ b/server/gate/server/service.go @@ -2,15 +2,22 @@ package server import ( "fmt" + "game/common/proto/ipb" + "game/common/proto/pb" "game/common/serviceName" + "game/common/topicName" + "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/service" "github.com/fox/fox/ws" + "github.com/fox/fox/xrand" + "github.com/golang/protobuf/proto" ) -var Gate *GateService +var Gates []*GateService type GateService struct { *service.NatsService @@ -19,18 +26,28 @@ type GateService struct { } func Init() { - Gate = newGateService() + for i := 0; i < config.Command.ServiceNum; i++ { + sid := config.Command.ServiceId + i + if gate := newGateService(sid); gate != nil { + Gates = append(Gates, gate) + } + } } func Stop() { - Gate.NotifyStop() - Gate.WaitStop() + for _, gate := range Gates { + gate.NotifyStop() + } + for _, gate := range Gates { + gate.WaitStop() + } } -func newGateService() *GateService { +func newGateService(serviceId int) *GateService { var err error s := new(GateService) - if s.NatsService, err = service.NewNatsService(serviceName.Gate, "1", s, config.Cfg.Nats.Address...); err != nil { + sName := fmt.Sprintf("%v-%d", serviceName.Gate, serviceId) + if s.NatsService, err = service.NewNatsService(serviceName.Gate, sName, s, config.Cfg.Nats.Address...); err != nil { log.Fatal(err.Error()) return nil } @@ -43,6 +60,7 @@ func newGateService() *GateService { 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: "", @@ -80,16 +98,106 @@ func (s *GateService) OnStop() { log.Debug("OnStop") } +// 通过handler转发消息 func (s *GateService) OnMessage(msg []byte) error { log.Debug(s.Log("on message:%v", string(msg))) return nil } -func (s *GateService) WsOnMessage(conn ws.IConn, msg []byte) { - - log.Debug(s.Log("on message:%v", string(msg))) +func (s *GateService) findService(serviceTypeId pb.ServiceTypeId) *etcd.ServiceNode { + var nodes []*etcd.ServiceNode + var newVer string + s.etcdService.GetNodes().Range(func(_, value interface{}) bool { + if node, ok := value.(*etcd.ServiceNode); ok && node.TypeId == int(serviceTypeId) { + if newVer < node.Version { + newVer = node.Version + } + nodes = append(nodes, node) + } + return true + }) + var newNodes []*etcd.ServiceNode + for _, node := range nodes { + if node.Version == newVer { + newNodes = append(newNodes, node) + } + } + if len(newNodes) == 0 { + return nil + } + return nodes[xrand.IntN(len(nodes))] } +/* +查找topic,根据serviceTypeId以及玩家id查找玩家过往访问该服务的节点,优先使用原节点 +*/ +func (s *GateService) findTopic(userId int64, serviceTypeId pb.ServiceTypeId) string { + if userId != 0 { + if sName, ok := userServiceMgr.FindServiceName(userId, serviceTypeId); ok { + return service.TopicEx(sName) + } + } + if sNode := s.findService(serviceTypeId); sNode != nil { + return service.TopicEx(sNode.Name) + } + return "" +} + +// 运行在conn的read协程里 +func (s *GateService) WsOnMessage(conn ws.IConn, data []byte) { + msg := &pb.ClientMsg{} + if err := proto.Unmarshal(data, msg); err != nil { + log.Error(err.Error()) + return + } + if topic := s.findTopic(conn.UserId(), msg.ServiceId); topic != "" { + iMsg := &ipb.InternalMsg{ConnId: conn.Id(), UserId: conn.UserId(), MsgId: msg.MsgId, Msg: msg.Data} + dMsg, _ := proto.Marshal(iMsg) + _ = s.Send(topic, dMsg) + } + log.Debug(s.Log("client to gate:%v", utils.Marshal(msg))) +} + +// 向内部服务发送消息 +func (s *GateService) SendServiceData(topic string, conn ws.IConn, msgId int32, data []byte) { + iMsg := &ipb.InternalMsg{ConnId: conn.Id(), UserId: conn.UserId(), MsgId: msgId, Msg: data} + dMsg, _ := proto.Marshal(iMsg) + _ = s.Send(topic, dMsg) +} + +// 向内部服务发送消息 +func (s *GateService) SendServiceMsg(topic string, conn ws.IConn, msgId int32, msg proto.Message) { + iMsg := &ipb.InternalMsg{ConnId: conn.Id(), UserId: conn.UserId(), MsgId: msgId} + iMsg.Msg, _ = proto.Marshal(msg) + dMsg, _ := proto.Marshal(iMsg) + _ = s.Send(topic, dMsg) +} + +// 向玩家发送消息 +func (s *GateService) SendClientMsg(conn ws.IConn, msgId int32, msg proto.Message) { + cMsg := &pb.ClientMsg{MsgId: msgId} + cMsg.Data, _ = proto.Marshal(msg) + dMsg, _ := proto.Marshal(cMsg) + _ = conn.SendMsg(dMsg) +} + +/* +todo:针对顶号的情况,由其它网关通知本网关向玩家发送下线消息,玩家关闭连接后,触发WsOnDisconnect,此时WsOnDisconnect鉴定时顶号后不需要做任务特殊处理 +*/ func (s *GateService) WsOnDisconnect(conn ws.IConn) { - log.Debug(s.Log("on message:%v", string(msg))) + if conn.UserId() > 0 { + userServiceMgr.CleanUser(conn.UserId()) + ug, err := model.NewUserGate().Get(conn.UserId(), s.Name()) + if err != nil { + log.Error(err.Error()) + } else { + // 相同网关,则为正常下线,删除redis信息然后向内网广播下线 + // 不同网关,异地登陆顶号 todo:异地登陆顶号,由其它网关通知本网关向玩家发送下线消息,并主动关闭连接,不广播下线消息,不会触发 + if ug.GateName == s.Name() { + model.NewUserGate().Del(conn.UserId(), s.Name()) + s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.LoginMsgId_NtfUserOffline), &pb.NtfUserOfflineMsg{UserId: conn.UserId()}) + } + } + log.Debug(s.Log("user:%v disconnect", conn.UserId())) + } } diff --git a/server/gate/server/userService.go b/server/gate/server/userService.go new file mode 100644 index 0000000..2a1ba39 --- /dev/null +++ b/server/gate/server/userService.go @@ -0,0 +1,54 @@ +package server + +import ( + "fmt" + "game/common/proto/pb" + "strings" + "sync" +) + +var userServiceMgr userServiceManager + +/* +记录玩家访问过的节点信息,玩家下线后清除相关信息,比如玩家在某个玩法服里掉线,重连后要回到该房间,应由对应的服务节点主动将玩家拉回房间 +*/ +type userServiceManager struct { + inService sync.Map // key:userId+service_type_id value:service_name +} + +func (m *userServiceManager) makeKey(userId int64, typeId pb.ServiceTypeId) string { + return fmt.Sprintf("%s_%d", userId, typeId) +} + +func (m *userServiceManager) Add(userId int64, typeId pb.ServiceTypeId, serviceName string) { + k := m.makeKey(userId, typeId) + m.inService.Store(k, serviceName) +} + +// 玩家下线,清除他呆过的所有服务节点信息 +func (m *userServiceManager) CleanUser(userId int64) { + var del []string + m.inService.Range(func(k, v interface{}) bool { + userServiceType := k.(string) + if strings.Contains(userServiceType, fmt.Sprintf("%d", userId)) { + del = append(del, userServiceType) + } + return true + }) + for _, k := range del { + m.inService.Delete(k) + } +} + +// todo:要考虑到旧服务可能已关闭,这里要访问etcd中是否有该服务节点,最好采用订阅机制,让etcd变动时清除对应服务节点 +func (m *userServiceManager) FindServiceName(userId int64, typeId pb.ServiceTypeId) (serviceName string, ok bool) { + var v any + if v, ok = m.inService.Load(m.makeKey(userId, typeId)); ok { + serviceName = v.(string) + } + return +} + +func (m *userServiceManager) Del(userId int64, typeId pb.ServiceTypeId) { + m.inService.Delete(m.makeKey(userId, typeId)) +}