diff --git a/src/server/game/external.go b/src/server/game/external.go index 32b1feda..3a85b10c 100644 --- a/src/server/game/external.go +++ b/src/server/game/external.go @@ -16,6 +16,7 @@ import ( "gitea.bywaystudios.com/pet_home/leaf/log" + "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "server/db" @@ -111,8 +112,12 @@ func HandleClientReq(args []interface{}) { case "ReqAdminInfo": // 后台接口 AdminProcess(m.GetFunc(), []interface{}{a, buf}) case "ReqLoginCode": - Detail := &msg.ReqLoginCode{} - proto.Unmarshal(buf, Detail) + detailMsg, err := UnmarshalProtoMessageByName(m.GetFunc(), buf) + if err != nil { + log.Error("unmarshal %s failed: %v", m.GetFunc(), err) + return + } + Detail := detailMsg.(*msg.ReqLoginCode) Code, err := GeneratedCode(Detail.TelPhone) ResLoginCode := &msg.ResLoginCode{} if err != nil { @@ -237,10 +242,13 @@ func HandleClientReq(args []interface{}) { p.(*Player).Recover(backup) //还原Player的数据 return } + detailMsg, err := UnmarshalProtoMessageByName(m.GetFunc(), buf) + str, _ := protojson.Marshal(detailMsg) p.(*Player).ProcessTrigger() p.(*Player).TeLog("func_exec_time", map[string]interface{}{ "method_name": m.GetFunc(), "exec_time": fmt.Sprintf("%v", time.Since(start)), + "proto": string(str), }) } } diff --git a/src/server/game/proto_factory.go b/src/server/game/proto_factory.go new file mode 100644 index 00000000..30be0252 --- /dev/null +++ b/src/server/game/proto_factory.go @@ -0,0 +1,63 @@ +package game + +import ( + "fmt" + "sync" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +var ( + protoMessageTypeCacheOnce sync.Once + protoMessageTypeByName sync.Map +) + +func buildProtoMessageTypeCache() { + protoregistry.GlobalTypes.RangeMessages(func(messageType protoreflect.MessageType) bool { + descriptor := messageType.Descriptor() + protoMessageTypeByName.Store(string(descriptor.FullName()), messageType) + shortName := string(descriptor.Name()) + if _, exists := protoMessageTypeByName.Load(shortName); !exists { + protoMessageTypeByName.Store(shortName, messageType) + } + return true + }) +} + +func FindProtoMessageTypeByName(name string) (protoreflect.MessageType, error) { + messageType, err := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(name)) + if err == nil { + return messageType, nil + } + + protoMessageTypeCacheOnce.Do(buildProtoMessageTypeCache) + if cachedType, ok := protoMessageTypeByName.Load(name); ok { + return cachedType.(protoreflect.MessageType), nil + } + + return nil, fmt.Errorf("protobuf message type not found: %s", name) +} + +func NewProtoMessageByName(name string) (proto.Message, error) { + messageType, err := FindProtoMessageTypeByName(name) + if err != nil { + return nil, err + } + + return messageType.New().Interface(), nil +} + +func UnmarshalProtoMessageByName(name string, data []byte) (proto.Message, error) { + message, err := NewProtoMessageByName(name) + if err != nil { + return nil, err + } + + if err := proto.Unmarshal(data, message); err != nil { + return nil, err + } + + return message, nil +}