package controller import ( "blazing/common/data/entity" "blazing/common/socket/errorcode" "blazing/common/socket/handler" "blazing/cool" "blazing/logic/service" "os" "time" "bytes" "context" "fmt" "reflect" "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/util/gconv" "github.com/lunixbochs/struc" ) var Maincontroller = NewController() //注入service // 分发cmd逻辑实现Controller type Controller struct { Port uint16 RPCClient struct { Kick func(uint32) error RegisterLogic func(uint16, uint16) error } } type LogicClient struct { } func (h *LogicClient) KickPerson(a int) error { fmt.Println("检测到踢人请求", a) service.KickPlayer(uint32(a)) return nil } func (h *LogicClient) QuitSelf(a int) error { //TODO 这里待退出 fmt.Println("检测到退出请求") go func() { for { //entity.ConutPlayer() fmt.Println("当前在线人数", cool.ConutPlayer()) if cool.ConutPlayer() <= 0 { //执行退出逻辑 os.Exit(1) } <-time.After((50000)) } }() //service.KickPlayer(uint32(a)) return nil } 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() { //默认初始化扫描 // 解析命令行参数 cool.Config.PortBL = gcmd.GetOpt("port", "1").Uint16() // 获取对象的反射值和类型 value := reflect.ValueOf(Maincontroller) // 获取类型 typ := value.Type() for i := 0; i < typ.NumMethod(); i++ { method := typ.Method(i) methodValue := value.MethodByName(method.Name) fmt.Println("找到注册方法", method.Name) methodValue.Type().NumIn() var func_cmd = getcmd(methodValue.Type().In(0)) if func_cmd == 0 { //说明不是注册方法 glog.Warning(context.Background(), "方法参数必须是结构体", method.Name, "跳过注册") continue } if cool.Config.PortBL == 0 && func_cmd > 1000 { //判断login服务器 continue } if cool.Config.PortBL != 0 && func_cmd < 1000 { //判断login服务器 continue } glog.Debug(context.Background(), "注册方法", func_cmd, method.Name) // fmt.Println(methodValue.Interface().(func(gnet.Conn, handler.TomeeHeader))) _, ok := cool.CmdCache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache if ok { //方法已存在init glog.Error(context.Background(), "方法已存在init,不会初始化后面的方法", func_cmd) } } } func getcmd(t reflect.Type) uint32 { // 处理指针类型 if t.Kind() == reflect.Ptr { t = t.Elem() // 获取指针指向的类型 } // 确保是结构体 if t.Kind() != reflect.Struct { 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) //fmt.Printf(" 类型: %v\n", field.Type) if field.Type == reflect.TypeOf(handler.TomeeHeader{}) { // fmt.Println(reflect.ValueOf(field)) return gconv.Uint32(field.Tag.Get("cmd")) } if field.Type.Kind() == reflect.Struct || (field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) { nestedType := field.Type if nestedType.Kind() == reflect.Ptr { nestedType = nestedType.Elem() } getcmd(nestedType) } // fmt.Println() } return 0 } // 遍历结构体方法并执行RECV_cmd func Recv(c *entity.Conn, data handler.TomeeHeader) { cmdlister, ok := cool.CmdCache.Load(data.CMD) if !ok { glog.Error(context.Background(), data.CMD, "cmd未注册") return //TODO 待实现cmd未注册 } // fmt.Println(cmdlister) params := []reflect.Value{} //funct := cmdlister.Type().NumIn() // 如果需要可设置的变量(用于修改值),创建指针并解引用 ptrValue := reflect.New(cmdlister.Type().In(0).Elem()) tt1 := ptrValue.Elem().Addr().Interface() // fmt.Println(tt1) err := struc.Unpack(bytes.NewBuffer(data.Data), tt1) if err != nil { fmt.Println(err) } //fmt.Println(tt1) ptrValue1 := ptrValue.Elem().Addr() // 设置 Name 字段 nameField := ptrValue.Elem().Field(0) //首个为header if nameField.IsValid() && nameField.CanSet() { nameField.Set(reflect.ValueOf(data)) } if cmdlister.Type().In(1) == reflect.TypeOf(&entity.Player{}) { c1 := service.GetPlayer(c, data.UserID) err := c1.WaitForLoginWithCtx(context.Background()) if err != nil { fmt.Println("登录失败") } params = append(params, ptrValue1, reflect.ValueOf(c1)) } else { params = append(params, ptrValue1, reflect.ValueOf(c)) } ret := cmdlister.Call(params) if len(ret) <= 0 { //如果判断没有参数,那就说明这个包没有返回参数 return } aa, ok := ret[1].Interface().(errorcode.ErrorCode) //判断错误 data.Result = uint32(aa) if aa == -1 { return } if ok && aa != 0 { //这里实现回复错误包 cool.Loger.Error(context.Background(), aa.Code()) c.SendPack(data.Pack(nil)) return } data.Version = "7" glog.Debug(context.Background(), data.CMD, "回复数据") c.SendPack(data.Pack(ret[0].Interface())) }