网关路由消息规则,还需要完善

This commit is contained in:
liuxiaobo 2025-05-26 20:12:45 +08:00
parent 491e45d7cf
commit 0676c23c28
21 changed files with 1169 additions and 301 deletions

View File

@ -4,6 +4,7 @@ type Common[T any] struct {
ServiceType int `json:"service_type"` ServiceType int `json:"service_type"`
Logger Logger `json:"logger"` Logger Logger `json:"logger"`
Etcd Etcd `json:"etcd"` Etcd Etcd `json:"etcd"`
Redis Redis `json:"redis"`
Nats Nats `json:"nats"` Nats Nats `json:"nats"`
Special *T `json:"special"` Special *T `json:"special"`
} }

View File

@ -6,6 +6,7 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"game/common/testHelper"
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
) )
@ -16,6 +17,10 @@ const (
etcdAddress = "114.132.124.145:2379" etcdAddress = "114.132.124.145:2379"
natsKey = "nats_config" natsKey = "nats_config"
natsAddress = "nats://114.132.124.145:4222" 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 { 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 ret resultT[T]
var comm Common[T] var comm Common[T]
comm.Special = &ret.Value comm.Special = &ret.Value
// 初始化etcd
s, err := rd.Get(context.Background(), etcdKey).Result() s, err := rd.Get(context.Background(), etcdKey).Result()
if err != nil && !errors.Is(err, redis.Nil) { if err != nil && !errors.Is(err, redis.Nil) {
log.FatalF("init config:%v", err) log.FatalF("init config:%v", err)
@ -61,6 +67,8 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) {
} else { } else {
err = json.Unmarshal([]byte(s), &comm.Etcd) err = json.Unmarshal([]byte(s), &comm.Etcd)
} }
// 初始化nats
s, err = rd.Get(context.Background(), natsKey).Result() s, err = rd.Get(context.Background(), natsKey).Result()
if err != nil && !errors.Is(err, redis.Nil) { if err != nil && !errors.Is(err, redis.Nil) {
log.FatalF("init config:%v", err) log.FatalF("init config:%v", err)
@ -75,6 +83,22 @@ func LoadCommonConfig[T any](rd *redis.Client) (*Common[T], error) {
} else { } else {
err = json.Unmarshal([]byte(s), &comm.Nats) 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 return &comm, nil
} }

View File

@ -1,19 +1,20 @@
syntax = "proto3"; syntax = "proto3";
package internal; package ipb;
option go_package = "common/proto/internal"; option go_package = "common/proto/ipb";
enum MsgId enum MsgId
{ {
Unknown = 0; Unknown = 0;
Internal = -1; // Internal = -1; // id
} }
message InternalMsg message InternalMsg
{ {
int64 user_id = 1; // id uint32 conn_id = 1; // user_idconn_id
int32 msg_id = 2; // id int64 user_id = 2; // id
bytes msg = 3; // int32 msg_id = 3; // id
bytes msg = 4; //
} }
// //

15
common/pb/client.proto Normal file
View File

@ -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; //
}

View File

@ -1,11 +1,11 @@
syntax = "proto3"; syntax = "proto3";
package internal; package pb;
option go_package = "common/proto"; option go_package = "common/proto/pb";
enum ErrCode enum ErrCode
{ {
OK = 0; EC_OK = 0;
LoginFail = 1; // EC_LoginDiffLoc = 1; //
} }

View File

@ -1,27 +1,55 @@
syntax = "proto3"; syntax = "proto3";
package internal; package pb;
option go_package = "common/proto"; option go_package = "common/proto/pb";
import "code.proto"; import "code.proto";
enum LoginMsgId enum LoginMsgId
{ {
Unknown = 0; Unknown = 0;
C2SLogin = 1; // C2SUserLogin = 1; //
S2SUserLogin = 2;
NtfUserOnline = 3;
C2SUserLogout = 4;
S2CUserLogout = 5;
NtfUserOffline = 6;
} }
// //
message C2SLoginMsg message C2SUserLoginMsg
{ {
string username = 1; // string username = 1; //
string token = 2; // token string token = 2; // token
string version = 3; // string version = 3; //
} }
message S2CLoginMsg message S2CUserLoginMsg
{ {
ErrCode code = 1; 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
}

12
common/pb/service.proto Normal file
View File

@ -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; //
}

View File

@ -4,7 +4,7 @@
// protoc v6.31.0 // protoc v6.31.0
// source: internal.proto // source: internal.proto
package internal package ipb
import ( import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@ -25,7 +25,7 @@ type MsgId int32
const ( const (
MsgId_Unknown MsgId = 0 MsgId_Unknown MsgId = 0
MsgId_Internal MsgId = -1 // 玩家申请进入房间 MsgId_Internal MsgId = -1 // 内部消息id
) )
// Enum value maps for MsgId. // Enum value maps for MsgId.
@ -69,9 +69,10 @@ func (MsgId) EnumDescriptor() ([]byte, []int) {
type InternalMsg struct { type InternalMsg struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id ConnId uint32 `protobuf:"varint,1,opt,name=conn_id,json=connId,proto3" json:"conn_id,omitempty"` // 刚登陆时没有user_id只有conn_id
MsgId int32 `protobuf:"varint,2,opt,name=msg_id,json=msgId,proto3" json:"msg_id,omitempty"` // 消息id UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 玩家id
Msg []byte `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` // 消息 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 unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
@ -106,6 +107,13 @@ func (*InternalMsg) Descriptor() ([]byte, []int) {
return file_internal_proto_rawDescGZIP(), []int{0} 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 { func (x *InternalMsg) GetUserId() int64 {
if x != nil { if x != nil {
return x.UserId return x.UserId
@ -200,11 +208,12 @@ var File_internal_proto protoreflect.FileDescriptor
const file_internal_proto_rawDesc = "" + const file_internal_proto_rawDesc = "" +
"\n" + "\n" +
"\x0einternal.proto\x12\binternal\"O\n" + "\x0einternal.proto\x12\x03ipb\"h\n" +
"\vInternalMsg\x12\x17\n" + "\vInternalMsg\x12\x17\n" +
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x15\n" + "\aconn_id\x18\x01 \x01(\rR\x06connId\x12\x17\n" +
"\x06msg_id\x18\x02 \x01(\x05R\x05msgId\x12\x10\n" + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x15\n" +
"\x03msg\x18\x03 \x01(\fR\x03msg\"q\n" + "\x06msg_id\x18\x03 \x01(\x05R\x05msgId\x12\x10\n" +
"\x03msg\x18\x04 \x01(\fR\x03msg\"q\n" +
"\n" + "\n" +
"C2SMessage\x12!\n" + "C2SMessage\x12!\n" +
"\fservice_type\x18\x01 \x01(\x05R\vserviceType\x12\x15\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" + "\x03msg\x18\x04 \x01(\fR\x03msg*+\n" +
"\x05MsgId\x12\v\n" + "\x05MsgId\x12\v\n" +
"\aUnknown\x10\x00\x12\x15\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 ( var (
file_internal_proto_rawDescOnce sync.Once 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_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_internal_proto_goTypes = []any{ var file_internal_proto_goTypes = []any{
(MsgId)(0), // 0: internal.MsgId (MsgId)(0), // 0: ipb.MsgId
(*InternalMsg)(nil), // 1: internal.InternalMsg (*InternalMsg)(nil), // 1: ipb.InternalMsg
(*C2SMessage)(nil), // 2: internal.C2SMessage (*C2SMessage)(nil), // 2: ipb.C2SMessage
} }
var file_internal_proto_depIdxs = []int32{ var file_internal_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method output_type

View File

@ -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
}

View File

@ -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
}

View File

@ -4,7 +4,7 @@
// protoc v6.31.0 // protoc v6.31.0
// source: code.proto // source: code.proto
package proto package pb
import ( import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@ -24,19 +24,19 @@ const (
type ErrCode int32 type ErrCode int32
const ( const (
ErrCode_OK ErrCode = 0 ErrCode_EC_OK ErrCode = 0
ErrCode_LoginFail ErrCode = 1 // 登陆失败 ErrCode_EC_LoginDiffLoc ErrCode = 1 // 帐号在其它地方登陆
) )
// Enum value maps for ErrCode. // Enum value maps for ErrCode.
var ( var (
ErrCode_name = map[int32]string{ ErrCode_name = map[int32]string{
0: "OK", 0: "EC_OK",
1: "LoginFail", 1: "EC_LoginDiffLoc",
} }
ErrCode_value = map[string]int32{ ErrCode_value = map[string]int32{
"OK": 0, "EC_OK": 0,
"LoginFail": 1, "EC_LoginDiffLoc": 1,
} }
) )
@ -72,10 +72,10 @@ var File_code_proto protoreflect.FileDescriptor
const file_code_proto_rawDesc = "" + const file_code_proto_rawDesc = "" +
"\n" + "\n" +
"\n" + "\n" +
"code.proto\x12\binternal* \n" + "code.proto\x12\x02pb*)\n" +
"\aErrCode\x12\x06\n" + "\aErrCode\x12\t\n" +
"\x02OK\x10\x00\x12\r\n" + "\x05EC_OK\x10\x00\x12\x13\n" +
"\tLoginFail\x10\x01B\x0eZ\fcommon/protob\x06proto3" "\x0fEC_LoginDiffLoc\x10\x01B\x11Z\x0fcommon/proto/pbb\x06proto3"
var ( var (
file_code_proto_rawDescOnce sync.Once 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_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_code_proto_goTypes = []any{ var file_code_proto_goTypes = []any{
(ErrCode)(0), // 0: internal.ErrCode (ErrCode)(0), // 0: pb.ErrCode
} }
var file_code_proto_depIdxs = []int32{ var file_code_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method output_type

457
common/proto/pb/login.pb.go Normal file
View File

@ -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
}

View File

@ -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
}

View File

@ -0,0 +1,7 @@
package testHelper
const (
Host = "114.132.124.145"
RedisPort = "6379"
RedisPassword = "fox379@@zyxi"
)

View File

@ -1,6 +1,8 @@
package topicName package topicName
const ( const (
UserLogin = "user.login" //extTopic = ".topic"
UserOffline = "user.offline" //extGroup = ".group"
UserLogin = "user.login.topic"
UserOffline = "user.offline.topic"
) )

29
common/utils/marshal.go Normal file
View File

@ -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
}

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

@ -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
}
}

View File

@ -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()
}

View File

@ -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))
}

View File

@ -2,15 +2,22 @@ package server
import ( import (
"fmt" "fmt"
"game/common/proto/ipb"
"game/common/proto/pb"
"game/common/serviceName" "game/common/serviceName"
"game/common/topicName"
"game/common/utils"
"game/server/gate/config" "game/server/gate/config"
"game/server/gate/model"
"github.com/fox/fox/etcd" "github.com/fox/fox/etcd"
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/fox/fox/service" "github.com/fox/fox/service"
"github.com/fox/fox/ws" "github.com/fox/fox/ws"
"github.com/fox/fox/xrand"
"github.com/golang/protobuf/proto"
) )
var Gate *GateService var Gates []*GateService
type GateService struct { type GateService struct {
*service.NatsService *service.NatsService
@ -19,18 +26,28 @@ type GateService struct {
} }
func Init() { 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() { func Stop() {
Gate.NotifyStop() for _, gate := range Gates {
Gate.WaitStop() gate.NotifyStop()
}
for _, gate := range Gates {
gate.WaitStop()
}
} }
func newGateService() *GateService { func newGateService(serviceId int) *GateService {
var err error var err error
s := new(GateService) 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()) log.Fatal(err.Error())
return nil return nil
} }
@ -43,6 +60,7 @@ func newGateService() *GateService {
wsAddress := fmt.Sprintf("%v:%v", config.Cfg.Special.Address, config.Cfg.Special.Port) wsAddress := fmt.Sprintf("%v:%v", config.Cfg.Special.Address, config.Cfg.Special.Port)
s.wss = ws.NewWsServer(wsAddress, s.WsOnMessage, s.WsOnDisconnect) s.wss = ws.NewWsServer(wsAddress, s.WsOnMessage, s.WsOnDisconnect)
endpoint := &etcd.ServiceNode{ endpoint := &etcd.ServiceNode{
TypeId: int(pb.ServiceTypeId_STI_Gate),
Name: s.Name(), Name: s.Name(),
Type: s.Type(), Type: s.Type(),
Address: "", Address: "",
@ -80,16 +98,106 @@ func (s *GateService) OnStop() {
log.Debug("OnStop") log.Debug("OnStop")
} }
// 通过handler转发消息
func (s *GateService) OnMessage(msg []byte) error { func (s *GateService) OnMessage(msg []byte) error {
log.Debug(s.Log("on message:%v", string(msg))) log.Debug(s.Log("on message:%v", string(msg)))
return nil return nil
} }
func (s *GateService) WsOnMessage(conn ws.IConn, msg []byte) { func (s *GateService) findService(serviceTypeId pb.ServiceTypeId) *etcd.ServiceNode {
var nodes []*etcd.ServiceNode
log.Debug(s.Log("on message:%v", string(msg))) 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) { 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()))
}
} }

View File

@ -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))
}