refactor(logic): 重构服务器启动逻辑与任务状态管理

- 移除了 `gcmd` 包在 controller 中的直接使用,改为通过参数传递端口和服务器类型
- 统一使用 `GetTask` 和 `SetTask` 方法替代直接访问 `TaskList` 数组,提升代码可维护性
- 修改了战斗逻辑中部分调试打印语句,并优化战斗循环结束日志输出
- 调整了新手玩家初始化流程,默认完成新手任务4
- 更新了数据库模型字段及结构定义,如增加 `max_ts` 字段、扩展 `TaskList` 长度等
- 改进了宠物添加逻辑,采用 SQL 方式确保捕捉时间唯一递增
- 清理了无用或注释掉的旧代码块
This commit is contained in:
2025-12-08 17:03:43 +08:00
parent 7005c1047f
commit 8983222dcb
21 changed files with 341 additions and 177 deletions

90
.vscode/launch.json vendored
View File

@@ -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",
}
]
}
"program": "${workspaceFolder}/logic"
}
// {
// "name": "Launch login-tcp",
// "type": "go",
// "request": "launch",
// "mode": "auto",
// "cwd": "${workspaceFolder}",
// "args": ["-port=0"],
// "program": "${workspaceFolder}/logic",
// }
]
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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

View File

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

View File

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

View File

@@ -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 {

View File

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

View File

@@ -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
}
}

View File

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

View File

@@ -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")

23
login/internal/cmd/reg.go Normal file
View File

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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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{})
}

View File

@@ -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()) //写入注册时间

View File

@@ -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) {

View File

@@ -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
}