From 8983222dcb4ab4f8109aee5a749ff8dad5e14abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Mon, 8 Dec 2025 17:03:43 +0800 Subject: [PATCH] =?UTF-8?q?```=20refactor(logic):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=90=AF=E5=8A=A8=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=B8=8E=E4=BB=BB=E5=8A=A1=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 `gcmd` 包在 controller 中的直接使用,改为通过参数传递端口和服务器类型 - 统一使用 `GetTask` 和 `SetTask` 方法替代直接访问 `TaskList` 数组,提升代码可维护性 - 修改了战斗逻辑中部分调试打印语句,并优化战斗循环结束日志输出 - 调整了新手玩家初始化流程,默认完成新手任务4 - 更新了数据库模型字段及结构定义,如增加 `max_ts` 字段、扩展 `TaskList` 长度等 - 改进了宠物添加逻辑,采用 SQL 方式确保捕捉时间唯一递增 - 清理了无用或注释掉的旧代码块 --- .vscode/launch.json | 90 +++++++++---------- logic/controller/controller.go | 10 +-- logic/controller/fight_boss.go | 3 +- logic/controller/task.go | 18 ++-- logic/main.go | 12 +-- logic/server.go | 52 ++++------- logic/service/fight/input/effect.go | 2 +- logic/service/fight/loop.go | 3 +- logic/service/player/save.go | 3 +- logic/service/player/task.go | 45 ++++++++++ login/internal/cmd/cmd.go | 8 +- login/internal/cmd/reg.go | 23 +++++ login/main.go | 5 +- modules/base/model/base_sys_user.go | 6 +- modules/base/service/base_sys_perms.go | 2 +- .../blazing/controller/admin/talkconfig.go | 22 +++++ modules/blazing/model/player.go | 84 ++++++++--------- modules/blazing/model/talkconfig.go | 55 ++++++++++++ modules/blazing/service/info.go | 8 +- modules/blazing/service/pet.go | 55 +++++++++--- modules/blazing/service/talk.go | 12 +++ 21 files changed, 341 insertions(+), 177 deletions(-) create mode 100644 logic/service/player/task.go create mode 100644 login/internal/cmd/reg.go create mode 100644 modules/blazing/controller/admin/talkconfig.go create mode 100644 modules/blazing/model/talkconfig.go diff --git a/.vscode/launch.json b/.vscode/launch.json index 93cfd01d3..1342cdc80 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,49 +1,45 @@ { - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch login-http", + "type": "go", + "request": "launch", + "mode": "auto", + "cwd": "${workspaceFolder}", + "program": "${workspaceFolder}/login" + }, + // { + // "name": "Launch logic1", + // "type": "go", + // "request": "launch", + // "mode": "auto", + // "cwd": "${workspaceFolder}", + // "args": ["-port=1", " -race"], + // "program": "${workspaceFolder}/logic", + // "console": "integratedTerminal" + // }, + { + "name": "Launch test server", + "type": "go", + "request": "launch", + "mode": "auto", + "cwd": "${workspaceFolder}", + "args": ["-port=2"], - { - "name": "Launch login-http", - "type": "go", - "request": "launch", - "mode": "auto", - "cwd": "${workspaceFolder}", - "program": "${workspaceFolder}/login", - - - }, - { - "name": "Launch logic1", - "type": "go", - "request": "launch", - "mode": "auto", - "cwd": "${workspaceFolder}", - "args": ["-port=1"," -race"], - "program": "${workspaceFolder}/logic", "console": "integratedTerminal" - - }, { - "name": "Launch logic2", - "type": "go", - "request": "launch", - "mode": "auto", - "cwd": "${workspaceFolder}", - "args": ["-port=2"], - - "program": "${workspaceFolder}/logic", - }, - { - "name": "Launch login-tcp", - "type": "go", - "request": "launch", - "mode": "auto", - "cwd": "${workspaceFolder}", - "args": ["-port=0"], - "program": "${workspaceFolder}/logic", - } - - ] -} \ No newline at end of file + "program": "${workspaceFolder}/logic" + } + // { + // "name": "Launch login-tcp", + // "type": "go", + // "request": "launch", + // "mode": "auto", + // "cwd": "${workspaceFolder}", + // "args": ["-port=0"], + // "program": "${workspaceFolder}/logic", + // } + ] +} diff --git a/logic/controller/controller.go b/logic/controller/controller.go index 11e68c0d5..01276ed01 100644 --- a/logic/controller/controller.go +++ b/logic/controller/controller.go @@ -12,7 +12,6 @@ import ( "context" "reflect" - "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/glog" "github.com/lunixbochs/struc" ) @@ -38,9 +37,8 @@ func ParseCmd[T any](a T, data []byte) T { //fmt.Println(data) } -func init() { //默认初始化扫描 - // 解析命令行参数 - cool.Config.PortBL = gcmd.GetOpt("port", "1").Uint16() +func Init(isgame bool) { //默认初始化扫描 + // 获取对象的反射值和类型 value := reflect.ValueOf(Maincontroller) @@ -60,12 +58,12 @@ func init() { //默认初始化扫描 continue } - if cool.Config.PortBL == 0 && func_cmd > 1000 { //判断login服务器 + if !isgame && func_cmd > 1000 { //判断login服务器 continue } - if cool.Config.PortBL != 0 && func_cmd < 1000 { //判断login服务器 + if isgame && func_cmd < 1000 { //判断login服务器 continue } diff --git a/logic/controller/fight_boss.go b/logic/controller/fight_boss.go index e11632491..d74089e78 100644 --- a/logic/controller/fight_boss.go +++ b/logic/controller/fight_boss.go @@ -121,7 +121,8 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla fight.NewFight(c, ai, func(foi *info.FightOverInfo) { if taskid != 0 { if foi.Reason == 0 && foi.WinnerId == c.Info.UserID { - if c.Info.TaskList[taskid-1] != 3 { + if c.GetTask(taskid) == player.Unaccepted { + c.SetTask(taskid, player.Completed) //设置完成任务 c.Info.TaskList[taskid-1] = 3 moinfo.PetList[0].Downgrade(1) diff --git a/logic/controller/task.go b/logic/controller/task.go index 3beb55766..a7d25baf3 100644 --- a/logic/controller/task.go +++ b/logic/controller/task.go @@ -19,8 +19,9 @@ func (h Controller) AcceptTask(data *task.AcceptTaskInboundInfo, c *player.Playe // //isdaliy = true // } - if c.Info.TaskList[data.TaskId-1] == 0 { - c.Info.TaskList[data.TaskId-1] = 1 + if c.GetTask(int(data.TaskId)) == player.Unaccepted { + c.SetTask(int(data.TaskId), player.Accepted) + } c.Service.Task.Exec(uint32(data.TaskId), func(t *model.TaskEX) bool { t.Data = []uint32{} @@ -54,13 +55,13 @@ func (h Controller) AddTaskBuf(data *task.AddTaskBufInboundInfo, c *player.Playe * 完成任务 */ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.Player) (result *task.CompleteTaskOutboundInfo, err errorcode.ErrorCode) { - - if c.Info.TaskList[data.TaskId-1] != 1 { //如果任务没有接受或者已经完成Complete_Task - + if c.GetTask(int(data.TaskId)) != player.Accepted { //如果任务没有接受或者已经完成Complete_Task return result, 0 } - c.Info.TaskList[data.TaskId-1] = 3 + + c.SetTask(int(data.TaskId), player.Completed) + result = &task.CompleteTaskOutboundInfo{ TaskId: data.TaskId, ItemList: make([]model.ItemInfo, 0), @@ -111,10 +112,9 @@ func (h Controller) Get_Task_Buf(data *task.GetTaskBufInboundInfo, c *player.Pla */ func (h Controller) Delete_Task(data *task.DeleteTaskInboundInfo, c *player.Player) (result *task.DeleteTaskOutboundInfo, err errorcode.ErrorCode) { - if c.Info.TaskList[data.TaskId-1] == 1 { - c.Info.TaskList[data.TaskId-1] = 0 + if c.GetTask(int(data.TaskId)) == player.Accepted { + c.SetTask(int(data.TaskId), player.Unaccepted) return &task.DeleteTaskOutboundInfo{TaskId: data.TaskId}, 0 - } return &task.DeleteTaskOutboundInfo{}, 0 diff --git a/logic/main.go b/logic/main.go index 3608679a9..59e4e404d 100644 --- a/logic/main.go +++ b/logic/main.go @@ -7,6 +7,7 @@ import ( "strings" _ "github.com/gogf/gf/contrib/nosql/redis/v2" + "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gproc" "blazing/logic/service/fight" @@ -19,8 +20,6 @@ import ( blservice "blazing/modules/blazing/service" "net/http" _ "net/http/pprof" - - "github.com/gogf/gf/v2/os/gctx" ) func PprofWeb() { @@ -44,10 +43,11 @@ func signalHandlerForMain(sig os.Signal) { func main() { //loadAccounts() - if cool.IsRedisMode { - go cool.ListenFunc(gctx.New()) - } - + // if cool.IsRedisMode { + // go cool.ListenFunc(gctx.New()) + // } + // 解析命令行参数 + cool.Config.PortBL = gcmd.GetOpt("port", "1").Uint16() go Start(cool.Config.PortBL) //注入service if cool.Config.PortBL == 1 || cool.Config.PortBL == 2 { //只分析1服务器的 go PprofWeb() diff --git a/logic/server.go b/logic/server.go index 125d71be1..11ee32128 100644 --- a/logic/server.go +++ b/logic/server.go @@ -23,15 +23,10 @@ const ( maxPortRetryCount = 5 ) -var defaultPort = gconv.Int(cool.Config.Port) //读入默认的端口 var candidatePorts = cool.Config.GamePort // determinePort 确定服务器使用的端口 -func determinePort(serverid uint16) (int, error) { - // 服务器ID为0时使用默认端口 - if serverid == 0 { - return defaultPort, nil - } +func determinePort() (int, error) { // 尝试从指定端口列表中找可用端口,最多尝试maxPortRetryCount轮 for i := 0; i < maxPortRetryCount; i++ { @@ -61,35 +56,22 @@ func isPortAvailable(port uint64) bool { // 如果id是0,那就是login server func Start(serverid uint16) { - - if serverid != 0 { //logic服务器 - // 确定端口 - port, err := determinePort(serverid) - if err != nil { - log.Fatalf("Failed to determine port: %v", err) - } - ser := socket.NewServer( - socket.WithCORS(), - socket.WithPort(port), - ) - // go func() { - t := rpc.StartClient(serverid, uint16(port), ser) - - controller.Maincontroller.RPCClient = *t //将RPC赋值Start - controller.Maincontroller.Port = uint16(port) //赋值服务器ID - xmlres.Initfile() - blservice.NewLoginServiceService().SetServerID(serverid, gconv.Uint16(port)) - ser.Boot() - - } else { - go rpc.StartServer() - - //go rpcserver() //对login tcp启动 - //ants.Submit(rpcserver) - socket.NewServer( - socket.WithCORS(), - socket.WithPort(defaultPort), - ).Boot() + // 确定端口 + port, err := determinePort() + if err != nil { + log.Fatalf("Failed to determine port: %v", err) } + ser := socket.NewServer( + socket.WithCORS(), + socket.WithPort(port), + ) + // go func() { + t := rpc.StartClient(serverid, uint16(port), ser) + controller.Maincontroller.RPCClient = *t //将RPC赋值Start + controller.Maincontroller.Port = uint16(port) //赋值服务器ID + controller.Init(true) + xmlres.Initfile() + blservice.NewLoginServiceService().SetServerID(serverid, gconv.Uint16(port)) + ser.Boot() } diff --git a/logic/service/fight/input/effect.go b/logic/service/fight/input/effect.go index 5fcb769b7..5559cdfa7 100644 --- a/logic/service/fight/input/effect.go +++ b/logic/service/fight/input/effect.go @@ -189,7 +189,7 @@ func (our *Input) AddEffect(in *Input, e Effect) Effect { e.Alive(true) //添加后默认激活 //todo 免疫 //TODO 先激活 - fmt.Println("产生回合数", e.ID(), e.Duration()) + //fmt.Println("产生回合数", e.ID(), e.Duration()) // 如果已有同 ID 的效果,尝试叠加 for _, v := range our.Effects { if v == e { diff --git a/logic/service/fight/loop.go b/logic/service/fight/loop.go index e6fc21180..06bb0b635 100644 --- a/logic/service/fight/loop.go +++ b/logic/service/fight/loop.go @@ -93,7 +93,6 @@ func (f *FightC) battleLoop() { //<-time.After(1000) f.Broadcast(func(ff *input.Input) { - fmt.Println("战斗结束信息", ff.UserID) ff.Player.SendPackCmd(2506, &f.FightOverInfo) ff.Player.QuitFight() @@ -102,7 +101,7 @@ func (f *FightC) battleLoop() { }) // close(f.actionChan) - fmt.Println("战斗循环结束") + fmt.Println(f.ownerID, "战斗循环结束") close(f.over) } diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 33259f9c8..2118249a6 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -71,6 +71,7 @@ func (lw *Player) CompleteLogin() { } if lw.IsNewPlayer() { //重置新手地图,放到机械仓 + lw.SetTask(4, Completed) //设置新手任务默认完成 lw.Info.MapID = 8 if len(lw.Info.PetList) == 0 { rr := lw.Service.Pet.PetInfo(0) @@ -87,7 +88,7 @@ func (lw *Player) CompleteLogin() { func (lw *Player) IsNewPlayer() bool { // 遍历84到87的索引 for i := 84; i <= 87; i++ { - if lw.Info.TaskList[i] != 3 { + if lw.GetTask(i) != Completed { return true // 只要有一个不等于3,就返回true } } diff --git a/logic/service/player/task.go b/logic/service/player/task.go new file mode 100644 index 000000000..f26e68d98 --- /dev/null +++ b/logic/service/player/task.go @@ -0,0 +1,45 @@ +package player + +import "fmt" + +// TaskStatus 任务状态(与 AS3 对应) +type TaskStatus uint8 + +const ( + Unaccepted TaskStatus = 0 // 未接受(AS3 中 0 或 2 映射至此) + Accepted TaskStatus = 1 // 已接受 + Completed TaskStatus = 3 // 已完成 + Reserved TaskStatus = 2 // 预留(AS3 中映射为未接受) +) + +// SetTask 设置第 i 个任务的状态(0 ≤ i < 2000) +func (m *Player) SetTask(i int, status TaskStatus) error { + i-- //下标减1 + if i < 0 || i >= 4000 { + return fmt.Errorf("index out of range: %d (must be 0-1999)", i) + } + + byteIdx := i / 4 + bitOffset := (i % 4) * 2 + + // 清除原有 2 位 + m.Info.TaskList[byteIdx] &^= 0x3 << bitOffset + + // 设置新状态(确保只取低 2 位) + m.Info.TaskList[byteIdx] |= byte(status&0x3) << bitOffset + + return nil +} + +// GetTask 获取第 i 个任务的状态 +func (m *Player) GetTask(i int) TaskStatus { + i-- //下标减1 + // if i < 0 || i >= 2000 { + // return 0, fmt.Errorf("index out of range: %d", i) + // } + + byteIdx := i / 4 + bitOffset := (i % 4) * 2 + + return TaskStatus((m.Info.TaskList[byteIdx] >> bitOffset) & 0x3) +} diff --git a/login/internal/cmd/cmd.go b/login/internal/cmd/cmd.go index 0cd46cf4a..2e13e4025 100644 --- a/login/internal/cmd/cmd.go +++ b/login/internal/cmd/cmd.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "runtime" "blazing/cool" @@ -26,14 +25,15 @@ var ( go cool.ListenFunc(ctx) } //go robot() + go reg() s := g.Server() s.Use(Limiter, ghttp.MiddlewareHandlerResponse) s.EnableAdmin() s.SetServerAgent(cool.Config.Name) s.BindHookHandler("/*", ghttp.HookBeforeServe, beforeServeHook) - runtime.SetMutexProfileFraction(1) // (非必需)开启对锁调用的跟踪 - runtime.SetBlockProfileRate(1) // (非必需)开启对阻塞操作的跟踪 - s.EnablePProf() + // runtime.SetMutexProfileFraction(1) // (非必需)开启对锁调用的跟踪 + // runtime.SetBlockProfileRate(1) // (非必需)开启对阻塞操作的跟踪 + // s.EnablePProf() // 如果存在 data/cool-admin-vue/dist 目录,则设置为主目录 if gfile.IsDir("public") { s.SetServerRoot("public") diff --git a/login/internal/cmd/reg.go b/login/internal/cmd/reg.go new file mode 100644 index 000000000..53d321b28 --- /dev/null +++ b/login/internal/cmd/reg.go @@ -0,0 +1,23 @@ +package cmd + +import ( + "blazing/common/rpc" + "blazing/common/socket" + "blazing/cool" + "blazing/logic/controller" + + "github.com/gogf/gf/v2/util/gconv" +) + +var defaultPort = gconv.Int(cool.Config.Port) //读入默认的端口 +func reg() { + go rpc.StartServer() + controller.Init(false) + //go rpcserver() //对login tcp启动 + //ants.Submit(rpcserver) + socket.NewServer( + socket.WithCORS(), + socket.WithPort(defaultPort), + ).Boot() + +} diff --git a/login/main.go b/login/main.go index 3fccb7fe3..499046021 100644 --- a/login/main.go +++ b/login/main.go @@ -58,7 +58,10 @@ func main() { //service.TestSendVerificationCode() // t := model.GenPetInfo(1, 31, 1, 1, 1, 1) - // service.NewUserService(10001).Pet.PetAdd(*t) + + // for i := 0; i < 1000; i++ { + // service.NewUserService(10001).Pet.PetAdd(t) + // } // service.NewUserService(10001).Pet.PetInfo_One_exec(t.CatchTime, func(pe *model.PetEX) { // fmt.Println(pe.CreateTime) diff --git a/modules/base/model/base_sys_user.go b/modules/base/model/base_sys_user.go index baab8be13..44940607c 100644 --- a/modules/base/model/base_sys_user.go +++ b/modules/base/model/base_sys_user.go @@ -18,9 +18,9 @@ type BaseSysUser struct { Email *string `gorm:"column:email;type:varchar(255)" json:"email"` // 邮箱 Status *int32 `gorm:"column:status;not null;default:1" json:"status"` // 状态 0:禁用 1:启用 GoldBean float64 `gorm:"column:goldBean;type:decimal;not null;default:0" json:"goldBean"` - Remark *string `gorm:"column:remark;type:varchar(255)" json:"remark"` // 备注 - Debug int32 `gorm:"column:debug;type:int;not null;default:0" json:"debug"` // 是否可以进入2服 - + Remark *string `gorm:"column:remark;type:varchar(255)" json:"remark"` // 备注 + Debug int32 `gorm:"column:debug;type:int;not null;default:0" json:"debug"` // 是否可以进入2服 测试服 + Maxts uint32 `gorm:"column:max_ts;type:int;not null;default:0" json:"max_ts"` //最后生成的时间记录表 } // TableName BaseSysUser's table name diff --git a/modules/base/service/base_sys_perms.go b/modules/base/service/base_sys_perms.go index edd08960d..06caa90a3 100644 --- a/modules/base/service/base_sys_perms.go +++ b/modules/base/service/base_sys_perms.go @@ -47,7 +47,7 @@ func (c *BaseSysPermsService) RefreshPerms(ctx context.Context, userId uint) (er ) cool.CacheManager.Set(ctx, "admin:perms:"+gconv.String(userId), perms, 0) // 更新部门权限 - departments := baseSysDepartmentService.GetByRoleIds(roleIds, userId == 1) + departments := baseSysDepartmentService.GetByRoleIds(roleIds, userId == 10001) cool.CacheManager.Set(ctx, "admin:department:"+gconv.String(userId), departments, 0) return diff --git a/modules/blazing/controller/admin/talkconfig.go b/modules/blazing/controller/admin/talkconfig.go new file mode 100644 index 000000000..f911cb8d9 --- /dev/null +++ b/modules/blazing/controller/admin/talkconfig.go @@ -0,0 +1,22 @@ +package admin + +import ( + "blazing/cool" + "blazing/modules/blazing/service" +) + +type TalkConfigController struct { + *cool.Controller +} + +func init() { + var task_info_controller = &TalkConfigController{ + &cool.Controller{ + Prefix: "/admin/sun/talkconfig", + Api: []string{"Add", "Delete", "Update", "Info", "List", "Page"}, + Service: service.NewTalkConfigService(), + }, + } + // 注册路由 + cool.RegisterController(task_info_controller) +} diff --git a/modules/blazing/model/player.go b/modules/blazing/model/player.go index 23f29ee95..6aadc19bd 100644 --- a/modules/blazing/model/player.go +++ b/modules/blazing/model/player.go @@ -72,38 +72,38 @@ type PlayerInfo struct { //LastResetTime time.Time `struc:"skip" json:"last_reset_time"` // 重置时间,比如电池和每日任务 OnlineTime uint32 `struc:"skip" json:"online_time"` //在线分钟数 // OutInfo 字段 - UserID uint32 `struc:"uint32" json:"user_id"` // 米米号 通过sid拿到 - RegisterTime uint32 `struc:"uint32" json:"register_time"` // 注册时间(秒时间戳) - Nick string `struc:"[16]byte" default:"seer" json:"nick"` // 16字节昵称 - Vip uint16 `struc:"uint16" json:"vip"` // 固定0 - Viped uint16 `struc:"uint16" default:"15" json:"viped"` // 固定15 - DSFlag uint32 `struc:"uint32" json:"ds_flag"` // 固定0 - Color uint32 `struc:"uint32" json:"color"` // 机器人颜色RGB颜色值(uint32,实际为3个uint8) - Texture uint32 `struc:"uint32" json:"texture"` // 固定0 - Energy uint32 `struc:"uint32" default:"3000" json:"energy"` // 固定3000 - Coins uint32 `struc:"uint32" json:"coins"` // 赛尔豆 - EVPool uint32 `struc:"uint32" json:"ev_pool"` //累计学习力 - FightBadge uint32 `struc:"uint32" json:"fight_badge"` // 固定0 - MapID uint32 `struc:"uint32" default:"1" json:"map_id"` // 上线地图ID - Pos Pos `json:"pos"` // 坐标 - TimeToday uint32 `struc:"uint32" default:"0" json:"time_today"` // 已消耗时间(秒) - TimeLimit uint32 `struc:"uint32" default:"43200" json:"time_limit"` // 总电池限制(秒) - IsClothHalfDay byte `struc:"byte" json:"is_cloth_half_day"` // 活动标志0/1 - IsRoomHalfDay byte `struc:"byte" json:"is_room_half_day"` // 活动标志0/1 - IFortressHalfDay byte `struc:"byte" json:"i_fortress_half_day"` // 活动标志0/1 - IsHQHalfDay byte `struc:"byte" json:"is_hq_half_day"` // 活动标志0/1 - LoginCount uint32 `struc:"uint32" json:"login_count"` // 固定0 - Inviter uint32 `struc:"uint32" json:"inviter"` // 固定0 - NewInviteeCount uint32 `struc:"uint32" json:"new_invitee_count"` // 固定0 - VipLevel uint32 `struc:"uint32" default:"8" json:"vip_level"` // 固定8 - VipValue uint32 `struc:"uint32" default:"80000" json:"vip_value"` // 固定80000 - VipStage uint32 `struc:"uint32" default:"1" json:"vip_stage"` // 超no的外形等级建议固定1 - AutoCharge uint32 `struc:"uint32" default:"1" json:"auto_charge"` // nono是否自动充电 - VipEndTime uint32 `struc:"uint32" default:"4294967295" json:"vip_end_time"` // 超no的结束时间建议尽可能大 - FreshManBonus uint32 `struc:"uint32" json:"fresh_man_bonus"` // 邀请活动建议先给固定值0 - NonoChipList [80]byte `struc:"[80]byte" json:"-"` // 超no芯片列表 - DailyResArr [50]byte `struc:"[50]byte" default:"0" json:"daily_res_arr"` // 每日任务状态 40+是谱尼的 - Study struct { + UserID uint32 `struc:"uint32" json:"user_id"` // 米米号 通过sid拿到 + RegisterTime uint32 `struc:"uint32" json:"register_time"` // 注册时间(秒时间戳) + Nick string `struc:"[16]byte" default:"seer" json:"nick"` // 16字节昵称 + Vip uint16 `struc:"uint16" json:"vip"` // 固定0 + Viped uint16 `struc:"uint16" default:"15" json:"viped"` // 固定15 + DSFlag uint32 `struc:"uint32" json:"ds_flag"` // 固定0 + Color uint32 `struc:"uint32" json:"color"` // 机器人颜色RGB颜色值(uint32,实际为3个uint8) + Texture uint32 `struc:"uint32" json:"texture"` // 固定0 + Energy uint32 `struc:"uint32" default:"3000" json:"energy"` // 固定3000 + Coins uint32 `struc:"uint32" json:"coins"` // 赛尔豆 + EVPool uint32 `struc:"uint32" json:"ev_pool"` //累计学习力 + FightBadge uint32 `struc:"uint32" json:"fight_badge"` // 固定0 + MapID uint32 `struc:"uint32" default:"1" json:"map_id"` // 上线地图ID + Pos Pos `json:"pos"` // 坐标 + TimeToday uint32 `struc:"uint32" default:"0" json:"time_today"` // 已消耗时间(秒) + TimeLimit uint32 `struc:"uint32" default:"43200" json:"time_limit"` // 总电池限制(秒) + IsClothHalfDay byte `struc:"byte" json:"is_cloth_half_day"` // 活动标志0/1 + IsRoomHalfDay byte `struc:"byte" json:"is_room_half_day"` // 活动标志0/1 + IFortressHalfDay byte `struc:"byte" json:"i_fortress_half_day"` // 活动标志0/1 + IsHQHalfDay byte `struc:"byte" json:"is_hq_half_day"` // 活动标志0/1 + LoginCount uint32 `struc:"uint32" json:"login_count"` // 固定0 + Inviter uint32 `struc:"uint32" json:"inviter"` // 固定0 + NewInviteeCount uint32 `struc:"uint32" json:"new_invitee_count"` // 固定0 + VipLevel uint32 `struc:"uint32" default:"8" json:"vip_level"` // 固定8 + VipValue uint32 `struc:"uint32" default:"80000" json:"vip_value"` // 固定80000 + VipStage uint32 `struc:"uint32" default:"1" json:"vip_stage"` // 超no的外形等级建议固定1 + AutoCharge uint32 `struc:"uint32" default:"1" json:"auto_charge"` // nono是否自动充电 + VipEndTime uint32 `struc:"uint32" default:"4294967295" json:"vip_end_time"` // 超no的结束时间建议尽可能大 + FreshManBonus uint32 `struc:"uint32" json:"fresh_man_bonus"` // 邀请活动建议先给固定值0 + //NonoChipList [80]byte `struc:"[80]byte" json:"-"` // 超no芯片列表 + DailyResArr [50]byte `struc:"[50]byte" default:"0" json:"daily_res_arr"` // 每日任务状态 40+是谱尼的 + Study struct { TeacherID uint32 `struc:"uint32" json:"teacher_id"` // 教官id StudentID uint32 `struc:"uint32" json:"student_id"` // 学员id @@ -144,16 +144,16 @@ type PlayerInfo struct { Nick string `struc:"[16]byte" default:"nono" json:"nono_nick"` // nono名字(16字节) } - TeamInfo TeamInfo `struc:"struct" json:"team_info"` // 战队信息24字节 - TeamPkInfo TeamPKInfo `struc:"struct" json:"team_pk_info"` // 8字节 - Reserved byte `struc:"byte" json:"reserved"` // 1字节无内容 - Badge uint32 `struc:"uint32" default:"0" json:"badge"` // 默认0 - Reserved1 [27]byte `struc:"[27]byte" default:"3" json:"reserved1"` // 27字节默认3 - TaskList [500]byte `struc:"[500]byte" default:"0" json:"task_list"` // 任务状态数组500字节,默认3 - PetListCount uint32 `struc:"sizeof=PetList" json:"pet_list_count"` // 精灵列表长度 - PetList []PetInfo ` json:"pet_list"` // 精灵背包内信息 - ClothesCount uint32 `struc:"sizeof=Clothes" json:"clothes_count"` // 穿戴装备数量 - Clothes []PeopleItemInfo ` json:"clothes"` // 穿戴装备 + TeamInfo TeamInfo `struc:"struct" json:"team_info"` // 战队信息24字节 + TeamPkInfo TeamPKInfo `struc:"struct" json:"team_pk_info"` // 8字节 + Reserved byte `struc:"byte" json:"reserved"` // 1字节无内容 + Badge uint32 `struc:"uint32" default:"0" json:"badge"` // 默认0 + Reserved1 [27]byte `struc:"[27]byte" default:"3" json:"reserved1"` // 27字节默认3 + TaskList [1000]byte `struc:"[1000]byte" default:"0" json:"task_list"` // 任务状态数组500字节,默认3 + PetListCount uint32 `struc:"sizeof=PetList" json:"pet_list_count"` // 精灵列表长度 + PetList []PetInfo ` json:"pet_list"` // 精灵背包内信息 + ClothesCount uint32 `struc:"sizeof=Clothes" json:"clothes_count"` // 穿戴装备数量 + Clothes []PeopleItemInfo ` json:"clothes"` // 穿戴装备 } // TableName PlayerInfo's table name diff --git a/modules/blazing/model/talkconfig.go b/modules/blazing/model/talkconfig.go new file mode 100644 index 000000000..edd8b6ed1 --- /dev/null +++ b/modules/blazing/model/talkconfig.go @@ -0,0 +1,55 @@ +package model + +import ( + "blazing/cool" // 沿用你项目中已有的基础Model包 +) + +// 表名常量(遵循项目现有命名规范) +const TableNameMineralCollectionConfig = "mineral_collection_config" + +// MineralCollectionConfig 挖矿/采集/采摘矿产配置表Model定义 +// 字段完全匹配数据表结构,包含最小/最大产出核心字段 +type MineralCollectionConfig struct { + *cool.Model // 嵌入基础Model,包含id(主键)、createTime、updateTime等通用字段 + + // MapID 矿产所在地图ID + MapID uint32 `gorm:"column:map_id;not null;index:idx_mineral_collection_config_map_id;comment:矿产所在地图ID" json:"map_id"` + Type uint32 `gorm:"column:type;not null;index:idx_mineral_collection_config_type;comment:类型" json:"type"` + + // DailyCollectCount 每日可采集次数 + DailyCollectCount uint32 `gorm:"column:daily_collect_count;not null;comment:每日可采集次数" json:"daily_collect_count"` + + // ItemID 物品编号(对应道具系统ID) + ItemID string `gorm:"column:item_id;type:varchar(16);not null;index:idx_mineral_collection_config_item_id;comment:物品编号(对应道具系统ID)" json:"item_id"` + // ItemMinCount 单次采集最小产出数量 + ItemMinCount uint32 `gorm:"column:item_min_count;not null;comment:单次采集最小产出数量" json:"item_min_count"` + // ItemMaxCount 单次采集最大产出数量 + ItemMaxCount uint32 `gorm:"column:item_max_count;not null;comment:单次采集最大产出数量" json:"item_max_count"` + // Description 矿产描述 + Description string `gorm:"column:description;type:varchar(128); comment:矿产描述" json:"description"` +} + +// TableName 指定数据表名(必须匹配数据库表名,遵循项目规范) +func (*MineralCollectionConfig) TableName() string { + return TableNameMineralCollectionConfig +} + +// GroupName 指定表分组(与项目现有表保持一致,默认分组) +func (*MineralCollectionConfig) GroupName() string { + return "default" +} + +// NewMineralCollectionConfig 创建挖矿配置表实例(初始化基础Model) +// 保证通用字段(createTime/updateTime)被正确初始化 +func NewMineralCollectionConfig() *MineralCollectionConfig { + return &MineralCollectionConfig{ + Model: cool.NewModel(), // 调用基础Model的初始化方法 + } +} + +// init 程序启动时自动创建数据表(与项目现有表初始化逻辑一致) +// 若项目有统一的表初始化入口,可将此逻辑迁移至对应位置 +func init() { + // 自动创建表(不存在则创建,已存在则不操作) + cool.CreateTable(&MineralCollectionConfig{}) +} diff --git a/modules/blazing/service/info.go b/modules/blazing/service/info.go index bd3ac9ea0..6c81d9c86 100644 --- a/modules/blazing/service/info.go +++ b/modules/blazing/service/info.go @@ -37,11 +37,11 @@ func (s *InfoService) Reg(nick string, color uint32) { //设置用户信息 t.Data = model.NewPlayerInfo() t.Data.Nick = nick - t.Data.TaskList[3] = 3 //新手任务 - for i := 0; i < 80; i++ { //超NO芯片填充 - t.Data.NonoChipList[i] = 255 - } + // for i := 0; i < 80; i++ { //超NO芯片填充 + + // t.Data.NonoChipList[i] = 255 + // } t.Data.Color = color t.Data.RegisterTime = uint32(time.Now().Unix()) //写入注册时间 diff --git a/modules/blazing/service/pet.go b/modules/blazing/service/pet.go index dba4ea23a..4e69a07a9 100644 --- a/modules/blazing/service/pet.go +++ b/modules/blazing/service/pet.go @@ -2,6 +2,7 @@ package service import ( "blazing/cool" + "blazing/modules/base/service" "blazing/modules/blazing/model" "context" "fmt" @@ -64,24 +65,50 @@ func (s *PetService) Pet_del(cachetime uint32) { cool.DBM(s.Model).Where("player_id", s.userid).Where("catch_time", cachetime).Delete() } + +// 精灵真正添加后的捕捉时间才是真正的时间 func (s *PetService) PetAdd(y *model.PetInfo) { + sql := fmt.Sprintf(` +UPDATE %s +SET max_ts = CASE + WHEN max_ts < EXTRACT(EPOCH FROM NOW())::INT THEN EXTRACT(EPOCH FROM NOW())::INT + ELSE max_ts + 1 +END +WHERE id = ? AND deleted_at IS NULL +RETURNING max_ts; +`, service.NewBaseSysUserService().Model.TableName()) - for { - m1 := cool.DBM(s.Model).Where("player_id", s.userid) - var player model.PetEX - player.PlayerID = s.userid - player.Data = *y - player.CatchTime = y.CatchTime - player.Free = 0 + // 执行 Raw SQL 并扫描返回值 + ret, err := cool.DBM(service.NewBaseSysUserService().Model).Raw(sql, s.userid).All() + //fmt.Println(ret, err) + y.CatchTime = ret.Array()[0].Uint32() + m1 := cool.DBM(s.Model).Where("player_id", s.userid) + var player model.PetEX + player.PlayerID = s.userid + player.Data = *y + player.CatchTime = y.CatchTime + player.Free = 0 - _, err := m1.Insert(player) - if err != nil { - fmt.Println("添加失败id自增1继续添加") - y.CatchTime += 1 //自增保持时间排序 - continue - } - break + _, err = m1.Insert(player) + if err != nil { + panic(err) } + // for { + // m1 := cool.DBM(s.Model).Where("player_id", s.userid) + // var player model.PetEX + // player.PlayerID = s.userid + // player.Data = *y + // player.CatchTime = y.CatchTime + // player.Free = 0 + + // _, err := m1.Insert(player) + // if err != nil { + // fmt.Println("添加失败id自增1继续添加") + // y.CatchTime += 1 //自增保持时间排序 + // continue + // } + // break + // } } func (s *PetService) ModifyBefore(ctx context.Context, method string, param map[string]interface{}) (err error) { diff --git a/modules/blazing/service/talk.go b/modules/blazing/service/talk.go index e1a72fb97..bfd1e5157 100644 --- a/modules/blazing/service/talk.go +++ b/modules/blazing/service/talk.go @@ -5,6 +5,18 @@ import ( "blazing/modules/blazing/model" ) +type TalkConfigService struct { + *cool.Service +} + +func NewTalkConfigService() *TalkConfigService { + return &TalkConfigService{ + + Service: &cool.Service{Model: model.NewMineralCollectionConfig()}, + } + +} + type TalkService struct { BaseService }