```
feat(fight): 调整技能效果命中逻辑与回合开始处理 - 修改了技能效果命中的判定顺序,确保暴击计算在效果添加之前执行 - 修复了回合开始时敌我双方状态结算的上下文错误 - 优化了效果缓存初始化逻辑,避免重复添加相同效果 - 增加了效果去重判断,防止完全相同的效果被重复添加 - 调整了战斗循环中结束逻辑的位置,确保广播和通道关闭正确执行 - 更新了部分日志提示信息,使其更符合实际业务含义 - 移除了部分无用代码和注释,提高
This commit is contained in:
@@ -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 (
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,比如免疫能力提升效果
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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:]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
// 收集玩家动作(含超时判定)
|
||||
|
||||
@@ -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--
|
||||
}
|
||||
|
||||
|
||||
@@ -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都为自身,就回合效果结束后再使用回合效果
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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类
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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("注册码已下发 ")
|
||||
}
|
||||
// 发送验证码
|
||||
|
||||
Reference in New Issue
Block a user