Files
bl/logic/controller/controller.go
昔念 081f990110 refactor(assets): 重构资产同步流程并添加宠物相关功能
- 移除了资产同步到私有 B 仓库的工作流
- 在玩家结构中添加了 IsFighting 字段
- 新增了宠物信息相关功能和数据结构
- 优化了地图进入和怪物刷新逻辑
- 调整了玩家登录和地图数据发送流程
- 重构了部分代码以提高可维护性和性能
2025-08-24 17:33:19 +08:00

228 lines
5.4 KiB
Go

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