feat: 增强踢人逻辑与BOSS脚本支持
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
优化踢人超时处理和僵尸连接清理,支持BOSS动作脚本并增加测试,修复事件匹配与战斗循环中的并发问题。
This commit is contained in:
@@ -2,6 +2,8 @@ package input
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/player"
|
||||
configmodel "blazing/modules/config/model"
|
||||
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
)
|
||||
@@ -22,6 +24,16 @@ func (our *Input) GetAction() {
|
||||
|
||||
return t.HookAction()
|
||||
})
|
||||
|
||||
if aiPlayer, ok := our.Player.(*player.AI_player); ok && aiPlayer.BossScript != "" {
|
||||
scriptBoss := &configmodel.BossConfig{Script: aiPlayer.BossScript}
|
||||
nextByScript, err := scriptBoss.RunHookActionScript(next)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
next = nextByScript
|
||||
}
|
||||
|
||||
if !next {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -162,7 +162,8 @@ func (f *FightC) collectPlayerActions(expectedSlots map[actionSlotKey]struct{})
|
||||
|
||||
waitr := time.Duration(f.waittime)*time.Millisecond*10 + 30*time.Second
|
||||
|
||||
timeout := time.After(waitr)
|
||||
timeout := time.NewTimer(waitr)
|
||||
defer timeout.Stop()
|
||||
for len(actions) < len(expectedSlots) {
|
||||
|
||||
select {
|
||||
@@ -266,11 +267,12 @@ func (f *FightC) collectPlayerActions(expectedSlots map[actionSlotKey]struct{})
|
||||
actions[key] = paction
|
||||
//fmt.Println("玩家执行动作:", pid, paction.Priority())
|
||||
|
||||
case <-timeout:
|
||||
case <-timeout.C:
|
||||
r := f.handleTimeout(expectedSlots, actions)
|
||||
if r {
|
||||
return flattenActionMap(actions)
|
||||
}
|
||||
timeout.Reset(waitr)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -287,7 +289,7 @@ func (f *FightC) handleTimeout(expectedSlots map[actionSlotKey]struct{}, actions
|
||||
}
|
||||
player := f.getPlayerByID(key.PlayerID)
|
||||
if player != nil {
|
||||
go f.UseSkillAt(player, 0, key.ActorIndex, 0)
|
||||
f.UseSkillAt(player, 0, key.ActorIndex, 0)
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -2,7 +2,8 @@ package player
|
||||
|
||||
import (
|
||||
"blazing/common/utils"
|
||||
"blazing/modules/config/model"
|
||||
configmodel "blazing/modules/config/model"
|
||||
playermodel "blazing/modules/player/model"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -10,15 +11,17 @@ import (
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func (p *Player) IsMatch(t model.Event) bool {
|
||||
_, ok := lo.Find(t.Weather, func(item int32) bool {
|
||||
return item == int32(p.GetSpace().MapBossSInfo.Wer)
|
||||
})
|
||||
if !ok {
|
||||
// 不在同一天气下
|
||||
return false
|
||||
|
||||
func (p *Player) IsMatch(t configmodel.Event) bool {
|
||||
if len(t.Weather) > 0 {
|
||||
_, ok := lo.Find(t.Weather, func(item int32) bool {
|
||||
return item == int32(p.GetSpace().MapBossSInfo.Wer)
|
||||
})
|
||||
if !ok {
|
||||
// 不在同一天气下
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if t.StartTime != "" && t.EndTime != "" {
|
||||
ok, _ := utils.IsCurrentTimeInRange(t.StartTime, t.EndTime)
|
||||
if !ok {
|
||||
@@ -26,8 +29,74 @@ func (p *Player) IsMatch(t model.Event) bool {
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
if len(t.Week) > 0 {
|
||||
week := int32(time.Now().Weekday())
|
||||
if week == 0 {
|
||||
week = 7
|
||||
}
|
||||
|
||||
_, ok := lo.Find(t.Week, func(item int32) bool {
|
||||
return item == week
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.Sprites) > 0 && !matchPetIDInList(t.Sprites, p.Info.PetList, p.Info.BackupPetList) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(t.FirstSprites) > 0 {
|
||||
if len(p.Info.PetList) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
firstPetID := int32(p.Info.PetList[0].ID)
|
||||
_, ok := lo.Find(t.FirstSprites, func(item int32) bool {
|
||||
return item == firstPetID
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.MustTask) > 0 {
|
||||
for _, taskID := range t.MustTask {
|
||||
if p.Info.GetTask(int(taskID)) != playermodel.Completed {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.MustItem) > 0 {
|
||||
if p.Service == nil || p.Service.Item == nil {
|
||||
return false
|
||||
}
|
||||
for _, itemID := range t.MustItem {
|
||||
if p.Service.Item.CheakItem(uint32(itemID)) <= 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func matchPetIDInList(targetIDs []int32, petLists ...[]playermodel.PetInfo) bool {
|
||||
for _, pets := range petLists {
|
||||
for _, pet := range pets {
|
||||
petID := int32(pet.ID)
|
||||
_, ok := lo.Find(targetIDs, func(item int32) bool {
|
||||
return item == petID
|
||||
})
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 应该根据怪物信息决定后端生成
|
||||
|
||||
@@ -4,5 +4,5 @@ type AI_player struct {
|
||||
baseplayer
|
||||
|
||||
CanCapture int
|
||||
|
||||
BossScript string
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"context"
|
||||
|
||||
@@ -102,6 +103,10 @@ func putPacketData(buf []byte) {
|
||||
}
|
||||
|
||||
func (h *ClientData) PushEvent(v []byte, submit func(task func()) error) {
|
||||
if h == nil || h.IsClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
var header common.TomeeHeader
|
||||
header.Len = binary.BigEndian.Uint32(v[0:4])
|
||||
header.CMD = binary.BigEndian.Uint32(v[5:9])
|
||||
@@ -111,9 +116,18 @@ func (h *ClientData) PushEvent(v []byte, submit func(task func()) error) {
|
||||
copy(header.Data, v[17:])
|
||||
}
|
||||
|
||||
_ = submit(func() {
|
||||
h.LF.Producer().Write(header)
|
||||
err := submit(func() {
|
||||
if h.IsClosed() || h.LF == nil || !h.LF.Running() {
|
||||
putPacketData(header.Data)
|
||||
return
|
||||
}
|
||||
if err := h.LF.Producer().Write(header); err != nil {
|
||||
putPacketData(header.Data)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
putPacketData(header.Data)
|
||||
}
|
||||
}
|
||||
|
||||
// 重写
|
||||
@@ -241,6 +255,20 @@ type ClientData struct {
|
||||
Wsmsg *WsCodec
|
||||
Conn gnet.Conn
|
||||
LF *lockfree.Lockfree[common.TomeeHeader]
|
||||
closed int32
|
||||
}
|
||||
|
||||
func (p *ClientData) IsClosed() bool {
|
||||
return atomic.LoadInt32(&p.closed) == 1
|
||||
}
|
||||
|
||||
func (p *ClientData) Close() {
|
||||
if !atomic.CompareAndSwapInt32(&p.closed, 0, 1) {
|
||||
return
|
||||
}
|
||||
if p.LF != nil && p.LF.Running() {
|
||||
_ = p.LF.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ClientData) GetPlayer(userid uint32) *Player { //TODO 这里待优化,可能存在内存泄漏问题
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package player
|
||||
|
||||
import "blazing/common/data/share"
|
||||
|
||||
func KickPlayer(userid uint32) error { //踢出玩家
|
||||
//TODO 返回错误码
|
||||
//var player *entity.Player
|
||||
if player1, ok := Mainplayer.Load(userid); ok {
|
||||
player1.Player.Kick(false)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//return player
|
||||
// 已不在本服在线列表,视为离线并清理僵尸在线标记
|
||||
_ = share.ShareManager.DeleteUserOnline(userid)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -221,14 +221,15 @@ func (ret *Space) init() {
|
||||
|
||||
}
|
||||
func (p *Space) IsMatch(t model.Event) bool {
|
||||
_, ok := lo.Find(t.Weather, func(item int32) bool {
|
||||
return item == int32(p.MapBossSInfo.Wer)
|
||||
})
|
||||
if !ok {
|
||||
|
||||
return false
|
||||
|
||||
if len(t.Weather) > 0 {
|
||||
_, ok := lo.Find(t.Weather, func(item int32) bool {
|
||||
return item == int32(p.MapBossSInfo.Wer)
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if t.StartTime != "" && t.EndTime != "" {
|
||||
ok, _ := utils.IsCurrentTimeInRange(t.StartTime, t.EndTime)
|
||||
if !ok {
|
||||
@@ -236,6 +237,20 @@ func (p *Space) IsMatch(t model.Event) bool {
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.Week) > 0 {
|
||||
week := int32(time.Now().Weekday())
|
||||
if week == 0 {
|
||||
week = 7
|
||||
}
|
||||
|
||||
_, ok := lo.Find(t.Week, func(item int32) bool {
|
||||
return item == week
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user