Files
bl/logic/service/player/SocketHandler_Tomee.go
昔念 cccf26788e fix(socket): 玩家断开连接时增加保存锁,避免重复保存
在玩家断开连接时,使用 sync.Once 确保只保存一次玩家数据,
防止因并发或多次触发导致的数据异常。

feat(fight): 增加战斗资格判断与邀请取消功能

- 新增 Player.CanFight() 方法用于统一判断是否可以参与战斗
- 在多个战斗相关接口中加入 CanFight 检查
- 添加“取消战斗邀请”指令及处理逻辑(cmd: 2402)
- 修复部分错误码不准确的问题,提升提示一致性

refactor(login): 优化登录流程并增强健壮性

- 提前校验 session 合法性
- 增强获取玩家信息后的空指针检查
- 调整挖矿数据重置方式为 defer 执行
- 优化日志输出内容,便于调试追踪

docs(model): 更新部门、菜单等模型字段命名规范

将 orderNum 字段改为 ordernum,保持数据库列名风格一致,
同时更新了 base_sys_role 中 userId 为 userid。

perf(rate-limit): 提高登录接口的限流 Burst 容量

调整限流器配置,将请求 burst 容量从 2 提升至 5,
以应对短时间高频访问场景,改善用户体验。

chore(build): 忽略新增编译产物和临时文件

在 .gitignore 中添加 logic/logic2、login/login 等新生成文件路径,
避免误提交二进制文件到版本控制。
2025-10-31 00:53:22 +08:00

193 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package player
import (
"blazing/common/socket/errorcode"
"blazing/common/utils/bytearray"
"blazing/cool"
"context"
"bytes"
"fmt"
"reflect"
"github.com/gogf/gf/v2/os/glog"
"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"`
UserID uint32 `json:"userId"`
//Error uint32 `json:"error" struc:"[0]pad"`
Result uint32 `json:"result"`
Data []byte `json:"data" struc:"skip"` //组包忽略此字段// struc:"[0]pad"
//Return []byte `struc:"[0]pad"` //返回记录
}
func NewTomeeHeader(cmd uint32, userid uint32) *TomeeHeader {
return &TomeeHeader{
CMD: cmd,
// Len: 0,
Version: 49,
Result: 0,
}
}
// Pack 将给定的数据打包成一个字节切片。
// 该方法处理的数据类型包括指针、切片和结构体。
// 对于指针类型,会解引用以获取实际值。
// 切片类型直接转换为字节切片。
// 结构体类型使用struc库进行序列化。
// 最后将数据长度、版本号、命令码、用户ID和结果代码一并打包进返回的字节切片中。
func (h *TomeeHeader) Pack(data any) []byte { //组包
//h.Result = 0//默认置0
//t := reflect.TypeOf(data)
tv := reflect.ValueOf(data)
var datar []byte
// 处理指针类型
if tv.Kind() == reflect.Ptr {
//tv = t.Elem() // 获取指针指向的类型
tv = tv.Elem() // 获取指针指向的值
}
switch tv.Kind() {
case reflect.String:
datar = []byte(tv.String())
case reflect.Slice:
datar = data.([]byte)
//p.Conn.Write(p.pack(cmd, data.([]byte))) //写入数据
case reflect.Struct:
var data1 bytes.Buffer
err := struc.Pack(&data1, data)
if err != nil {
fmt.Println(err)
}
datar = data1.Bytes()
default:
datar = []byte{}
// fmt.Println(err, datar)
// p.Conn.Write(p.pack(cmd, data))
}
h.Len = uint32(len(datar) + 17)
by := bytearray.CreateByteArray()
by.WriteUInt32(h.Len)
by.WriteByte(h.Version)
by.WriteUInt32(uint32(h.CMD))
by.WriteUInt32(h.UserID)
by.WriteUInt32(h.Result)
by.Write(datar)
return by.Bytes()
}
// var _ Blazingservice = (*TomeeHeader)(nil)
// type Blazingservice interface {
// Ret() []byte
// }
// MergeBytes 将多个字节数组合并为一个
func MergeBytes(arrays ...[]byte) []byte {
// 计算所有数组的总长度
totalLen := 0
for _, arr := range arrays {
totalLen += len(arr)
}
// 创建结果切片
result := make([]byte, totalLen)
// 逐个复制数组内容
currentIndex := 0
for _, arr := range arrays {
copy(result[currentIndex:], arr)
currentIndex += len(arr)
}
return result
}
// 遍历结构体方法并执行RECV_cmd
func (h *ClientData) Recv(data TomeeHeader) {
cmdlister, ok := cool.CmdCache.Load(data.CMD)
if !ok {
glog.Debug(context.Background(), data.CMD, "cmd未注册")
return //TODO 待实现cmd未注册
}
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 data.CMD > 1001 { //if cmdlister.Type().In(1) == reflect.TypeOf(&Player{}) {
//t := GetPlayer(c, data.UserID)
// fmt.Println(data.CMD, "接收 变量的地址 ", &t.Info, t.Info.UserID)
params = append(params, ptrValue1, reflect.ValueOf(h.Conn.Context().(*ClientData).Player))
} else {
params = append(params, ptrValue1, reflect.ValueOf(h.Conn))
}
ret := cmdlister.Call(params)
if len(ret) <= 0 { //如果判断没有参数,那就说明这个包没有返回参数
return
}
aa, ok := ret[1].Interface().(errorcode.ErrorCode) //判断错误
data.Result = uint32(aa)
if aa == -1 {
return
}
t := h.Conn.Context().(*ClientData).Player
if ok && aa != 0 { //这里实现回复错误包
cool.Loger.Error(context.Background(), aa.Code())
t.SendPack(data.Pack(nil))
return
}
//data.Version = 49
t.SendPack(data.Pack(ret[0].Interface()))
}