diff --git a/common/cool/global.go b/common/cool/global.go index c16b1292b..484282c45 100644 --- a/common/cool/global.go +++ b/common/cool/global.go @@ -8,11 +8,11 @@ import ( "github.com/antlabs/cronex" "github.com/gogf/gf/v2/os/glog" - "github.com/xiaoqidun/limit" sensitive "github.com/zmexing/go-sensitive-word" ) -var Limiter = limit.New() +// ar Limiter = ratelimit.New(100) // per second +// var Limiter = limit.New() var ctx = context.TODO() var ( diff --git a/common/go.mod b/common/go.mod index dceba9d54..07ef2f940 100644 --- a/common/go.mod +++ b/common/go.mod @@ -10,12 +10,14 @@ require github.com/antchfx/xmlquery v1.4.4 require ( github.com/antchfx/xpath v1.3.3 // indirect + github.com/benbjohnson/clock v1.3.0 // indirect github.com/butoften/array v1.0.9 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/stretchr/testify v1.11.1 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.uber.org/ratelimit v0.3.1 // indirect ) require ( diff --git a/common/go.sum b/common/go.sum index 422f108df..c6a0c4331 100644 --- a/common/go.sum +++ b/common/go.sum @@ -8,6 +8,8 @@ github.com/antchfx/xmlquery v1.4.4/go.mod h1:AEPEEPYE9GnA2mj5Ur2L5Q5/2PycJ0N9Fus github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs= github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/butoften/array v1.0.9 h1:/kPHAc+fHz72u5B23p2W1RzIoT2eOYvhsY0tKMvsHEc= github.com/butoften/array v1.0.9/go.mod h1:RgJ3XIUy/Z2rQllTkXmS4LtfqJeD3mjYJ4XoP3odTqM= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= @@ -86,6 +88,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= +go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -187,3 +191,4 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/logic/controller/controller.go b/logic/controller/controller.go index c4b234e68..91463021c 100644 --- a/logic/controller/controller.go +++ b/logic/controller/controller.go @@ -59,7 +59,7 @@ func init() { //默认初始化扫描 for _, func_cmd := range getcmd(methodValue.Type().In(0)) { if func_cmd == 0 { //说明不是注册方法 - glog.Warning(context.Background(), "方法参数必须是结构体", method.Name, "跳过注册") + glog.Warning(context.Background(), "方法参数必须包含CMD参数", method.Name, "跳过注册") continue } diff --git a/logic/service/fight/effect/effect_20.go b/logic/service/fight/effect/effect_20.go index 49122a5c1..6d5d14fa1 100644 --- a/logic/service/fight/effect/effect_20.go +++ b/logic/service/fight/effect/effect_20.go @@ -26,7 +26,7 @@ func (e *Effect20) OnSkill(input.Ctx) bool { return true } t := input.Geteffect(input.EffectType.Status, int(info.PetStatus.Tired)) - t.Duration(e.SideEffectArgs[1] + 1) + t.Duration(e.SideEffectArgs[1]) e.Input.AddEffect(t) return true } diff --git a/logic/service/fight/effect/effect_62.go b/logic/service/fight/effect/effect_62.go index e045186af..b945523ee 100644 --- a/logic/service/fight/effect/effect_62.go +++ b/logic/service/fight/effect/effect_62.go @@ -4,6 +4,7 @@ import ( "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" + "fmt" "sync" "github.com/shopspring/decimal" @@ -30,7 +31,7 @@ type Effect62_sub struct { // 这个实际上在对方回合执行的 func (e *Effect62_sub) OnSkill(ctx input.Ctx) bool { - defer e.Alive(false) + //defer e.Alive(false) if e.bindpet == e.bind.CurrentPet { //说明对方没有切换精灵 //直接扣除所有血量OnSkill @@ -50,46 +51,55 @@ func init() { } func (e *Effect62) Turn_Start(ctx input.Ctx) { - if ctx.Player != e.Input.Player { - return - } - - if e.Duration() != 1 { //说明还没到生效节点 + //如果对面还是我方放技能时候的玩家 + // if ctx.Player != e.opp.Player { + // return + // } + fmt.Println(e.Duration(), "镇魂歌剩余回合") + if e.Duration() != 0 { //说明还没到生效节点 e.Hide = true //隐藏效果 } else { - e.Hide = false - } - if !e.Hide { //说明是自身回合//如果还在隐藏,就直接返回 - - //t.Duration(e.SideEffectArgs[0]) e.opp.AddEffect(e.e) - //defer e.EffectNode.NotALive() //失效 - //应该是对方固定伤害等于自身血量 - //e.Input.Death() //本只死亡 - - //否则触发秒杀 在对面使用技能后 - //return true } + // if !e.Hide { //说明是自身回合//如果还在隐藏,就直接返回 + + // //t.Duration(e.SideEffectArgs[0]) + // e.opp.AddEffect(e.e) + // //defer e.EffectNode.NotALive() //失效 + // //应该是对方固定伤害等于自身血量 + // //e.Input.Death() //本只死亡 + + // //否则触发秒杀 在对面使用技能后 + // //return true + // } } func (e *Effect62) OnSkill(ctx input.Ctx) bool { if !e.Hit() { //e.Alive(false) return true } - - e.opp = ctx.Input - e.e = &Effect62_sub{ - EffectNode: node.EffectNode{}, - bindpet: ctx.CurrentPet, - bind: ctx.Input, - } - e.e.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID - e.e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) - //给对方添加我方施加的buff - e.e.SetArgs(e.Input, e.SideEffectArgs...) + e.l.Do(func() { + //e.Duration(1) //必须保持到下一回合,这样才会被复制 + e.opp = ctx.Input + e.e = &Effect62_sub{ + EffectNode: node.EffectNode{}, + bindpet: ctx.CurrentPet, + bind: ctx.Input, + } + e.e.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID + //e.e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) + //给对方添加我方施加的buff + e.e.SetArgs(e.Input, e.SideEffectArgs...) + }) return true } +func (e *Effect62) SetArgs(t *input.Input, a ...int) { + + e.EffectNode.SetArgs(t, a...) + e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) + +} // // 因为对方切精灵,这个效果也要无效掉 // func (this *Effect62) OnSwitchIn(input.Ctx) bool { diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index 5ecee398e..af2ebb819 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -277,8 +277,8 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski // 记录技能信息 attacker.SkillID = uint32(a.ID) //获取技能ID if attacker.AttackTime > 0 { //如果命中 - attacker.AddEffects(attacker.EffectCache...) //命中再添加效果 - attacker.CalculateCrit(defender, a) //暴击计算 + + attacker.CalculateCrit(defender, a) //暴击计算 attacker.AttackValue.IsCritical = a.Crit attacker.DamageZone.Damage = attacker.CalculatePower(defender, a) @@ -299,6 +299,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski } } + attacker.AddEffects(attacker.EffectCache...) //命中再添加效果 for _, e := range attacker.EffectCache { //这里实现应该参考本地技能是否命中,然后 e.Hit(a.AttackTime != 0) //我方效果命中 @@ -421,13 +422,13 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) { f.First.ExecCace(func(t input.Effect) bool { //回合开始前 //结算状态 - t.Turn_Start(input.Ctx{Input: f.First}) + t.Turn_Start(input.Ctx{Input: f.Second}) return true }) f.Second.ExecCace(func(t input.Effect) bool { //回合开始前 //结算状态 - t.Turn_Start(input.Ctx{Input: f.Second}) + t.Turn_Start(input.Ctx{Input: f.First}) return true }) //开始回合操作 @@ -446,7 +447,7 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) { currentskill = oldskill - //fmt.Println("开始攻击威力", oldskill.Power) + // fmt.Println("开始攻击威力", oldskill.Power) canuseskill := true // 实际上攻击方 还有系统选择放弃出手的 if !action.CanUse(currentskill) || attacker.CurrentPet.Info.Hp <= 0 { @@ -520,7 +521,7 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) { f.FightOverInfo.WinnerId = defender.UserID f.closefight = true - break + // break } } @@ -567,8 +568,7 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) { f.First.GenInfo() f.Second.GenInfo() - // ret.FAttack = *f.First.AttackValue - // ret.SAttack = *f.Second.AttackValue + ret := info.AttackValueS{ FAttack: *f.First.AttackValue, diff --git a/logic/service/fight/info/BattleSkillEntity.go b/logic/service/fight/info/BattleSkillEntity.go index 6caa53169..724c04518 100644 --- a/logic/service/fight/info/BattleSkillEntity.go +++ b/logic/service/fight/info/BattleSkillEntity.go @@ -151,6 +151,7 @@ func getSkillName(move *SkillEntity) string { // 计算是否命中 func (s *SkillEntity) AttackTimeC(level int) { s.AttackTime = 0 //先重置上一次的 + if s.MustHit != 0 { s.AttackTime = 2 } diff --git a/logic/service/fight/input/effect.go b/logic/service/fight/input/effect.go index f08197da9..cd342f792 100644 --- a/logic/service/fight/input/effect.go +++ b/logic/service/fight/input/effect.go @@ -128,11 +128,10 @@ func (c *Input) AddEffects(e ...Effect) { for _, v := range e { - + // v.Alive() c.AddEffect(v) - - } + } } func (c *Input) AddEffect(e Effect) { @@ -142,11 +141,14 @@ func (c *Input) AddEffect(e Effect) { fmt.Println("产生回合数", e.ID(), e.Duration()) // 如果已有同 ID 的效果,尝试叠加 for _, v := range c.Effects { + if v == e { + return //完全相同,跳过执行 + } //如果效果相同,id相同,参数相同,就是同一个,确认是否可以叠加,正常来说本身就可以共存 //衰弱本身参数也是相同的,区别只是传入的回合数不一样和层数不一样 - if e.ID() != 0 && v.ID() == e.ID() && - v.Alive() && + if v.ID() == e.ID() && //找到相同的效果id + v.Alive() && //如果之前的效果还存活 equalInts(v.GetArgs(), e.GetArgs()) { //如果层数可以叠加或者是无限层数 if v.MaxStack() == 0 { v.Alive(false) //不允许叠层,取消效果 @@ -196,12 +198,9 @@ func (c *Input) Exec(fn func(Effect) bool) bool { func (c *Input) ExecCace(fn func(Effect) bool) bool { result := true for _, value := range c.EffectCache { - if value.Alive() { - - if !fn(value) { //存在false,但是仍然要向下执行 - result = false //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 - } + if !fn(value) { //存在false,但是仍然要向下执行 + result = false //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 } } diff --git a/logic/service/fight/input/input.go b/logic/service/fight/input/input.go index 47c9334de..74cc47cd7 100644 --- a/logic/service/fight/input/input.go +++ b/logic/service/fight/input/input.go @@ -11,16 +11,19 @@ import ( ) type Input struct { - CanChange bool //是否可以死亡切换CanChange - CurrentPet *info.BattlePetEntity //当前精灵 - AllPet []*info.BattlePetEntity - Player common.PlayerI - EffectCache []Effect - Finished bool //是否加载完成 + CanChange bool //是否可以死亡切换CanChange + CurrentPet *info.BattlePetEntity //当前精灵 + AllPet []*info.BattlePetEntity + Player common.PlayerI + + Finished bool //是否加载完成 *info.AttackValue FightC common.FightI // info.BattleActionI - Effects []Effect //effects 实际上全局就是effect无限回合 //effects容器 技能的 + Effects []Effect //effects 实际上全局就是effect无限回合 //effects容器 技能的 + EffectCache []Effect //这里是命中前执行的容器,也就是命中前执行的所有逻辑相关,理论上一个effect被激活,就应该同时将其他的effect取消激活 + //NewEffects []Effect + DamageZone struct { Damage decimal.Decimal //伤害 BeforeADD decimal.Decimal //攻击伤害 @@ -60,15 +63,11 @@ func (input *Input) GenSataus() { t := input.GetEffect(EffectType.Status, i) - if t != nil { //状态都是叠层类的 + if t != nil && t.Alive() { //状态都是叠层类的 - input.AttackValue.Status[i] = int8(t.Duration()) + input.Status[i] = int8(t.Duration()) } - // t = f.Second.GetEffect(input.EffectType.Status, i) - // if t != nil { - // ret.SAttack.Status[i] = int8(t.Duration()) + 1 - // } } @@ -87,6 +86,8 @@ func (input *Input) GenInfo() { func (i *Input) ResetAttackValue() { i.AttackValue.SkillID = 0 i.AttackValue.IsCritical = 0 + i.AttackValue.GainHp = 0 + i.AttackValue.LostHp = 0 } @@ -135,9 +136,26 @@ func (i *Input) GetStatusBonus() float64 { return maxBonus } +func (i *Input) initeffectcache() { + i.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来 + + for _, v := range i.Effects { + + if v.Alive() { //说明存活效果而且是延续类效果,将之添加到初始化列表中 + + //这里添加的效果是已经生效的效果对effect的复制,相当于技能施的效果的前置比如改命中的效果等 + i.EffectCache = append(i.EffectCache, v) + + } + + } + +} + // 解析并 施加effect func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) { - i.EffectCache = make([]Effect, 0) //先把上一回合数据清空 + i.initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了 + //i.NewEffects = make([]Effect, 0) //这里说明是新增的效果 temparg := skill.SideEffectArgS for _, v := range skill.SideEffectS { @@ -159,8 +177,9 @@ func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) { //i.AddEffect(t) // } //这里是临时缓存buff,后面确认命中后修改HIT状态 - + // t.Alive() //先让效果保持存活 i.EffectCache = append(i.EffectCache, t) + // i.NewEffects = append(i.NewEffects, t) } temparg = temparg[args:] diff --git a/logic/service/fight/loop.go b/logic/service/fight/loop.go index dc2b77b82..d10d3a30f 100644 --- a/logic/service/fight/loop.go +++ b/logic/service/fight/loop.go @@ -15,16 +15,7 @@ import ( ) func (f *FightC) battleLoop() { - defer func() { - f.Broadcast(func(ff *input.Input) { - //todo 将血量和技能pp传回enterturn - //<-time.After(10000) - ff.Player.SendFightEndInfo(f.FightOverInfo) - }) - close(f.actionChan) - close(f.overchan) - }() f.actionChan = make(chan action.BattleActionI, 2) fmt.Println("战斗开始精灵", f.Our.Player.GetInfo().PetList[0].CatchTime) @@ -32,10 +23,6 @@ func (f *FightC) battleLoop() { oppID := f.Opp.Player.GetInfo().UserID for { - if f.closefight { - - break - } f.Round++ fmt.Printf("—— 第 %d 回合开始 ——\n", f.Round) @@ -43,9 +30,21 @@ func (f *FightC) battleLoop() { actions := f.collectPlayerActions(ourID, oppID) f.resolveRound(actions[ourID], actions[oppID]) + if f.closefight { + + break + } } fmt.Println("战斗循环结束") + f.Broadcast(func(ff *input.Input) { + //todo 将血量和技能pp传回enterturn + + ff.Player.SendFightEndInfo(f.FightOverInfo) + + }) + close(f.actionChan) + close(f.overchan) } // 收集玩家动作(含超时判定) diff --git a/logic/service/fight/node/Turn.go b/logic/service/fight/node/Turn.go index 46477f40b..3a54bd107 100644 --- a/logic/service/fight/node/Turn.go +++ b/logic/service/fight/node/Turn.go @@ -15,12 +15,18 @@ func (e *EffectNode) Turn_Start(ctx input.Ctx) { func (e *EffectNode) Turn_End(ctx input.Ctx) { if e.duration == 0 { // 保留 (负数表示永久) - if ctx.Input.FightC.IsFirst(ctx.Input.Player) { //如果对方先手 - e.duration++ - return - } + e.Alive(false) + } else { + e.trunl.Do(func() { + + if ctx.Input.FightC.IsFirst(ctx.Input.Player) { //如果对方先手 + e.duration++ + // e.Alive(true) + } + + }) e.duration-- } diff --git a/logic/service/fight/node/node.go b/logic/service/fight/node/node.go index 06eb6c5c7..71c878c6e 100644 --- a/logic/service/fight/node/node.go +++ b/logic/service/fight/node/node.go @@ -3,6 +3,7 @@ package node import ( "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" + "sync" ) // 检查,激活,延后 @@ -21,7 +22,7 @@ type EffectNode struct { Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效 alive bool // 是否失效 effect返回值是否被取消,是否被删除 hit bool - + trunl sync.Once //增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果 } diff --git a/logic/service/maps/walk.go b/logic/service/maps/walk.go index f443eb86b..fab1012bf 100644 --- a/logic/service/maps/walk.go +++ b/logic/service/maps/walk.go @@ -1,14 +1,12 @@ package maps import ( - "blazing/cool" "blazing/logic/service/common" "blazing/logic/service/player" "blazing/logic/service/space" "blazing/modules/blazing/model" - "github.com/gogf/gf/v2/util/gconv" "golang.org/x/time/rate" ) @@ -24,10 +22,12 @@ type WalkInInfo struct { Path string } -func (t *WalkInInfo) Broadcast(mapid uint32, o WalkOutInfo) { +var limiter = rate.NewLimiter(rate.Limit(10), 1) - r := cool.Limiter.Get("Broadcast"+gconv.String(mapid), rate.Limit(10), 5) - if !r.Allow() { +func (t *WalkInInfo) Broadcast(mapid uint32, o WalkOutInfo) { + // cool.Limiter.Take() + //r := cool.Limiter.Get("Broadcast"+gconv.String(mapid), rate.Limit(10), 5) + if !limiter.Allow() { return } space.GetSpace(mapid).User.IterCb(func(playerID uint32, player common.PlayerI) { diff --git a/logic/service/pet/BargeList.go b/logic/service/pet/BargeList.go index e372dbfe9..bfe01779b 100644 --- a/logic/service/pet/BargeList.go +++ b/logic/service/pet/BargeList.go @@ -1,9 +1,12 @@ package pet +import "blazing/logic/service/player" + // PetBargeListInboundInfo 对应Java的PetBargeListInboundInfo,实现InboundMessage接口 type PetBargeListInboundInfo struct { - StartPetId uint32 `description:"开始精灵id" codec:"startPetId"` // @UInt long 对应Go的uint32(无符号64位) - EndPetId uint32 `description:"结束精灵id" codec:"endPetId"` // 字段标签模拟注解功能(描述、编解码标识) + Head player.TomeeHeader `cmd:"2309" struc:"[0]pad"` + StartPetId uint32 `description:"开始精灵id" codec:"startPetId"` // @UInt long 对应Go的uint32(无符号64位) + EndPetId uint32 `description:"结束精灵id" codec:"endPetId"` // 字段标签模拟注解功能(描述、编解码标识) } // PetBargeListInfo 对应Java的PetBargeListInfo类 diff --git a/logic/service/player/cmd.go b/logic/service/player/cmd.go index 3245ae84d..0d238952c 100644 --- a/logic/service/player/cmd.go +++ b/logic/service/player/cmd.go @@ -1,6 +1,8 @@ package player -import "blazing/logic/service/fight/info" +import ( + "blazing/logic/service/fight/info" +) func (p *Player) SendAttackValue(b info.AttackValueS) { t1 := NewTomeeHeader(2505, p.Info.UserID) @@ -26,6 +28,7 @@ func (p *Player) SendNoteReadyToFightInfo(b info.NoteReadyToFightInfo) { } func (p *Player) SendFightEndInfo(b info.FightOverInfo) { p.FightC = nil + //<-time.After(10000) t1 := NewTomeeHeader(2506, p.Info.UserID) p.SendPack(t1.Pack(&b)) diff --git a/login/internal/cmd/cmd.go b/login/internal/cmd/cmd.go index 07c4b89ff..593de99fd 100644 --- a/login/internal/cmd/cmd.go +++ b/login/internal/cmd/cmd.go @@ -52,15 +52,16 @@ func beforeServeHook(r *ghttp.Request) { r.Response.CORSDefault() } +var limiter = rate.NewLimiter(rate.Limit(10), 1) + // Limiter is a middleware that implements rate limiting for all HTTP requests. // It returns HTTP 429 (Too Many Requests) when the rate limit is exceeded. func Limiter(r *ghttp.Request) { // 3. 为任意键 "some-key" 获取一个速率限制器 // - rate.Limit(2): 表示速率为 "每秒2个请求" // - 2: 表示桶的容量 (Burst),允许瞬时处理2个请求 - rateLimiter := cool.Limiter.Get(r.GetClientIp(), rate.Limit(10), 5) - if !rateLimiter.Allow() { + if !limiter.Allow() { r.Response.WriteStatusExit(429) // Return 429 Too Many Requests r.ExitAll() } diff --git a/modules/base/service/base_sys_reg.go b/modules/base/service/base_sys_reg.go index c8051df12..7cd72cfbc 100644 --- a/modules/base/service/base_sys_reg.go +++ b/modules/base/service/base_sys_reg.go @@ -18,8 +18,8 @@ import ( "github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/util/gconv" - "github.com/hashicorp/golang-lru/v2/expirable" ) func (s *BaseSysLoginService) Reg(ctx context.Context, req *v1.BaseOpenLoginReq) (result *TokenResult, err error) { @@ -56,7 +56,7 @@ func (s *BaseSysLoginService) Reg(ctx context.Context, req *v1.BaseOpenLoginReq) // 10分钟内限制请求 ip->次数 邮箱->次数 // 验证码对redis传,防止被重复操作 // var emailcache = expirable.NewLRU[string, int](0, nil, time.Millisecond*10) -var ipcache = expirable.NewLRU[string, int](0, nil, time.Millisecond*10) +var ipcache = gcache.New(1000) func (s *BaseSysLoginService) Email(ctx context.Context, req *v1.BaseOpenEmailReq) (result *TokenResult, err error) { var ( @@ -65,14 +65,16 @@ func (s *BaseSysLoginService) Email(ctx context.Context, req *v1.BaseOpenEmailRe ) ip := r.GetClientIp() - v, ok := ipcache.Get(ip) - if ok && v > 3 { + v, ok2 := ipcache.Get(context.Background(), ip) + + if ok2 != nil || v.Int() > 3 { return nil, gerror.New("操作过于频繁,请稍后再试") } - ok, _ = share.ShareManager.EmailCodeExists(req.Email) - if ok { + ipcache.Set(context.Background(), ip, v.Int()+1, 10*time.Minute) + ok1, _ := share.ShareManager.EmailCodeExists(req.Email) + if ok1 { return nil, gerror.New("注册码已下发 ") } // 发送验证码