All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
优化踢人超时处理和僵尸连接清理,支持BOSS动作脚本并增加测试,修复事件匹配与战斗循环中的并发问题。
97 lines
2.9 KiB
Go
97 lines
2.9 KiB
Go
package model
|
||
|
||
import (
|
||
"blazing/cool"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"github.com/dop251/goja"
|
||
)
|
||
|
||
const (
|
||
TableNameBossConfig = "config_boss" // BOSS配置表(全量包含基础/奖励/护盾/捕捉/特效/世界野怪/地图费用/战斗通用逻辑)
|
||
)
|
||
|
||
// BossConfig BOSS配置模型(覆盖所有补充的配置项:GBTL/非VIP费用/首场景/战斗通用逻辑)
|
||
type BossConfig struct {
|
||
*cool.Model // 嵌入通用Model(包含ID/创建时间/更新时间等通用字段)
|
||
PetBaseConfig
|
||
|
||
MapID int32 `gorm:"not null;index;comment:'所属地图ID'" json:"map_id" description:"地图ID"`
|
||
|
||
Ordernum int32 `gorm:"not null;default:0;comment:'排序'" json:"ordernum" description:"排序"`
|
||
ParentID int32 `gorm:"not null;default:0;column:parentId;type:int" json:"parentId"` // 父ID
|
||
Remark string `gorm:"comment:'BOSS备注'" json:"remark"`
|
||
//是否可捕捉MapPit
|
||
IsCapture int `gorm:"type:int;default:0;comment:'是否可捕捉'" json:"is_capture"`
|
||
Script string `gorm:"size:1024;default:'';comment:'BOSS脚本'" json:"script"` //boss出招逻辑做成js脚本
|
||
Rule []uint32 `gorm:"type:jsonb; ;comment:'战胜规则'" json:"rule"`
|
||
}
|
||
|
||
// TableName 指定BossConfig对应的数据库表名
|
||
func (*BossConfig) TableName() string {
|
||
return TableNameBossConfig
|
||
}
|
||
|
||
// GroupName 指定表所属的分组(保持和怪物刷新表一致)
|
||
func (*BossConfig) GroupName() string {
|
||
return "default"
|
||
}
|
||
|
||
// NewBossConfig 创建一个新的BossConfig实例(初始化通用Model字段+所有默认值)
|
||
|
||
func NewBossConfig() *BossConfig {
|
||
return &BossConfig{
|
||
Model: cool.NewModel(),
|
||
}
|
||
}
|
||
|
||
// init 程序启动时自动创建/同步boss_config表结构
|
||
func init() {
|
||
cool.CreateTable(&BossConfig{})
|
||
}
|
||
|
||
// RunHookActionScript 执行BOSS脚本中的 hookAction,并传入 fight 的 hookaction 参数。
|
||
// 返回值遵循 HookAction 语义:true 允许继续出手,false 阻止继续出手。
|
||
func (b *BossConfig) RunHookActionScript(hookAction any) (bool, error) {
|
||
if b == nil || strings.TrimSpace(b.Script) == "" {
|
||
return true, nil
|
||
}
|
||
|
||
program, err := goja.Compile("boss_hook_action.js", b.Script, false)
|
||
if err != nil {
|
||
return false, fmt.Errorf("compile boss script: %w", err)
|
||
}
|
||
|
||
vm := goja.New()
|
||
if _, err = vm.RunProgram(program); err != nil {
|
||
return false, fmt.Errorf("run boss script: %w", err)
|
||
}
|
||
|
||
var (
|
||
callable goja.Callable
|
||
ok bool
|
||
)
|
||
for _, fnName := range []string{"hookAction", "HookAction", "hookaction"} {
|
||
callable, ok = goja.AssertFunction(vm.Get(fnName))
|
||
if ok {
|
||
break
|
||
}
|
||
}
|
||
if !ok {
|
||
return false, fmt.Errorf("boss script function not found: hookAction")
|
||
}
|
||
|
||
result, err := callable(goja.Undefined(), vm.ToValue(hookAction))
|
||
if err != nil {
|
||
return false, fmt.Errorf("execute boss hookAction: %w", err)
|
||
}
|
||
|
||
// 与既有HookAction默认行为保持一致:未显式返回时视为允许继续出手。
|
||
if goja.IsUndefined(result) || goja.IsNull(result) {
|
||
return true, nil
|
||
}
|
||
|
||
return result.ToBoolean(), nil
|
||
}
|