diff --git a/logic/controller/fight_boss.go b/logic/controller/fight_boss.go index d74089e7..a0c0080e 100644 --- a/logic/controller/fight_boss.go +++ b/logic/controller/fight_boss.go @@ -121,9 +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.GetTask(taskid) == player.Unaccepted { - c.SetTask(taskid, player.Completed) //设置完成任务 - c.Info.TaskList[taskid-1] = 3 + if c.Info.GetTask(taskid) == model.Unaccepted { + c.Info.SetTask(taskid, model.Completed) //设置完成任务 moinfo.PetList[0].Downgrade(1) PetID := moinfo.PetList[0].ID diff --git a/logic/controller/login.go b/logic/controller/login.go index 07f80a45..0afaabd8 100644 --- a/logic/controller/login.go +++ b/logic/controller/login.go @@ -58,6 +58,7 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user. t.Service = blservice.NewUserService(data.Head.UserID) t.User = service.NewBaseSysUserService() t.Info = t.Service.Info.Personself() + if t.Info == nil { defer c.Close() return diff --git a/logic/controller/task.go b/logic/controller/task.go index a7d25baf..8f6fc217 100644 --- a/logic/controller/task.go +++ b/logic/controller/task.go @@ -19,8 +19,8 @@ func (h Controller) AcceptTask(data *task.AcceptTaskInboundInfo, c *player.Playe // //isdaliy = true // } - if c.GetTask(int(data.TaskId)) == player.Unaccepted { - c.SetTask(int(data.TaskId), player.Accepted) + if c.Info.GetTask(int(data.TaskId)) == model.Unaccepted { + c.Info.SetTask(int(data.TaskId), model.Accepted) } c.Service.Task.Exec(uint32(data.TaskId), func(t *model.TaskEX) bool { @@ -55,12 +55,12 @@ 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.GetTask(int(data.TaskId)) != player.Accepted { //如果任务没有接受或者已经完成Complete_Task + if c.Info.GetTask(int(data.TaskId)) != model.Accepted { //如果任务没有接受或者已经完成Complete_Task return result, 0 } - c.SetTask(int(data.TaskId), player.Completed) + c.Info.SetTask(int(data.TaskId), model.Completed) result = &task.CompleteTaskOutboundInfo{ TaskId: data.TaskId, @@ -112,8 +112,8 @@ 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.GetTask(int(data.TaskId)) == player.Accepted { - c.SetTask(int(data.TaskId), player.Unaccepted) + if c.Info.GetTask(int(data.TaskId)) == model.Accepted { + c.Info.SetTask(int(data.TaskId), model.Unaccepted) return &task.DeleteTaskOutboundInfo{TaskId: data.TaskId}, 0 } diff --git a/logic/service/player/player.go b/logic/service/player/player.go index f04b75f2..a02ee159 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -8,7 +8,6 @@ import ( "blazing/logic/service/common" "blazing/logic/service/fight/info" "blazing/logic/service/space" - "math/rand" "strings" "sync/atomic" @@ -17,7 +16,6 @@ import ( blservice "blazing/modules/blazing/service" "context" - "time" "github.com/antlabs/timer" "github.com/gogf/gf/v2/frame/g" @@ -187,8 +185,7 @@ func (p *Player) SendPack(b []byte) error { // 2. 从 string 类型 slice 随机选一个元素 func RandomStringFromSlice(s []string) string { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - randomIdx := r.Intn(len(s)) + randomIdx := grand.Intn(len(s)) return s[randomIdx] } @@ -321,7 +318,8 @@ func (p *Player) ItemAdd(t ...model.ItemInfo) (result []model.ItemInfo) { } if p.Service.Item.CheakItem(v.ItemId)+v.ItemCnt > uint32(itemx.Max) { - cool.Loger.Error(context.TODO(), "物品超过拥有最大限制", v.ItemId) + + println(p.Info.UserID, "物品超过拥有最大限制", v.ItemId) t1 := common.NewTomeeHeader(2601, p.Info.UserID) t1.Result = uint32(errorcode.ErrorCodes.ErrTooManyOfItem) diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 2118249a..e01b3b68 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -3,6 +3,7 @@ package player import ( "blazing/common/data/share" "blazing/cool" + "blazing/modules/blazing/model" "blazing/logic/service/fight/info" "blazing/logic/service/space" @@ -71,7 +72,7 @@ func (lw *Player) CompleteLogin() { } if lw.IsNewPlayer() { //重置新手地图,放到机械仓 - lw.SetTask(4, Completed) //设置新手任务默认完成 + lw.Info.SetTask(4, model.Completed) //设置新手任务默认完成 lw.Info.MapID = 8 if len(lw.Info.PetList) == 0 { rr := lw.Service.Pet.PetInfo(0) @@ -88,7 +89,7 @@ func (lw *Player) CompleteLogin() { func (lw *Player) IsNewPlayer() bool { // 遍历84到87的索引 for i := 84; i <= 87; i++ { - if lw.GetTask(i) != Completed { + if lw.Info.GetTask(i) != model.Completed { return true // 只要有一个不等于3,就返回true } } diff --git a/logic/service/player/task.go b/logic/service/player/task.go deleted file mode 100644 index f26e68d9..00000000 --- a/logic/service/player/task.go +++ /dev/null @@ -1,45 +0,0 @@ -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/logic/service/space/hot.go b/logic/service/space/hot.go index 9665e631..d12f21ae 100644 --- a/logic/service/space/hot.go +++ b/logic/service/space/hot.go @@ -1,10 +1,5 @@ package space -import ( - "golang.org/x/sync/singleflight" -) - -var requestGroup singleflight.Group // SingleFlight 实例 // MapHotInfo 表示地图热度信息 type MapHotInfo struct { MapID uint32 `json:"mapId"` // 地图ID diff --git a/modules/blazing/model/pet.go b/modules/blazing/model/pet.go index 3ecb64de..3a08b421 100644 --- a/modules/blazing/model/pet.go +++ b/modules/blazing/model/pet.go @@ -11,6 +11,7 @@ import ( "time" "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/grand" "github.com/jinzhu/copier" "github.com/samber/lo" ) @@ -397,7 +398,7 @@ func GenPetInfo( dv, natureId, abilityTypeEnum, shinyid, level int, ) *PetInfo { // 创建随机源 - rng := rand.New(rand.NewSource(time.Now().UnixNano())) + //rng := rand.New(rand.NewSource(time.Now().UnixNano())) // 初始化精灵 p := &PetInfo{ @@ -414,14 +415,14 @@ func GenPetInfo( // ---- 性格 ---- if natureId == -1 { - p.Nature = uint32(rng.Intn(25)) + p.Nature = uint32(grand.Intn(25)) } else { p.Nature = uint32(natureId) } // ---- 个体值(DV)---- if dv == -1 { - p.Dv = uint32(CalculateIndividualValue(rng)) + p.Dv = uint32(CalculateIndividualValue()) } else { if dv < 0 { dv = 0 @@ -447,7 +448,7 @@ func GenPetInfo( } case abilityTypeEnum == -1: // 随机特性 - randomIndex := rng.Intn(len(xmlres.PlayerEffectMAP)) + randomIndex := grand.Intn(len(xmlres.PlayerEffectMAP)) var i int for _, v := range xmlres.PlayerEffectMAP { @@ -512,8 +513,8 @@ func CalculateIndividual(a int) int { // CalculateIndividualValue 计算个体值(0-31) // 接收外部随机数生成器,便于控制随机性和复用 -func CalculateIndividualValue(random *rand.Rand) int { +func CalculateIndividualValue() int { // 生成0-40000的随机数,作为个体值计算的输入 - a := random.Intn(40001) + a := grand.Intn(40001) return CalculateIndividual(a) } diff --git a/modules/blazing/model/player.go b/modules/blazing/model/player.go index 6aadc19b..20fa4ba0 100644 --- a/modules/blazing/model/player.go +++ b/modules/blazing/model/player.go @@ -2,6 +2,7 @@ package model import ( "blazing/cool" + "fmt" "math" "github.com/creasty/defaults" @@ -67,6 +68,48 @@ func NewPlayerInfo() PlayerInfo { return l } +// 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 *PlayerInfo) 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.TaskList[byteIdx] &^= 0x3 << bitOffset + + // 设置新状态(确保只取低 2 位) + m.TaskList[byteIdx] |= byte(status&0x3) << bitOffset + + return nil +} + +// GetTask 获取第 i 个任务的状态 +func (m *PlayerInfo) 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.TaskList[byteIdx] >> bitOffset) & 0x3) +} + type PlayerInfo struct { ExpPool uint32 `struc:"skip" json:"exp_pool"` // 累计经验池 //LastResetTime time.Time `struc:"skip" json:"last_reset_time"` // 重置时间,比如电池和每日任务 diff --git a/modules/blazing/service/info.go b/modules/blazing/service/info.go index 6c81d9c8..f1d6cf8c 100644 --- a/modules/blazing/service/info.go +++ b/modules/blazing/service/info.go @@ -85,7 +85,8 @@ func (s *InfoService) Personself() *model.PlayerInfo { tttL, ok := xmlres.TaskMap[i] if ok { if tttL.Type == 1 { //日常任务 - tt.Data.TaskList[i-1] = 0 //重置每日任务 + + tt.Data.SetTask(i, model.Unaccepted) } } diff --git a/modules/blazing/service/pet_fusion_material_service.go b/modules/blazing/service/pet_fusion_material_service.go index f38f76b8..0932b538 100644 --- a/modules/blazing/service/pet_fusion_material_service.go +++ b/modules/blazing/service/pet_fusion_material_service.go @@ -6,8 +6,11 @@ import ( "blazing/modules/blazing/model" dictmodel "blazing/modules/dict/model" "blazing/modules/dict/service" + "context" + "strings" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/grand" ) @@ -27,14 +30,24 @@ func NewPetFusionMaterialService() *PetFusionMaterialService { } } +var ( + cachePetFusionMaterialService = gcache.New() +) + +func (s *PetFusionMaterialService) ModifyBefore(ctx context.Context, method string, param g.MapStrAny) (err error) { + cachePetFusionMaterialService.Clear(context.Background()) + return nil +} + // 获取融合材料的特性,返回两个值,一个是指定的特性,另一个是如果配方没找到的情况下,默认的配置 func (s *PetFusionMaterialService) Data(Material1 [4]uint32) uint32 { - fusion, _ := service.NewDictInfoService().DataOne("fusion") + cacheKey := strings.Join(gconv.Strings(Material1[:]), ":") + println(cacheKey, "获取融合id") - fusions := utils.ToMap(fusion, func(t dictmodel.DictInfo) uint32 { + fusions := utils.ToMap(service.NewDictInfoService().DataOne("fusion"), func(t dictmodel.DictInfo) uint32 { - return gconv.Uint32(t.Remark) + return gconv.Uint32(t.Remark) //物品id转id }) for _, v := range Material1 { _, ok := fusions[v] @@ -44,42 +57,46 @@ func (s *PetFusionMaterialService) Data(Material1 [4]uint32) uint32 { } } - m := cool.DBM(s.Model) + ret, err := cachePetFusionMaterialService.GetOrSetFuncLock(context.Background(), cacheKey, func(context.Context) (interface{}, error) { - var effect model.PetFusionMaterial //一个特性应该是唯一的,但是我们要获取默认随机特性 - condition := g.Map{ - "material1": fusions[Material1[0]].ID, - "material2": fusions[Material1[1]].ID, - "material3": fusions[Material1[2]].ID, - "material4": fusions[Material1[3]].ID, - "is_enable": 1, - } - m.Where(condition).Scan(&effect) - //这时候有可能效果是空的,那么这时候就再次查询默认的特性,保证每次必会生成一个数据库有的特性 - //也许这个时候的特性配方就是随机从数据库中查找一个特性 + m := cool.DBM(s.Model) - effect2, _ := service.NewDictInfoService().DataOne("effect") - effect2s := utils.ToMap(effect2, func(t dictmodel.DictInfo) uint32 { + var effect *model.PetFusionMaterial //一个特性应该是唯一的,但是我们要获取默认随机特性 + condition := g.Map{ + "material1": fusions[Material1[0]].ID, + "material2": fusions[Material1[1]].ID, + "material3": fusions[Material1[2]].ID, + "material4": fusions[Material1[3]].ID, + "is_enable": 1, + } + m.Where(condition).Scan(&effect) + //这时候有可能效果是空的,那么这时候就再次查询默认的特性,保证每次必会生成一个数据库有的特性 + //也许这个时候的特性配方就是随机从数据库中查找一个特性 + + return effect, nil + }, 0) + + effect2s := utils.ToMap(service.NewDictInfoService().DataOne("effect"), func(t dictmodel.DictInfo) uint32 { return gconv.Uint32(t.ID) }) + effect := ret.Interface().(*model.PetFusionMaterial) - if effect.Trait1Idx != 0 { - r := grand.Intn(4) - switch r { - case 0: - return gconv.Uint32(effect2s[effect.Trait1Idx].Remark) - case 1: - return gconv.Uint32(effect2s[effect.Trait2Idx].Remark) - case 2: - return gconv.Uint32(effect2s[effect.Trait3Idx].Remark) - case 3: - return gconv.Uint32(effect2s[effect.Trait4Idx].Remark) - } + if err != nil { + r := grand.Intn(len(service.NewDictInfoService().DataOne("effect")) - 1) + return gconv.Uint32(service.NewDictInfoService().DataOne("effect")[r].Remark) } - - r := grand.Intn(len(effect2) - 1) - return gconv.Uint32(effect2[r].Remark) - + r := grand.Intn(4) + switch r { + case 0: + return gconv.Uint32(effect2s[effect.Trait1Idx].Remark) + case 1: + return gconv.Uint32(effect2s[effect.Trait2Idx].Remark) + case 2: + return gconv.Uint32(effect2s[effect.Trait3Idx].Remark) + case 3: + return gconv.Uint32(effect2s[effect.Trait4Idx].Remark) + } + return 0 } diff --git a/modules/blazing/service/pet_fusion_service.go b/modules/blazing/service/pet_fusion_service.go index efcebabb..84940c12 100644 --- a/modules/blazing/service/pet_fusion_service.go +++ b/modules/blazing/service/pet_fusion_service.go @@ -3,9 +3,13 @@ package service import ( "blazing/cool" "blazing/modules/blazing/model" + "context" + "fmt" + "strings" "github.com/alpacahq/alpacadecimal" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/util/grand" ) @@ -24,22 +28,21 @@ func NewPetFusionService() *PetFusionService { } } +var ( + cachePetFusionService = gcache.New() +) + +func (s *PetFusionService) ModifyBefore(ctx context.Context, method string, param g.MapStrAny) (err error) { + cachePetFusionService.Clear(context.Background()) + return nil +} + //获取主副精灵融合的id,如果不存在,那就给一个保底的id func (s *PetFusionService) Data(p1, p2, rand uint32) uint32 { - m := cool.DBM(s.Model) rand = uint32(alpacadecimal.NewFromInt(int64(rand)).Mul(alpacadecimal.NewFromFloat(0.5)).IntPart()) - var pet []model.PetFusion //一个特性应该是唯一的,但是我们要获取默认随机特性 - condition := g.Map{ - "main_pet_id": p1, - "sub_pet_id": p2, - "is_enable": 1, - // "hits between ? and ?" : g.Slice{1, 10}, - // "exp > 0" : nil, - // "category" : g.Slice{100, 200}, - } - m.Where(condition).Scan(&pet) + pet := s.getData(p1, p2) for _, v := range pet { rr := grand.Intn(100) @@ -51,19 +54,49 @@ func (s *PetFusionService) Data(p1, p2, rand uint32) uint32 { if len(pet) > 0 { return 0 } - - var pets []model.PetFusion - m = cool.DBM(s.Model) - m.Where("is_enable", 1).Where("is_default", 1).Scan(&pets) - if len(pets) == 0 { - return 0 - } + pets := s.def() res := pets[grand.Intn(len(pets)-1)] rr := grand.Intn(100) if rr < int(res.Probability+int32(rand)) { return uint32(res.ResultPetID) } - + //到这里相当于直接失败 return 0 } +func (s *PetFusionService) getData(p1, p2 uint32) []model.PetFusion { + cacheKey := strings.Join([]string{fmt.Sprintf("%d", p1), fmt.Sprintf("%d", p2)}, ":") + //println(cacheKey, "获取融合id") + ret, _ := cachePetFusionService.GetOrSetFuncLock(context.Background(), cacheKey, func(context.Context) (interface{}, error) { + m := cool.DBM(s.Model) + + var pet []model.PetFusion //一个特性应该是唯一的,但是我们要获取默认随机特性 + condition := g.Map{ + "main_pet_id": p1, + "sub_pet_id": p2, + "is_enable": 1, + // "hits between ? and ?" : g.Slice{1, 10}, + // "exp > 0" : nil, + // "category" : g.Slice{100, 200}, + } + m.Where(condition).Scan(&pet) + return pet, nil + + }, 0) + return ret.Interface().([]model.PetFusion) + +} +func (s *PetFusionService) def() []model.PetFusion { + + //println(cacheKey, "获取融合id") + ret, _ := cachePetFusionService.GetOrSetFuncLock(context.Background(), "-1", func(context.Context) (interface{}, error) { + + var pets []model.PetFusion + m := cool.DBM(s.Model) + m.Where("is_enable", 1).Where("is_default", 1).Scan(&pets) + + return pets, nil + }, 0) + return ret.Interface().([]model.PetFusion) + +} diff --git a/modules/dict/service/dict_info.go b/modules/dict/service/dict_info.go index e68300ff..ca38747d 100644 --- a/modules/dict/service/dict_info.go +++ b/modules/dict/service/dict_info.go @@ -8,6 +8,7 @@ import ( "blazing/modules/dict/model" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/util/gconv" ) @@ -53,29 +54,38 @@ func (s *DictInfoService) Data(ctx context.Context, types []string) (data interf } return } -func (s *DictInfoService) DataOne(types string) (data []model.DictInfo, err error) { +func (s *DictInfoService) DataOne(types string) (data []model.DictInfo) { var ( dictInfoModel = model.NewDictInfo() dictTypeModel = model.NewDictType() ) - // 如果typeData为空, 则返回空 - var ty *model.DictType - mType := cool.DBM(dictTypeModel) - mType.Where("key in (?)", types).Scan(&ty) + ret, _ := cacheDict.GetOrSetFunc(context.Background(), types, func(context.Context) (interface{}, error) { + // 如果typeData为空, 则返回空 + var ty *model.DictType + mType := cool.DBM(dictTypeModel) + mType.Where("key in (?)", types).Scan(&ty) - // 如果typeData为空, 则返回空 - if ty == nil { - return []model.DictInfo{}, nil - } - m := cool.DBM(dictInfoModel) - var ress []model.DictInfo - m.Where("typeId", ty.ID).Scan(&ress) + // 如果typeData为空, 则返回空 + if ty == nil { + return []model.DictInfo{}, nil + } + m := cool.DBM(dictInfoModel) + var ress []model.DictInfo + m.Where("typeId", ty.ID).Scan(&ress) + return ress, nil + }, 0) + + return ret.Interface().([]model.DictInfo) - return ress, nil } +var ( + cacheDict = gcache.New() +) + // ModifyAfter 修改后 func (s *DictInfoService) ModifyAfter(ctx context.Context, method string, param map[string]interface{}) (err error) { + cacheDict.Clear(context.Background()) if method == "Delete" { // 删除后,同时删除子节点 ids, ok := param["ids"]