Files
bl/logic/controller/controller.go
昔念 e25fe776eb refactor(common): 重构 Pack 函数并优化数据处理
- 重构了 Pack 函数,支持处理不同类型的 data 参数
- 优化了数据打包过程,使用反射处理结构体和切片
- 修改了 TomeeHeader 结构体,使用 EnumCommandID 类型
- 调整了 login 相关的结构体定义
- 优化了 main 函数中的数据处理逻辑
2025-06-27 00:30:15 +08:00

173 lines
4.5 KiB
Go

package controller
import (
"blazing/common/core"
"blazing/common/socket/cmd"
"blazing/common/socket/handler"
"blazing/logic/service"
"bytes"
"context"
"fmt"
"reflect"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/util/gconv"
"github.com/lunixbochs/struc"
"github.com/panjf2000/gnet/v2"
)
var maincontroller = NewController() //注入service
// 分发cmd逻辑实现Controller
type Controller struct {
}
func NewController() *Controller {
return &Controller{}
}
func parseCmd[T any](a T, data []byte) T {
// := info.NewLoginSidInfo()
struc.Unpack(bytes.NewBuffer(data), &a)
return a
//fmt.Println(pinfo)
//login.OnData_1001(pinfo, player)
//fmt.Println(data)
}
func init() { //默认初始化扫描
// 获取对象的反射值和类型
value := reflect.ValueOf(maincontroller)
// 获取类型
typ := value.Type()
for i := 0; i < typ.NumMethod(); i++ {
method := typ.Method(i)
// TODO 接收者 + 2个参数 一个是类型,一个是player
//method.Type.In(1) == reflect.TypeOf([]byte{}
// 获取方法值
methodValue := value.MethodByName(method.Name)
methodValue.Type().NumIn()
var func_cmd cmd.EnumCommandID
//params := []reflect.Value{}
//fmt.Println(methodValue.Type().NumIn())
// for i := 0; i < methodValue.Type().NumIn(); i++ {
// ttt := methodValue.Type().In(i)
// func_cmd = getcmd(ttt)
// }
// /ttt := methodValue.Type().In(0)
func_cmd = getcmd(methodValue.Type().In(0))
if !cmd.Isexist(cmd.CommandID, cmd.EnumCommandID(func_cmd)) {
fmt.Println("ID方法存在cmd未注册", func_cmd)
}
// fmt.Println(methodValue.Interface().(func(gnet.Conn, handler.TomeeHeader)))
_, ok := core.Maincmdcache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache
if ok { //方法已存在init
glog.Error(context.Background(), "方法已存在init,不会初始化后面的方法", func_cmd)
}
}
}
func getcmd(t reflect.Type) cmd.EnumCommandID {
// 处理指针类型
if t.Kind() == reflect.Ptr {
t = t.Elem() // 获取指针指向的类型
}
// 确保是结构体
if t.Kind() != reflect.Struct {
fmt.Println("非结构体类型")
return 0
}
// 遍历结构体字段
// fmt.Printf("结构体 %s 的字段信息:\n", t.Name())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// fmt.Printf("- 字段名: %s\n", field.Name)
if field.Type == reflect.TypeOf(handler.TomeeHeader{}) {
// fmt.Println(reflect.ValueOf(field))
return cmd.EnumCommandID(gconv.Uint32(field.Tag.Get("cmd")))
}
// fmt.Printf(" 类型: %v\n", field.Type)
// fmt.Printf(" 标签: %q\n", field.Tag)
// 递归处理嵌套结构体
if field.Type.Kind() == reflect.Struct ||
(field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) {
fmt.Println(" 嵌套结构体字段:")
nestedType := field.Type
if nestedType.Kind() == reflect.Ptr {
nestedType = nestedType.Elem()
}
getcmd(nestedType)
}
// fmt.Println()
}
return 0
}
// 遍历结构体方法并执行RECV_cmd
func Recv(c gnet.Conn, data handler.TomeeHeader) {
tt, ok := core.Maincmdcache.Load(data.CMD)
if !ok {
glog.Error(context.Background(), data.CMD, "cmd未注册")
return //TODO 待实现cmd未注册
}
cmdlister := tt.(reflect.Value)
// fmt.Println(cmdlister)
params := []reflect.Value{}
funct := cmdlister.Type().NumIn()
// 如果需要可设置的变量(用于修改值),创建指针并解引用
ptrValue := reflect.New(cmdlister.Type().In(0))
struc.Unpack(bytes.NewBuffer(data.Data), ptrValue)
// ttt := cmdlister.Type().In(0)
ptrValue1 := ptrValue.Elem()
switch funct {
case 1:
// struc.Unpack(bytes.NewBuffer(data), &a)
// return a
params = append(params, ptrValue1)
case 2:
params = append(params, ptrValue1, reflect.ValueOf(service.GetPlayer(c, data.UserID)))
}
ret := cmdlister.Call(params)
//core.Pack(c, cmd cmd.EnumCommandID, data any, iserror uint32)
switch ret[0].Interface().(type) { //TODO 待修改
case []byte: //原始包
c.Write(ret[0].Interface().([]byte)) //这里直接发送原始包,应该是已经拼接过的原始包,通常不同使用
//case uint32: //错误码 实际上这里包含在结构体里了 ,错误码应该构造在返回之前
default:
var data1 bytes.Buffer
struc.Pack(&data1, &data)
c.Write(data1.Bytes())
}
}