Skip to content

JS 脚本扩展 ​

EmakiAttribute 自 4.8.2 起支持用 JavaScript 声明属性定义. 把 .js 文件放进 plugins/EmakiAttribute/scripts/ 目录, 通过 attributes.register({...}) 注册的属性与 attributes/*.yml 中的属性同权: 可被物品 ea_attribute 效果, Lore 解析, 占位符与属性快照收集消费

宿主机制, 目录加载顺序, 求值超时与全开放沙箱规则与 CoreLib 一致, 契约见 CoreLib JS 脚本扩展 的安全声明与线程模型章节

attributes 绑定 API ​

payload 字段 ​

字段与 attributes/*.yml 的 schema 对齐:

字段类型必填默认说明
idstring是—属性 ID; 缺失或空白时该条跳过并报错
display_namestring否—显示名, 作为 Lore 关键字与别名匹配的基础
value_kindstring否"FLAT"FLAT / PERCENT / CHANCE / REGEN / RESOURCE / DERIVED; 非法值该条跳过
target_typestring否"GENERIC"DAMAGE / RESOURCE / GENERIC / VANILLA; 非法值该条跳过
target_idstring否—目标 ID: DAMAGE 对应伤害类型 ID, RESOURCE 对应资源 ID, VANILLA 对应原版属性名
mmoitems_statstring否—MMOItems 统计项映射
default_valuenumber否0默认值; 非数值该条跳过
min_valuenumber否—下限; 非数值该条跳过
max_valuenumber否—上限; 非数值该条跳过
allow_negativeboolean否true是否允许负值
prioritynumber否0Lore 读取优先级, 数值越大越优先 (取整)
lore_format_idstring否—词条格式 (如 default_flat / default_percent / default_regen / default_resource)
lore_patternsstring 数组否[]自定义 Lore 正则模板 (%Key% 与 %Value% 占位); 不是数组该条跳过
descriptionstring否—描述文本
attribute_powernumber否1战力系数; 非数值该条跳过
tagsstring 数组否[]标签列表
temporary_stack_modestring否"REPLACE"临时属性叠加模式: REPLACE / STACK; 非法值该条跳过

数值字段的入参契约: 既接受数字, 也接受可解析为数字的字符串

注册与覆盖规则 ​

  • 校验通过的 payload 映射为属性定义, 经内部注册表以来源 "script" 注册
  • 同 id 重复注册 (同文件或跨文件): 后注册者覆盖, 并在加载报告中输出提示 (script.register_override)
  • 任一字段校验失败时整条注册跳过 (错误报告含文件, 字段与非法值), 同文件其余条目与其余文件不受影响
  • 注册成功的属性在属性系统内的消费方式与 YAML 属性完全一致

线程与异常隔离 ​

  • 属性注册发生在脚本载入期 (经宿主锁串行化), 注册完成后由属性系统按既有逻辑消费, 运行期没有 JS 回调, 不存在脚本热路径
  • 单文件编译/求值失败由宿主隔离 (该文件跳过, 其余继续); 单条 payload 校验失败逐条跳过 (见上文)

配置与重载 ​

config.yml 中的 scripts 节:

yaml
scripts:
  enabled: true
  timeout_ms: 5000
字段类型必填默认值取值范围说明
scripts.enabledboolean否truetrue / false关闭后不扫描不加载脚本, 已注册的脚本属性随之注销
scripts.timeout_msinteger否5000正整数单次脚本求值超时毫秒数; 非正数回退 5000

重载行为: 脚本随 EmakiAttribute 既有 reload 流程重载 -- 先按来源 "script" 清空全部脚本属性注册, 再关闭并重建 JS Context, 按文件顺序重新求值与注册. 修改后的定义立即生效, 已删除文件对应的属性不复存在. GraalJS 运行库缺失时输出一条告警并跳过脚本加载, 其余功能不受影响

错误排查 ​

控制台输出原因处置
script.engine_unavailable: "GraalJS 引擎不可用, 脚本属性加载已跳过: %reason%"GraalJS 运行库缺失或宿主创建失败按 %reason% 排查; 其余功能不受影响
script.disabled: "脚本属性支持已关闭 (scripts.enabled = false)"scripts.enabled: false需要时开启后 reload
script.loaded: "脚本属性加载完成: 成功 %loaded% 个, 跳过 %skipped% 个"每次加载/重载的汇总跳过数异常时查看随后的 file_error / register_error
script.file_error: "脚本 %file% 加载失败: %error%"单文件语法错误, 求值超时或运行时异常按 %error% 修复该文件; 其余文件不受影响
script.register_error: "属性注册被跳过: %error%"payload 校验失败 (对应下述 payload_* 消息)按 %error% 修正字段
script.register_override: "脚本属性 %id% 覆盖了已注册的同名属性"同 id 重复注册确认覆盖是否符合预期; 不想覆盖请改 id
script.payload_missing_id: "%file% 缺少必填的 id 字段"注册对象缺 id补充 id
script.payload_invalid_enum: "%file% 的字段 %field% 枚举值无效: %value%"value_kind / target_type / temporary_stack_mode 拼写错误改为合法枚举值 (见 payload 表)
script.payload_invalid_number: "%file% 的字段 %field% 不是有效数字: %value%"数值字段写了非法文本修正为数字或数字字符串
script.payload_invalid_list: "%file% 的字段 %field% 必须为字符串列表"lore_patterns / tags 不是数组改为数组

安全声明 ​

脚本环境默认全开放 (可访问任意 Java 类与服务器 API), 具备与服务器同级权限, 请只加载你自己审查过的脚本; 重载会重建 Context 并清空脚本顶层状态. 完整声明见 CoreLib JS 脚本扩展

示例脚本 ​

以下示例随插件首次释放到 scripts/attributes/example_attribute.js, 可直接修改或删除

js
// EmakiAttribute 脚本属性示例 (attributes 绑定)
// attributes.register ({...}) 以字段声明一个属性定义, 注册后与 attributes/*.yml 中的属性同权:
// 可被物品 ea_attribute 效果, Lore 解析, 占位符与属性快照收集消费
//
// 字段说明 (与 attributes/*.yml schema 对齐):
//   id                   必填, 属性 ID (同 ID 重复注册时后注册者覆盖并在报告中提示)
//   display_name         显示名, 作为 Lore 关键字与别名匹配的基础
//   value_kind           数值类型: FLAT / PERCENT / CHANCE / REGEN / RESOURCE / DERIVED
//   target_type          目标类型: DAMAGE / RESOURCE / GENERIC / VANILLA
//   target_id            目标 ID (资源或原版属性标识, 可选)
//   mmoitems_stat        MMOItems 统计项映射 (可选)
//   default_value        默认值; min_value / max_value 为可选上下限
//   allow_negative       是否允许负值, 默认 true
//   priority             Lore 读取优先级, 数值越大越优先, 默认 0
//   lore_format_id       词条格式 (default_flat / default_percent / default_regen / default_resource)
//   lore_patterns        自定义 Lore 正则模板 (可选, %Key% 与 %Value% 占位)
//   description          描述文本 (可选)
//   attribute_power      战力系数, 默认 1
//   tags                 标签列表 (可选)
//   temporary_stack_mode 临时属性叠加模式: REPLACE / STACK
//
// 本文件随插件首次释放; 已存在的 scripts/ 目录不会被升级覆盖, 可自由修改或删除
attributes.register({
    id: "script_example_mana_cost",
    display_name: "施法消耗减免",
    value_kind: "FLAT",
    target_type: "GENERIC",
    target_id: "mana_cost",
    default_value: 0.0,
    min_value: 0.0,
    max_value: 100.0,
    allow_negative: false,
    priority: 10,
    lore_format_id: "default_flat",
    lore_patterns: ["%Key%.*?: ?%Value%$"],
    description: "脚本示例属性:降低施法消耗。",
    tags: ["script", "example"],
    temporary_stack_mode: "REPLACE"
});

相关页面 ​