refactor(logic): 重构逻辑模块
- 移除了 player.go 中的 SendPackBytes 方法 - 将 TomeeHeader 中的 CMDID 改为 CMD,类型从 uint32 改为 EnumCommandID - 删除了 controller 文件夹下的 service.go 和 login.go - 新增了 login 文件夹下的 PlayerLoginService.go - 优化了 main.go 中的 Start 函数,使用 controller.Recv 作为回调
This commit is contained in:
10
common/core/global.go
Normal file
10
common/core/global.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Mainplayer sync.Map //玩家数据
|
||||||
|
Maincmdcache sync.Map //命令缓存
|
||||||
|
)
|
||||||
67
common/core/pack.go
Normal file
67
common/core/pack.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/common/socket/cmd"
|
||||||
|
"blazing/common/socket/handler"
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/lunixbochs/struc"
|
||||||
|
"github.com/panjf2000/gnet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SendError(cmd cmd.EnumCommandID, data any) { //TODO发送错误码的实现
|
||||||
|
|
||||||
|
//序列化结构体取错误码,然后构造错误结构
|
||||||
|
|
||||||
|
//SEND ERROR 方法,通过error tag取到标签,然后error库内取参数
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendPack(c gnet.Conn, cmd cmd.EnumCommandID, data any) { //TODO 待测试
|
||||||
|
|
||||||
|
//t := reflect.TypeOf(data)
|
||||||
|
// var datar []byte
|
||||||
|
// var iserror uint32 = 0
|
||||||
|
// switch t.Kind() {
|
||||||
|
// case reflect.Slice:
|
||||||
|
// datar = data.([]byte)
|
||||||
|
// //p.Conn.Write(p.pack(cmd, data.([]byte))) //写入数据
|
||||||
|
|
||||||
|
// case reflect.Struct:
|
||||||
|
// var data1 bytes.Buffer
|
||||||
|
// struc.Pack(&data1, &data)
|
||||||
|
// datar = data1.Bytes()
|
||||||
|
// // p.Conn.Write(p.pack(cmd, data))
|
||||||
|
|
||||||
|
// case reflect.Uint32: //说明是错误码
|
||||||
|
|
||||||
|
// iserror = data.(uint32)
|
||||||
|
// default:
|
||||||
|
// // 可选:处理 nil 数据情况,直接返回
|
||||||
|
// datar = nil
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//c.Write(pack(packhead(userid uint32, cmd cmd.EnumCommandID, data []byte, iserror uint32)))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pack(userid uint32, cmd cmd.EnumCommandID, data []byte, iserror uint32) []byte { //组包
|
||||||
|
|
||||||
|
head1 := handler.TomeeHeader{
|
||||||
|
|
||||||
|
Len: uint32(len(data) + 17),
|
||||||
|
CMD: uint32(cmd),
|
||||||
|
Version: "7",
|
||||||
|
UserID: userid,
|
||||||
|
Result: iserror,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
|
||||||
|
if iserror != 0 { //如果存在错误码
|
||||||
|
head1.Data = nil
|
||||||
|
}
|
||||||
|
var data1 bytes.Buffer
|
||||||
|
struc.Pack(&data1, &head1)
|
||||||
|
return data1.Bytes()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/socket/cmd"
|
|
||||||
"blazing/common/socket/handler"
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/lunixbochs/struc"
|
|
||||||
"github.com/panjf2000/gnet/v2"
|
"github.com/panjf2000/gnet/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
UserID uint32 //用户ID
|
UserID uint32 //用户ID
|
||||||
Conn gnet.Conn
|
IsLogin bool //是否登录 //TODO 待实现登录包为第一个包,后续再发其他的包
|
||||||
|
Conn gnet.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlayerOption 定义配置 Player 的函数类型
|
// PlayerOption 定义配置 Player 的函数类型
|
||||||
@@ -41,18 +37,3 @@ func NewPlayer(opts ...PlayerOption) *Player {
|
|||||||
func (p *Player) GetUserID() uint32 {
|
func (p *Player) GetUserID() uint32 {
|
||||||
return p.UserID
|
return p.UserID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) SendPackBytes(cmd cmd.EnumCommandID, data []byte) { //组包
|
|
||||||
|
|
||||||
head1 := handler.TomeeHeader{}
|
|
||||||
head1.CMDID = uint32(cmd)
|
|
||||||
head1.Len = uint32(len(data) + 17)
|
|
||||||
head1.Version = "7"
|
|
||||||
head1.UserID = p.UserID
|
|
||||||
head1.Result = 0
|
|
||||||
var data1 bytes.Buffer
|
|
||||||
struc.Pack(&data1, head1)
|
|
||||||
p.Conn.Write(data1.Bytes()) //写入头部
|
|
||||||
p.Conn.Write(data) //写入数据
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type EnumValue struct {
|
|||||||
Value EnumCommandID
|
Value EnumCommandID
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
type EnumCommandID int
|
type EnumCommandID uint32
|
||||||
|
|
||||||
func Isexist(t any, value EnumCommandID) bool {
|
func Isexist(t any, value EnumCommandID) bool {
|
||||||
return enum.Contains(CommandID, value)
|
return enum.Contains(CommandID, value)
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import (
|
|||||||
// TomeeHeader 结构体字段定义
|
// TomeeHeader 结构体字段定义
|
||||||
type TomeeHeader struct {
|
type TomeeHeader struct {
|
||||||
Len uint32 `json:"len"`
|
Len uint32 `json:"len"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version" struc:"[1]byte"`
|
||||||
CMDID uint32 `json:"cmdId"`
|
CMD uint32 `json:"cmdId"`
|
||||||
UserID uint32 `json:"userId"`
|
UserID uint32 `json:"userId"`
|
||||||
//Error uint32 `json:"error" struc:"[0]pad"`
|
//Error uint32 `json:"error" struc:"[0]pad"`
|
||||||
|
|
||||||
Result uint32 `json:"result"`
|
Result uint32 `json:"result"`
|
||||||
Data []byte `json:"data" struc:"[0]pad"` //组包忽略此字段
|
Data []byte `json:"data"` //组包忽略此字段// struc:"[0]pad"
|
||||||
}
|
}
|
||||||
type TomeeHandler struct {
|
type TomeeHandler struct {
|
||||||
Callback func(conn gnet.Conn, data TomeeHeader)
|
Callback func(conn gnet.Conn, data TomeeHeader)
|
||||||
@@ -34,7 +34,7 @@ func (h *TomeeHandler) Handle(c gnet.Conn, data []byte) { //处理接收到的
|
|||||||
tempdata := bytearray.CreateByteArray(data)
|
tempdata := bytearray.CreateByteArray(data)
|
||||||
header.Len, _ = tempdata.ReadUInt32()
|
header.Len, _ = tempdata.ReadUInt32()
|
||||||
header.Version, _ = tempdata.ReadString(1)
|
header.Version, _ = tempdata.ReadString(1)
|
||||||
header.CMDID, _ = tempdata.ReadUInt32()
|
header.CMD, _ = tempdata.ReadUInt32()
|
||||||
header.UserID, _ = tempdata.ReadUInt32()
|
header.UserID, _ = tempdata.ReadUInt32()
|
||||||
|
|
||||||
header.Result, _ = tempdata.ReadUInt32()
|
header.Result, _ = tempdata.ReadUInt32()
|
||||||
|
|||||||
1
go.work
1
go.work
@@ -14,5 +14,6 @@ use (
|
|||||||
./modules/dict
|
./modules/dict
|
||||||
./modules/space
|
./modules/space
|
||||||
./modules/task
|
./modules/task
|
||||||
|
E:\newcode\seercode\tools\bytearray
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
167
logic/controller/controller.go
Normal file
167
logic/controller/controller.go
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
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 uint32
|
||||||
|
//params := []reflect.Value{}
|
||||||
|
//fmt.Println(methodValue.Type().NumIn())
|
||||||
|
for i := 0; i < methodValue.Type().NumIn(); i++ {
|
||||||
|
|
||||||
|
ttt := methodValue.Type().In(i)
|
||||||
|
|
||||||
|
func_cmd = gconv.Uint32(getcmd(ttt))
|
||||||
|
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
switch ret[0].Interface().(type) {
|
||||||
|
case []byte: //原始包
|
||||||
|
|
||||||
|
c.Write(ret[0].Interface().([]byte)) //这里直接发送原始包,应该是已经拼接过的原始包,通常不同使用
|
||||||
|
|
||||||
|
//case uint32: //错误码 实际上这里包含在结构体里了 ,错误码应该构造在返回之前
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
var data1 bytes.Buffer
|
||||||
|
struc.Pack(&data1, &data)
|
||||||
|
c.Write(data1.Bytes())
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/data/entity"
|
|
||||||
"blazing/logic/service/login"
|
"blazing/logic/service/login"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 处理命令: 1001
|
// 处理命令: 1001
|
||||||
func (h Controller) Login(data login.LoginSidInfo, player *entity.Player) interface{} {
|
func (h Controller) Login(data login.LoginSidInfo) interface{} { //这个时候player应该是空的
|
||||||
|
|
||||||
fmt.Println(login.CheakSession(data, player))
|
fmt.Println(login.CheakSession(data)) //检查结构体
|
||||||
|
|
||||||
t1, _ := hex.DecodeString("0000045D37000003E9000186A600000000000186A6683F89CF6E69656F0000000000000000000000000008000F00000000000000000000000000000000000000000000000000000001000001DB0000018B000000000000A8C000000000000000000000000000000000000000080001388000000001000000017FFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000000000000000000000000000000000064000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001FFFFFFFF000000004E4F4E4F0000000000000000000000000000000000000001000000010000000100000001000000010000000100000001000000000003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000100000064000000000000000000000000000000000000001F000000000000006400000000000093F4000093F4000000D5000000F7000000AD00000088000000920000008C0000009C00000000000000000000000000000000000000000000000000000004000027900000001B00004E6200000014000028380000002800004E3E0000002368493DC60000000000000000000000000000000000000000000100000000000000A937000007D1000186A600000000000186A66E69656F00000000000000000000000000000000000000000000000F0000000000000000000001DB0000018B0000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000")
|
t1, _ := hex.DecodeString("0000045D37000003E9000186A600000000000186A6683F89CF6E69656F0000000000000000000000000008000F00000000000000000000000000000000000000000000000000000001000001DB0000018B000000000000A8C000000000000000000000000000000000000000080001388000000001000000017FFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000000000000000000000000000000000064000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001FFFFFFFF000000004E4F4E4F0000000000000000000000000000000000000001000000010000000100000001000000010000000100000001000000000003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000100000064000000000000000000000000000000000000001F000000000000006400000000000093F4000093F4000000D5000000F7000000AD00000088000000920000008C0000009C00000000000000000000000000000000000000000000000000000004000027900000001B00004E6200000014000028380000002800004E3E0000002368493DC60000000000000000000000000000000000000000000100000000000000A937000007D1000186A600000000000186A66E69656F00000000000000000000000000000000000000000000000F0000000000000000000001DB0000018B0000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package controller
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/lunixbochs/struc"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 分发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)
|
|
||||||
}
|
|
||||||
186
logic/main.go
186
logic/main.go
@@ -1,208 +1,26 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
"github.com/lunixbochs/struc"
|
|
||||||
"github.com/panjf2000/gnet/v2"
|
|
||||||
|
|
||||||
"blazing/common/core/info"
|
|
||||||
"blazing/common/data/entity"
|
|
||||||
"blazing/common/socket"
|
"blazing/common/socket"
|
||||||
"blazing/common/socket/cmd"
|
|
||||||
"blazing/common/socket/handler"
|
"blazing/common/socket/handler"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
"blazing/logic/controller"
|
"blazing/logic/controller"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gctx"
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
maininfocodec = info.NewInfoCodec() //创建一个InfoCodec实例
|
|
||||||
maincontroller = controller.NewController() //注入service
|
|
||||||
mainplayer sync.Map //玩家数据
|
|
||||||
maincmdcache sync.Map //命令缓存
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if cool.IsRedisMode {
|
if cool.IsRedisMode {
|
||||||
go cool.ListenFunc(gctx.New())
|
go cool.ListenFunc(gctx.New())
|
||||||
}
|
}
|
||||||
|
|
||||||
Start(cool.Config.PortBL) //注入service
|
Start(cool.Config.PortBL) //注入service
|
||||||
}
|
}
|
||||||
func Start(port string) {
|
func Start(port string) {
|
||||||
|
|
||||||
head := handler.NewTomeeHandler()
|
head := handler.NewTomeeHandler()
|
||||||
head.Callback = recv
|
head.Callback = controller.Recv
|
||||||
socket.NewServer(socket.WithPort(port), socket.WithSocketHandler(head)).Start()
|
socket.NewServer(socket.WithPort(port), socket.WithSocketHandler(head)).Start()
|
||||||
}
|
}
|
||||||
func recv(c gnet.Conn, data handler.TomeeHeader) {
|
|
||||||
// 处理接收到的TomeeHeader数据
|
|
||||||
// fmt.Println("收到数据:", data)
|
|
||||||
processWithReflection(c, data)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func getplayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优化,可能存在内存泄漏问题
|
|
||||||
|
|
||||||
clientdata := c.Context().(*entity.ClientData)
|
|
||||||
if clientdata != nil && clientdata.Player != nil {
|
|
||||||
return clientdata.Player
|
|
||||||
}
|
|
||||||
var player *entity.Player
|
|
||||||
if player1, ok := mainplayer.Load((userid)); !ok {
|
|
||||||
player = entity.NewPlayer(
|
|
||||||
entity.WithUserID(userid), //注入ID
|
|
||||||
entity.WithConn(c), //注入conn
|
|
||||||
)
|
|
||||||
mainplayer.Store(userid, player)
|
|
||||||
} else {
|
|
||||||
player = player1.(*entity.Player) //取成功,否则创建
|
|
||||||
}
|
|
||||||
clientdata.Player = player
|
|
||||||
return player
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历结构体方法并执行RECV_cmd
|
|
||||||
func processWithReflection(c gnet.Conn, pp handler.TomeeHeader) {
|
|
||||||
data := pp.Data
|
|
||||||
player := getplayer(c, pp.UserID) //获取player实例
|
|
||||||
cmdlister, ok := maincmdcache.Load(pp.CMDID) //TODO 待实现对不同用户初始化方法以取消全局cmdcache
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
|
|
||||||
callhandler(cmdlister.(reflect.Value), data, player, cmd.EnumCommandID(pp.CMDID))
|
|
||||||
|
|
||||||
// return
|
|
||||||
} else {
|
|
||||||
// 获取对象的反射值和类型
|
|
||||||
value := reflect.ValueOf(maincontroller)
|
|
||||||
|
|
||||||
// 如果传入的是指针,获取其指向的值
|
|
||||||
if value.Kind() == reflect.Ptr {
|
|
||||||
if value.IsNil() {
|
|
||||||
fmt.Println("错误: 传入的是nil指针")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = value.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取类型
|
|
||||||
typ := value.Type()
|
|
||||||
|
|
||||||
// 遍历所有方法
|
|
||||||
fmt.Printf("检查结构体 %s 的方法...\n", typ.Name(), typ.NumMethod())
|
|
||||||
for i := 0; i < typ.NumMethod(); i++ {
|
|
||||||
method := typ.Method(i)
|
|
||||||
|
|
||||||
if method.Type.NumIn() == 4 { //&& // TODO 接收者 + 2个参数 一个是类型,一个是player
|
|
||||||
//method.Type.In(1) == reflect.TypeOf([]byte{}
|
|
||||||
|
|
||||||
// 获取方法值
|
|
||||||
methodValue := value.MethodByName(method.Name)
|
|
||||||
|
|
||||||
// 准备参数
|
|
||||||
cmd1 := method.Name[len("Recv_"):len(method.Name)]
|
|
||||||
cmdint, _ := strconv.Atoi(cmd1)
|
|
||||||
if cmdint == int(pp.CMDID) {
|
|
||||||
if !cmd.Isexist(cmd.CommandID, cmd.EnumCommandID(pp.CMDID)) {
|
|
||||||
fmt.Println("ID方法存在cmd未注册", pp.CMDID, cmd.CommandID)
|
|
||||||
}
|
|
||||||
maincmdcache.Store(pp.CMDID, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache
|
|
||||||
callhandler(methodValue, data, player, cmd.EnumCommandID(pp.CMDID))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//return
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func callhandler(cmdlister reflect.Value, data []byte, player *entity.Player, cmd cmd.EnumCommandID) {
|
|
||||||
//TODO 待实现返回参数返回客户端???实现直接返回对象进行序列化 传递chan待返回
|
|
||||||
//TODO 已实现,待测试结构体序列化
|
|
||||||
recvchan := make(chan any, 1) //传递自定义chan
|
|
||||||
|
|
||||||
go func() { //TODO 待实现ants线程池,以及确认是否存在顺序混乱问题https://github.com/lxzan/gws/issues/3
|
|
||||||
retv := <-recvchan
|
|
||||||
|
|
||||||
switch ttt := retv.(type) {
|
|
||||||
case []byte:
|
|
||||||
player.SendPackBytes(cmd, ttt)
|
|
||||||
|
|
||||||
default:
|
|
||||||
var data1 bytes.Buffer
|
|
||||||
struc.Unpack(&data1, &ttt)
|
|
||||||
player.SendPackBytes(cmd, data1.Bytes())
|
|
||||||
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
cmdlister.Call([]reflect.Value{
|
|
||||||
reflect.ValueOf(data),
|
|
||||||
reflect.ValueOf(player),
|
|
||||||
reflect.ValueOf(recvchan),
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func getincodec(cmdid cmd.EnumCommandID, data []byte) reflect.Value {
|
|
||||||
// 获取对象的反射值和类型
|
|
||||||
value := reflect.ValueOf(maininfocodec)
|
|
||||||
|
|
||||||
// 如果传入的是指针,获取其指向的值
|
|
||||||
if value.Kind() == reflect.Ptr {
|
|
||||||
if value.IsNil() {
|
|
||||||
fmt.Println("错误: 传入的是nil指针")
|
|
||||||
return reflect.ValueOf(nil)
|
|
||||||
}
|
|
||||||
value = value.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取类型
|
|
||||||
typ := value.Type()
|
|
||||||
|
|
||||||
// 遍历所有方法
|
|
||||||
fmt.Printf("检查结构体 %s 的方法...\n", typ.Name(), typ.NumMethod())
|
|
||||||
for i := 0; i < typ.NumMethod(); i++ {
|
|
||||||
method := typ.Method(i)
|
|
||||||
|
|
||||||
if method.Type.NumIn() == 2 && // 接收者 + 2个参数
|
|
||||||
method.Type.In(1) == reflect.TypeOf([]byte{}) {
|
|
||||||
|
|
||||||
// 获取方法值
|
|
||||||
methodValue := value.MethodByName(method.Name)
|
|
||||||
|
|
||||||
// 准备参数
|
|
||||||
cmd1 := method.Name[len("In_"):len(method.Name)]
|
|
||||||
cmdint, _ := strconv.Atoi(cmd1)
|
|
||||||
if cmdint == int(cmdid) {
|
|
||||||
if !cmd.Isexist(cmd.CommandID, cmd.EnumCommandID(cmdid)) {
|
|
||||||
fmt.Println("ID方法存在cmd未注册", cmdid, cmd.CommandID)
|
|
||||||
}
|
|
||||||
|
|
||||||
//data := pp.Data
|
|
||||||
|
|
||||||
// 调用方法
|
|
||||||
tt := methodValue.Call([]reflect.Value{
|
|
||||||
// reflect.ValueOf(cmdint),
|
|
||||||
reflect.ValueOf(data),
|
|
||||||
})
|
|
||||||
|
|
||||||
return tt[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
//return
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(nil)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
package login
|
|
||||||
|
|
||||||
import (
|
|
||||||
"blazing/common/data/entity"
|
|
||||||
"blazing/cool"
|
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommendSvrInfo 初始连接请求信息结构体
|
|
||||||
type CommendSvrInfo struct {
|
|
||||||
MaxOnlineID uint32 // 最大连接数
|
|
||||||
IsVip uint32 // 建议为0
|
|
||||||
ServerInfoLen uint32 `struc:"sizeof=ServerList"` // 服务器信息长度 ServerInfo
|
|
||||||
ServerList []ServerInfo // 服务器具体信息
|
|
||||||
Reversed uint32 // 保留字段
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCommendSvrInfo() *CommendSvrInfo {
|
|
||||||
return &CommendSvrInfo{
|
|
||||||
MaxOnlineID: 100,
|
|
||||||
IsVip: 0,
|
|
||||||
ServerInfoLen: 0,
|
|
||||||
ServerList: make([]ServerInfo, 0),
|
|
||||||
Reversed: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerInfo 服务器信息结构体
|
|
||||||
type ServerInfo struct {
|
|
||||||
// 连接ID, 即服务器序号
|
|
||||||
OnlineID uint32
|
|
||||||
// 当前服务器玩家在线数量, 供SWF显示
|
|
||||||
UserCnt uint32
|
|
||||||
// 服务器IP, 16字节UTF-8, 不足16补齐到16
|
|
||||||
IP string `struc:"[16]byte"` // 定长模式:16字节
|
|
||||||
// 端口
|
|
||||||
Port uint16
|
|
||||||
// 好友在线的个数
|
|
||||||
Friends uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServerInfo 创建新的服务器信息实例
|
|
||||||
func NewServerInfo() *ServerInfo {
|
|
||||||
return &ServerInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoginSidInfo 登录携带的凭证结构体
|
|
||||||
type LoginSidInfo struct {
|
|
||||||
Sid []byte `struc:"[16]byte"` // 登录会话ID,固定长度16字节
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheakSession(c LoginSidInfo, p *entity.Player) bool {
|
|
||||||
// tt, _ := cool.CacheManager.Keys(context.Background())
|
|
||||||
//g.Dump(tt)
|
|
||||||
t1 := hex.EncodeToString(c.Sid)
|
|
||||||
|
|
||||||
t2 := strings.Trim(t1, " ")
|
|
||||||
t, err := cool.CacheManager.Get(context.Background(), t2)
|
|
||||||
fmt.Println("后端获取", string(c.Sid), t, err)
|
|
||||||
if t.Uint32() == p.UserID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
34
logic/service/login/in.go
Normal file
34
logic/service/login/in.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package login
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/common/socket/handler"
|
||||||
|
"blazing/cool"
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoginSidInfo 登录携带的凭证结构体
|
||||||
|
type LoginSidInfo struct { //这里直接使用组合来实现将传入的原始头部数据和结构体参数序列化
|
||||||
|
handler.TomeeHeader `cmd:"1001" struc:"[0]pad"`
|
||||||
|
|
||||||
|
Sid []byte `struc:"[16]byte"` // 登录会话ID,固定长度16字节
|
||||||
|
// NotLogin uint32 `error="10001"|struc:"[0]pad"` //返回错误码 ,不序列化,仅作为错误码
|
||||||
|
// ErrorPassWord uint32 `struc:"[0]pad"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheakSession(c LoginSidInfo) bool {
|
||||||
|
// tt, _ := cool.CacheManager.Keys(context.Background())
|
||||||
|
//g.Dump(tt)
|
||||||
|
t1 := hex.EncodeToString(c.Sid)
|
||||||
|
|
||||||
|
t2 := strings.Trim(t1, " ")
|
||||||
|
t, err := cool.CacheManager.Get(context.Background(), t2)
|
||||||
|
fmt.Println("后端获取", string(c.Sid), t, err)
|
||||||
|
if t.Uint32() == c.UserID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
42
logic/service/login/out.go
Normal file
42
logic/service/login/out.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package login
|
||||||
|
|
||||||
|
import "blazing/common/socket/handler"
|
||||||
|
|
||||||
|
// CommendSvrInfo 初始连接请求信息结构体
|
||||||
|
type CommendSvrInfo struct {
|
||||||
|
Handler handler.TomeeHeader ` struc:"[0]pad"` //消息头 ,这里为传入的头部数据,遍历此头部实现解析CommendSvrInfo
|
||||||
|
MaxOnlineID uint32 // 最大连接数
|
||||||
|
IsVip uint32 // 建议为0
|
||||||
|
ServerInfoLen uint32 `struc:"sizeof=ServerList"` // 服务器信息长度 ServerInfo
|
||||||
|
ServerList []ServerInfo // 服务器具体信息
|
||||||
|
Reversed uint32 // 保留字段
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCommendSvrInfo() *CommendSvrInfo {
|
||||||
|
return &CommendSvrInfo{
|
||||||
|
MaxOnlineID: 100,
|
||||||
|
IsVip: 0,
|
||||||
|
ServerInfoLen: 0,
|
||||||
|
ServerList: make([]ServerInfo, 0),
|
||||||
|
Reversed: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerInfo 服务器信息结构体
|
||||||
|
type ServerInfo struct {
|
||||||
|
// 连接ID, 即服务器序号
|
||||||
|
OnlineID uint32
|
||||||
|
// 当前服务器玩家在线数量, 供SWF显示
|
||||||
|
UserCnt uint32
|
||||||
|
// 服务器IP, 16字节UTF-8, 不足16补齐到16
|
||||||
|
IP string `struc:"[16]byte"` // 定长模式:16字节
|
||||||
|
// 端口
|
||||||
|
Port uint16
|
||||||
|
// 好友在线的个数
|
||||||
|
Friends uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServerInfo 创建新的服务器信息实例
|
||||||
|
func NewServerInfo() *ServerInfo {
|
||||||
|
return &ServerInfo{}
|
||||||
|
}
|
||||||
31
logic/service/service.go
Normal file
31
logic/service/service.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/common/core"
|
||||||
|
"blazing/common/data/entity"
|
||||||
|
|
||||||
|
"github.com/panjf2000/gnet/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优化,可能存在内存泄漏问题
|
||||||
|
|
||||||
|
//检查player初始化,是否为conn初始后取map,防止二次连接后存在两个player
|
||||||
|
|
||||||
|
clientdata := c.Context().(*entity.ClientData)
|
||||||
|
if clientdata != nil && clientdata.Player != nil {
|
||||||
|
return clientdata.Player
|
||||||
|
}
|
||||||
|
var player *entity.Player
|
||||||
|
if player1, ok := core.Mainplayer.Load((userid)); !ok {
|
||||||
|
player = entity.NewPlayer(
|
||||||
|
entity.WithUserID(userid), //注入ID
|
||||||
|
entity.WithConn(c), //注入conn
|
||||||
|
)
|
||||||
|
core.Mainplayer.Store(userid, player)
|
||||||
|
} else {
|
||||||
|
player = player1.(*entity.Player) //取成功,否则创建
|
||||||
|
}
|
||||||
|
clientdata.Player = player
|
||||||
|
return player
|
||||||
|
// return nil
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
@@ -10,11 +9,11 @@ import (
|
|||||||
"github.com/lunixbochs/struc"
|
"github.com/lunixbochs/struc"
|
||||||
"github.com/panjf2000/gnet/v2"
|
"github.com/panjf2000/gnet/v2"
|
||||||
|
|
||||||
"blazing/common/core/info/login"
|
|
||||||
"blazing/common/socket"
|
"blazing/common/socket"
|
||||||
"blazing/common/socket/handler"
|
"blazing/common/socket/handler"
|
||||||
_ "blazing/contrib/files/local"
|
_ "blazing/contrib/files/local"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
|
"blazing/logic/service/login"
|
||||||
|
|
||||||
// Minio,按需启用
|
// Minio,按需启用
|
||||||
// _ "blazing/contrib/files/minio"
|
// _ "blazing/contrib/files/minio"
|
||||||
@@ -49,9 +48,9 @@ func Start(port string) {
|
|||||||
|
|
||||||
func recv(c gnet.Conn, data handler.TomeeHeader) {
|
func recv(c gnet.Conn, data handler.TomeeHeader) {
|
||||||
|
|
||||||
fmt.Println(data)
|
//fmt.Println(data)
|
||||||
t, _ := cool.CacheManager.Get(context.Background(), data.Data)
|
//t, _ := cool.CacheManager.Get(context.Background(), data.Data)
|
||||||
fmt.Println(t.String())
|
// fmt.Println(t.String())
|
||||||
ret := login.NewCommendSvrInfo()
|
ret := login.NewCommendSvrInfo()
|
||||||
|
|
||||||
lofin := login.NewServerInfo()
|
lofin := login.NewServerInfo()
|
||||||
@@ -64,25 +63,22 @@ func recv(c gnet.Conn, data handler.TomeeHeader) {
|
|||||||
ret.ServerList = append(ret.ServerList, *lofin)
|
ret.ServerList = append(ret.ServerList, *lofin)
|
||||||
|
|
||||||
var trr bytes.Buffer
|
var trr bytes.Buffer
|
||||||
|
|
||||||
err := struc.Pack(&trr, ret)
|
|
||||||
fmt.Println(err)
|
|
||||||
t11, _ := struc.Sizeof(ret)
|
t11, _ := struc.Sizeof(ret)
|
||||||
t1 := handler.TomeeHeader{
|
ret.Handler = handler.TomeeHeader{
|
||||||
Len: uint32(t11 + 17),
|
Len: uint32(t11),
|
||||||
CMDID: 105,
|
CMD: 105,
|
||||||
Version: "7",
|
Version: "7",
|
||||||
UserID: 1,
|
UserID: 1,
|
||||||
// Data: bytt.Bytes(),
|
// Data: bytt.Bytes(),
|
||||||
}
|
}
|
||||||
var trr1 bytes.Buffer
|
err := struc.Pack(&trr, ret)
|
||||||
err = struc.Pack(&trr1, &t1)
|
fmt.Println(err)
|
||||||
fmt.Println(hex.EncodeToString(trr1.Bytes()))
|
|
||||||
//0000003f3700000001000000000000006900000000
|
//0000003f3700000001000000000000006900000000
|
||||||
//0000003f37000000690000000100000000
|
//0000003f37000000690000000100000000
|
||||||
//0000003F3700000069000186A600000000
|
//0000003F3700000069000186A600000000
|
||||||
fmt.Println(hex.EncodeToString(trr.Bytes()))
|
fmt.Println(hex.EncodeToString(trr.Bytes()))
|
||||||
c.Write(trr1.Bytes())
|
// c.Write(trr1.Bytes())
|
||||||
|
|
||||||
c.Write(trr.Bytes())
|
c.Write(trr.Bytes())
|
||||||
|
|
||||||
@@ -91,14 +87,3 @@ func recv(c gnet.Conn, data handler.TomeeHeader) {
|
|||||||
//processWithReflection(data)
|
//processWithReflection(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func packheader(cmd, userid uint32, data []byte) *handler.TomeeHeader {
|
|
||||||
|
|
||||||
return &handler.TomeeHeader{
|
|
||||||
Len: uint32(63),
|
|
||||||
CMDID: 105,
|
|
||||||
Version: "7",
|
|
||||||
UserID: 1,
|
|
||||||
//Data: bytt.Bytes(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user