92 lines
2.6 KiB
Go
92 lines
2.6 KiB
Go
package common
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/binary"
|
||
"fmt"
|
||
|
||
"github.com/lunixbochs/struc"
|
||
)
|
||
|
||
// TomeeHeader 定义协议包头。
|
||
type TomeeHeader struct {
|
||
Len uint32 `json:"len"` // 包总长度(包头 + 数据体)。
|
||
Version byte `json:"version" struc:"[1]byte"` // 协议版本。
|
||
CMD uint32 `json:"cmdId" struc:"uint32"` // 命令 ID。
|
||
UserID uint32 `json:"userId"` // 玩家 ID。
|
||
Result uint32 `json:"result"` // 结果码。
|
||
Data []byte `json:"data" struc:"skip"` // 数据体,序列化时跳过。
|
||
Res []byte `struc:"skip"` // 预留返回数据,序列化时跳过。
|
||
}
|
||
|
||
// NewTomeeHeader 创建用于下行封包的默认 TomeeHeader。
|
||
func NewTomeeHeader(cmd uint32, userid uint32) *TomeeHeader {
|
||
|
||
return &TomeeHeader{
|
||
CMD: cmd,
|
||
// Len: 0,
|
||
Version: 49,
|
||
Result: 0,
|
||
}
|
||
|
||
}
|
||
|
||
// Pack 组包方法:手动编码字节流,兼容interface{}、nil、多层指针/接口
|
||
func (h *TomeeHeader) Pack(data any) []byte {
|
||
if data == nil {
|
||
return h.packHeaderWithData([]byte{})
|
||
}
|
||
var data1 bytes.Buffer
|
||
err := struc.Pack(&data1, data)
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
|
||
if len(data1.Bytes()) == 0 {
|
||
// fmt.Println("数据为空")
|
||
|
||
}
|
||
//datar = data1.Bytes()
|
||
// 4. 手动打包包头+数据体
|
||
return h.packHeaderWithData(data1.Bytes())
|
||
}
|
||
|
||
// packHeaderWithData 手动编码包头和数据体(静态指定偏移量,无自增变量)
|
||
// 包头固定结构(大端序):
|
||
// - 0-3 字节:Len (uint32)
|
||
// - 4 字节:Version (byte)
|
||
// - 5-8 字节:CMD (uint32,从uint64截断)
|
||
// - 9-12 字节:UserID (uint32)
|
||
// - 13-16 字节:Result (uint32)
|
||
// 17字节后:数据体
|
||
func (h *TomeeHeader) packHeaderWithData(data []byte) []byte {
|
||
// 计算总长度:包头17字节 + 数据体长度
|
||
dataLen := len(data)
|
||
h.Len = uint32(17 + dataLen)
|
||
|
||
// 预分配切片(总长度 = 包头 + 数据体),避免多次扩容
|
||
buf := make([]byte, h.Len)
|
||
|
||
// 1. 写入Len(固定偏移:0-3 字节,大端序)
|
||
binary.BigEndian.PutUint32(buf[0:4], h.Len)
|
||
|
||
// 2. 写入Version(固定偏移:4 字节)
|
||
buf[4] = h.Version
|
||
|
||
// 3. 写入CMD(固定偏移:5-8 字节,大端序)
|
||
binary.BigEndian.PutUint32(buf[5:9], uint32(h.CMD))
|
||
|
||
// 4. 写入UserID(固定偏移:9-12 字节,大端序)
|
||
binary.BigEndian.PutUint32(buf[9:13], h.UserID)
|
||
|
||
// 5. 写入Result(固定偏移:13-16 字节,大端序)
|
||
binary.BigEndian.PutUint32(buf[13:17], h.Result)
|
||
|
||
// 6. 写入数据体(固定起始偏移:17 字节,若有数据则拷贝)
|
||
if dataLen > 0 {
|
||
copy(buf[17:], data)
|
||
}
|
||
|
||
return buf
|
||
}
|