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