fix(socket): 修复TCP连接处理中逻辑取反错误

修复了`handleTcp`函数中对`s.discorse`的判断条件错误,导致CORS配置未正确应用的问题。

feat(player): 增加地图切换标记支持

在`Player`结构体中新增`Changemap`字段,用于标识玩家是否切换过地图,并在相关业务逻辑中进行设置和判断。

feat(pet): 重构精灵生成与经验处理逻辑

将`GenPetInfo`方法从model包迁移至player包,增加个体值、性格、特性等随机生成逻辑,优化技能学习处理方式。

refactor(service): 优化定时任务与连接管理

使用`cool.Cron`替代原生ticker实现刷怪定时任务,优化连接获取方式,确保并发安全。

refactor(model): 移除冗余代码并优化结构

从`pet.go`中移除已迁移至`player`包的函数定义,精简模型结构,提升模块清晰度。

refactor(config): 更新部门及字典名称配置

将`base_sys_department.json`和
This commit is contained in:
2025-10-13 18:51:41 +08:00
parent b258a81bb8
commit 79213c67d6
23 changed files with 268 additions and 175 deletions

View File

@@ -150,7 +150,7 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) {
func (s *Server) handleTcp(conn gnet.Conn) (action gnet.Action) {
for {
if !s.discorse {
if s.discorse {
handle(conn)
}
data, err := s.codec.Decode(conn)
@@ -181,7 +181,7 @@ func (s *Server) handleTcp(conn gnet.Conn) (action gnet.Action) {
}
func (s *Server) parser(c gnet.Conn, line []byte) {
c.Context().(*player.ClientData).IsCrossDomain = true
//todo 这里待实现注入player实体
s.handler.Handle(c, line)
}

View File

@@ -37,7 +37,7 @@ func NewServer(options ...Option) *Server {
workerPool: goroutine.Default(),
bufferSize: 4096, //默认缓冲区大小
multicore: true,
discorse: true,
//discorse: true,
}
for _, option := range options {
option(server)
@@ -52,7 +52,7 @@ func WithSocketCodec(codec codec.SocketCodec) Option {
}
func WithCORS() Option {
return func(u *Server) {
u.discorse = false
u.discorse = true
}
}
func WithSocketHandler(handler Handler) Option {

View File

@@ -27,7 +27,7 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
petid = 7
}
mo = model.GenPetInfo(
mo = c.GenPetInfo(
int(petid), 24, //24个体
-1,
0, //野怪没特性
@@ -55,7 +55,7 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
mo := model.GenPetInfo(
mo := c.GenPetInfo(
int(refpet.Id), -1,
-1,
0, //野怪没特性

View File

@@ -39,6 +39,7 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c *player.Conn) (result *us
t.Info = t.Service.Person(data.Head.UserID)
t.Info.UserID = data.Head.UserID
t.Onlinetime = uint32(time.Now().Unix()) //保存时间戳
t.Changemap = true
share.ShareManager.SetUserOnline(data.Head.UserID, h.Port) //设置用户登录服务器

View File

@@ -36,7 +36,8 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho
}
func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) (result *space.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
//result = &maps.LeaveMapOutboundInfo{UserID: c.GetUserID()}
c.Canmon = false //可以刷怪
c.Canmon = false
c.Changemap = true //可以刷怪
data.Broadcast(c.Info.MapID, space.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
space.GetSpace(c.Info.MapID).User.Remove(c.Info.UserID)
// 如果有正在运行的刷怪协程,发送停止信号

View File

@@ -48,7 +48,7 @@ func (h *Controller) GetPetList(
result.ShortInfoList = make([]pet.PetShortInfo, len(tt))
for i, v := range tt {
copier.Copy(&result.ShortInfoList[i], &v)
copier.Copy(&result.ShortInfoList[i], &v.Data)
}
return result, 0

View File

@@ -7,6 +7,7 @@ import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/player"
"fmt"
"math"
"github.com/gogf/gf/v2/util/gconv"
@@ -127,17 +128,18 @@ func (f *FightC) ReadyFight(c common.PlayerI) {
}
switch f.Info.Status {
case 1: //pvp
case info.BattleStatus.FIGHT_WITH_PLAYER: //pvp
f.GetInputByPlayer(c, false).Finished = true
if f.GetInputByPlayer(c, true).Finished {
rrsult()
}
case 2: // 6v6
case info.BattleStatus.FIGHT_WITH_BOSS: // 6v6
rrsult()
case 3: // 野怪战斗
case info.BattleStatus.FIGHT_WITH_NPC: // 野怪战斗
//判断捕捉率大于0
fmt.Println("CatchRate", xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate)
if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 {
rett.Info2.Catchable = 1
t, _ := f.Opp.Player.(*player.AI_player)

View File

@@ -1,6 +1,7 @@
package player
import (
"blazing/cool"
"blazing/modules/blazing/model"
"time"
)
@@ -14,28 +15,12 @@ func NewPlayer(opts ...PlayerOption) *Player {
}
p.monsters = generateThreeUniqueNumbers()
p.StopChan = make(chan struct{})
// 启动刷怪协程
go func(stopChan chan struct{}) {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
case <-stopChan:
// 收到停止信号,退出协程
return
case <-ticker.C:
// 刷新当前地图的怪物
if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪
p.SpawnMonsters()
}
}
p.StopChan = cool.Cron.ScheduleFunc(10*time.Second, func() {
if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪
p.SpawnMonsters()
}
}(p.StopChan)
})
for _, opt := range opts {
opt(p)
}

View File

@@ -3,10 +3,13 @@ package player
import (
"blazing/common/data/xmlres"
"blazing/logic/service/fight/info"
"math/rand"
"time"
"blazing/modules/blazing/model"
"math"
"github.com/gogf/gf/v2/util/gconv"
"github.com/jinzhu/copier"
)
@@ -85,7 +88,7 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
//player.SendMessage(generatePetUpdateInfo(petEntity, originalExp+addExp-exp, addition))
// 处理技能学习
canLearnSkillList := model.LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level)) //获取最后四个技能,如果不足,那就取全部技能
canLearnSkillList := LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level)) //获取最后四个技能,如果不足,那就取全部技能
for i := 0; i < 4; i++ {
@@ -117,3 +120,115 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
// return exp
}
func LastFourElements[T any](s []T) []T {
n := len(s)
if n <= 4 {
// 切片长度小于等于4时返回整个切片
return s
}
// 切片长度大于4时返回最后4个元素从n-4索引到末尾
return s[n-4:]
}
// -1是随机
// * @param petTypeId 精灵类型ID
// * @param individualValue 个体值
// * @param natureId 性格ID
// * @param abilityTypeEnum 特性类型
// * @param isShiny 是否为闪光
// * @param level 等级
// * @return 生成的精灵实体
func (player *Player) GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level int) *model.PetInfo {
// 设置随机数种子,确保每次运行生成不同的随机数序列
rand.Seed(time.Now().UnixNano())
p := &model.PetInfo{ID: uint32(id),
EffectInfo: make([]model.PetEffectInfo, 0),
CatchTime: uint32(time.Now().Unix()),
Level: uint32(level)} //等级
if shinyid != -1 {
p.Shiny = uint32(shinyid)
}
if natureId != -1 {
p.Nature = uint32(natureId)
} else {
p.Nature = uint32(rand.Intn(25))
}
if dv != -1 {
p.Dv = uint32(dv)
} else {
p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
}
if abilityTypeEnum != -1 {
if abilityTypeEnum != 0 {
v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
p.EffectInfo = append(p.EffectInfo, model.PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
} else {
for i, v := range xmlres.PlayerEffectMAP {
if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
p.EffectInfo = append(p.EffectInfo, model.PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
}
}
tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
for i := 0; i < len(tttt); i++ {
p.SkillList[i].ID = tttt[i]
p.SkillList[i].PP = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
}
p.SkillListLen = uint32(len(tttt))
p.CalculatePetPane()
p.Hp = p.MaxHp
player.AddPetExp(p, 0)
return p
}
// 除数数组放大100倍
// 数组按递增顺序排列,用于判断个体值等级
var divisors = []int{
600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
36600, 37500, 38300, 39000, 39600,
}
// CalculateIndividual 根据给定的a值计算个体值
// 返回值表示a大于等于多少个除数范围0-31
func CalculateIndividual(a int) int {
individual := 0
for _, divisor := range divisors {
if a >= divisor {
individual++
} else {
break // 数组是递增的,可提前跳出循环
}
}
return individual
}
// CalculateIndividualValue 计算个体值0-31
// 接收外部随机数生成器,便于控制随机性和复用
func CalculateIndividualValue(random *rand.Rand) int {
// 生成0-40000的随机数作为个体值计算的输入
a := random.Intn(40001)
return CalculateIndividual(a)
}

View File

@@ -19,6 +19,7 @@ import (
"sync"
"time"
"github.com/antlabs/timer"
"github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil"
"github.com/gogf/gf/v2/frame/g"
@@ -59,17 +60,17 @@ func NewClientData() *ClientData {
var Mainplayer = &utils.SyncMap[uint32, *Player]{} //玩家数据
func (c *Conn) SendPack(bytes []byte) error {
if t, ok := c.MainConn.Context().(*ClientData); ok {
if t, ok := c.GetConn().Context().(*ClientData); ok {
if t.Wsmsg.Upgraded {
// This is the echo server
err := wsutil.WriteServerMessage(c.MainConn, ws.OpBinary, bytes)
if err != nil {
logging.Infof("conn[%v] [err=%v]", c.MainConn.RemoteAddr().String(), err.Error())
logging.Infof("conn[%v] [err=%v]", c.GetConn().RemoteAddr().String(), err.Error())
return err
}
} else {
_, err := c.MainConn.Write(bytes)
_, err := c.GetConn().Write(bytes)
if err != nil {
glog.Debug(context.Background(), err)
@@ -98,17 +99,18 @@ type Player struct {
loginChan chan struct{} // 登录完成通知通道
StopChan chan struct{} //停止刷怪协程
StopChan timer.TimeNoder
context.Context
PVPinfo *info.PVPinfo //当前邀请的玩家ID
Onlinetime uint32 //当前登录时间
OgreInfo *OgreInfo
OgreInfo OgreInfo
Service *blservice.UserService
HavePVPinfo []*Player
monsters [3]int
Canmon bool //可以刷怪
Changemap bool //是否切换过地图
}
// PlayerOption 定义配置 Player 的函数类型
@@ -131,11 +133,9 @@ func (p *Player) SpawnMonsters() {
// 创建数据包
tt := NewTomeeHeader(2004, p.Info.UserID)
p.monsters, _, _ = replaceOneNumber(p.monsters)
p.genMonster(p.Info.MapID) //生成野怪
p.SendPack(tt.Pack(p.OgreInfo))
p.SendPack(tt.Pack(&p.OgreInfo))
}
@@ -149,6 +149,8 @@ func RandomStringFromSlice(s []string) string {
// 应该根据怪物信息决定后端生成
func (p *Player) genMonster(mapid uint32) {
var oldnum, newNum int
p.monsters, oldnum, newNum = replaceOneNumber(p.monsters)
// 设置怪物信息
t1 := OgreInfo{}
mapss, ok := xmlres.MonsterMap[gconv.Int(mapid)]
@@ -170,13 +172,18 @@ func (p *Player) genMonster(mapid uint32) {
}
t2 := OgreInfo{}
for i := 0; i < 3; i++ {
if p.Changemap {
p.Changemap = false
p.OgreInfo = OgreInfo{} //切地图清空
for i := 0; i < 3; i++ {
t2.Data[p.monsters[i]] = t1.Data[p.monsters[i]]
p.OgreInfo.Data[p.monsters[i]] = t1.Data[p.monsters[i]]
}
} else {
p.OgreInfo.Data[oldnum] = OgrePetInfo{}
p.OgreInfo.Data[newNum] = t1.Data[newNum]
}
p.OgreInfo = &t2
}
// 生成0-9之间三个不重复的随机数 进地图5s
@@ -294,7 +301,8 @@ func (p *Player) Save() {
p.Service.Save(p.Info)
LeaveMap(p)
close(p.StopChan) //停止刷怪
p.StopChan.Stop() //停止刷怪
p.IsLogin = false
Mainplayer.Delete(p.Info.UserID)

View File

@@ -3,11 +3,10 @@ package player
import "blazing/common/socket/errorcode"
func GetPlayer(c *Conn, userid uint32) *Player { //TODO 这里待优化,可能存在内存泄漏问题
c.Mu.Lock()
defer c.Mu.Unlock()
//检查player初始化是否为conn初始后取map防止二次连接后存在两个player
clientdata := c.MainConn.Context().(*ClientData)
clientdata := c.GetConn().Context().(*ClientData)
if clientdata.Player == nil {
clientdata.Player = NewPlayer(
@@ -38,7 +37,7 @@ func KickPlayer(userid uint32) { //踢出玩家
//实际上这里有个问题,会造成重复保存问题
player1.SendPack(head.Pack(nil))
player1.MainConn.MainConn.Close()
player1.MainConn.GetConn().Close()
// clientdata.Player = player
}

View File

@@ -17,6 +17,13 @@ type Conn struct {
Mu sync.Mutex
}
func (c *Conn) GetConn() gnet.Conn {
c.Mu.Lock()
defer c.Mu.Unlock()
return c.MainConn
}
func NewConn(c gnet.Conn) *Conn {
return &Conn{MainConn: c}
}

View File

@@ -4,7 +4,7 @@
"createTime": "2025-07-05 11:18:43.560949 +00:00",
"updateTime": "2025-07-05 11:18:43.560949 +00:00",
"deleted_at": null,
"name": "COOL",
"name": "SUN",
"parentId": null,
"orderNum": 0
},

View File

@@ -80,6 +80,7 @@ func (s *BaseSysUserService) ServiceAdd(ctx context.Context, req *cool.AddReq) (
r = g.RequestFromCtx(ctx)
reqmap = r.GetMap()
)
// 如果reqmap["password"]不为空则对密码进行md5加密
if !r.Get("password").IsNil() {
reqmap["password"] = gmd5.MustEncryptString(r.Get("password").String())
@@ -89,6 +90,27 @@ func (s *BaseSysUserService) ServiceAdd(ctx context.Context, req *cool.AddReq) (
return
}
data = g.Map{"id": lastInsertId}
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
if !r.Get("roleIdList").IsNil() {
inRoleIdSet := gset.NewFrom(r.Get("roleIdList").Ints())
roleArray := garray.NewArray()
inRoleIdSet.Iterator(func(v interface{}) bool {
roleArray.PushRight(g.Map{
"userId": gconv.Uint(lastInsertId),
"roleId": gconv.Uint(v),
})
return true
})
_, err = cool.DBM(model.NewBaseSysUserRole()).Fields("userId,roleId").Insert(roleArray)
if err != nil {
return err
}
}
return
})
return
}
@@ -252,7 +274,7 @@ func NewBaseSysUserService() *BaseSysUserService {
Extend: func(ctx g.Ctx, m *gdb.Model) *gdb.Model {
return m.Group(`base_sys_user.id`)
},
KeyWordField: []string{"name", "username", "nickName"},
KeyWordField: []string{"username", "email"},
},
},
}

View File

@@ -0,0 +1,50 @@
package admin
import (
"blazing/cool"
"blazing/modules/blazing/model"
"blazing/modules/blazing/service"
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
)
type PetBagController struct {
*cool.Controller
}
type PetGetReq struct {
g.Meta `path:"/genpet" method:"POST"`
// 新增:精灵相关参数(完全对齐自定义表单配置)
PetTypeId int `json:"petTypeId" v:"required|min:1" comment:"精灵类型ID必填正整数最小1无0或负数类型对应GenPetInfo的id参数"`
IndividualValue int `json:"individualValue" v:"required|between:-1,31" comment:"精灵个体值,必填,范围-1~31-1表示随机生成满个体0~31为固定值决定基础属性上限"`
NatureId int `json:"natureId" v:"required|between:-1,24" comment:"精灵性格ID必填范围-1~24-1表示随机0~24对应25种固定性格影响属性加成"`
AbilityTypeEnum int `json:"abilityTypeEnum" v:"required|min:-1" comment:"精灵特性类型ID必填最小值-1-1表示随机选择1个特性0及以上为固定特性ID需与PlayerEffectMAP匹配"`
IsShiny int `json:"isShiny" v:"min:-1" comment:"精灵异色闪光ID必填最小值-1-1表示随机0及以上为固定异色状态稀有精灵特殊外观/属性原表单hidden但需保留必填逻辑"`
Level int `json:"level" v:"required|between:1,100" comment:"精灵等级必填范围1~100常规游戏等级上限影响精灵当前属性强度"`
}
func init() {
var task_info_controller = &PetBagController{
&cool.Controller{
Prefix: "/admin/monster/bag",
Api: []string{"Delete", "Update", "Info", "List", "Page"},
Service: service.NewPetService(),
},
}
// 注册路由
cool.RegisterController(task_info_controller)
}
func (c *PetBagController) GetSession(ctx context.Context, req *PetGetReq) (res *cool.BaseRes, err error) {
fmt.Println(req)
var (
admin = cool.GetAdmin(ctx)
//r = g.RequestFromCtx(ctx)
)
t := model.GenPetInfo(
req.PetTypeId, req.IndividualValue, req.NatureId, req.AbilityTypeEnum, req.IsShiny, req.Level)
service.NewUserService(uint32(admin.UserId)).PetAdd(*t)
return
}

View File

@@ -1,46 +1,9 @@
package model
import (
"blazing/common/data/xmlres"
"blazing/cool"
"math/rand"
"time"
"github.com/gogf/gf/v2/util/gconv"
)
// 除数数组放大100倍
// 数组按递增顺序排列,用于判断个体值等级
var divisors = []int{
600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
36600, 37500, 38300, 39000, 39600,
}
// CalculateIndividual 根据给定的a值计算个体值
// 返回值表示a大于等于多少个除数范围0-31
func CalculateIndividual(a int) int {
individual := 0
for _, divisor := range divisors {
if a >= divisor {
individual++
} else {
break // 数组是递增的,可提前跳出循环
}
}
return individual
}
// CalculateIndividualValue 计算个体值0-31
// 接收外部随机数生成器,便于控制随机性和复用
func CalculateIndividualValue(random *rand.Rand) int {
// 生成0-40000的随机数作为个体值计算的输入
a := random.Intn(40001)
return CalculateIndividual(a)
}
const TableNamePet = "pet"
// Pet mapped from table <pet>
@@ -65,87 +28,6 @@ type PetS struct {
Data []PetInfo `orm:"data" dc:"资源规格"`
}
func LastFourElements[T any](s []T) []T {
n := len(s)
if n <= 4 {
// 切片长度小于等于4时返回整个切片
return s
}
// 切片长度大于4时返回最后4个元素从n-4索引到末尾
return s[n-4:]
}
// -1是随机
// * @param petTypeId 精灵类型ID
// * @param individualValue 个体值
// * @param natureId 性格ID
// * @param abilityTypeEnum 特性类型
// * @param isShiny 是否为闪光
// * @param level 等级
// * @return 生成的精灵实体
func GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level int) *PetInfo {
// 设置随机数种子,确保每次运行生成不同的随机数序列
rand.Seed(time.Now().UnixNano())
p := &PetInfo{ID: uint32(id),
EffectInfo: make([]PetEffectInfo, 0),
CatchTime: uint32(time.Now().Unix()),
Level: uint32(level)} //等级
if shinyid != -1 {
p.Shiny = uint32(shinyid)
}
if natureId != -1 {
p.Nature = uint32(natureId)
} else {
p.Nature = uint32(rand.Intn(25))
}
if dv != -1 {
p.Dv = uint32(dv)
} else {
p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
}
if abilityTypeEnum != -1 {
if abilityTypeEnum != 0 {
v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
} else {
for i, v := range xmlres.PlayerEffectMAP {
if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
}
}
tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
for i := 0; i < len(tttt); i++ {
p.SkillList[i].ID = tttt[i]
p.SkillList[i].PP = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
}
p.SkillListLen = uint32(len(tttt))
p.CalculatePetPane()
p.Hp = p.MaxHp
return p
}
// PetInfo 精灵信息结构(合并后的优化版本)
type PetInfo struct {

View File

@@ -3,6 +3,7 @@ package service
import (
"blazing/cool"
"blazing/modules/blazing/model"
"context"
)
// 获取精灵信息 0是仓库,1是背包,2是放生
@@ -43,3 +44,23 @@ func (s *UserService) PetAdd(y model.PetInfo) {
m1.Insert(player)
}
func NewPetService() *MonsterService {
return &MonsterService{
&cool.Service{
Model: model.NewPet(),
PageQueryOp: &cool.QueryOp{
Where: func(ctx context.Context) [][]interface{} {
var (
admin = cool.GetAdmin(ctx)
userId = admin.UserId
)
return [][]interface{}{
{"player_id", userId, true},
{"in_bag", 0, true},
}
},
},
},
}
}

View File

@@ -44,7 +44,7 @@
"createTime": "2022-07-06 14:22:18.309000",
"updateTime": "2022-07-06 14:22:18.309000",
"typeId": 2,
"name": "COOL",
"name": "SUN",
"orderNum": 1,
"remark": null,
"parentId": null

View File

@@ -1 +0,0 @@
E:/newcode/blazing/public/assets/210.xml

1
public/config/221.xml Symbolic link
View File

@@ -0,0 +1 @@
E:/newcode/sun/public/assets/221.xml

View File

@@ -1 +1 @@
E:/newcode/blazing/public/assets/226.xml
E:/newcode/sun/public/assets/226.xml

View File

@@ -1 +1 @@
E:/newcode/blazing/public/assets/227.xml
E:/newcode/sun/public/assets/227.xml

View File

@@ -1 +1 @@
E:/newcode/blazing/public/assets/43.xml
E:/newcode/sun/public/assets/43.xml