LogoArcartX Doc

属性来源 API

为实体添加、替换和移除外部属性与物品来源

sources 管理参与属性计算的外部数据。每个来源由 AttributeSourceKey 唯一标识;使用相同的键更新,会完整替换旧内容。

写入普通属性

val source = AttributeSourceKey("myplugin", "temporary-blessing")
 
val result = api.sources.replaceSource(
    player,
    source,
    listOf(
        AttributeModifier(
            id = "blessing.attack",
            attribute = AttributeKey.symphony("attack_damage"),
            operation = AttributeOperation.ADD,
            value = 12.0,
            description = "祝福提供的攻击力"
        )
    )
)

效果消失时,使用原来的来源键移除:

api.sources.removeSource(player, source)

不要为每次刷新生成随机来源键,否则旧数据无法替换,也无法在槽位清空或插件停用时准确移除。

从文字读取

replaceSourceFromLines 接收一个字符串列表,列表中的每个字符串表示一项属性修改。每行必须依次写完整属性 ID、运算方式和数值,三部分之间用一个或多个空格或制表符分隔:

<命名空间:属性> <运算方式> <数值>
部分写法说明
属性 IDsymphony:attack_damage必须写完整命名空间;这里不会把 attack_damage 自动补成 symphony:attack_damage
运算方式addmultiply_basemultiply_total不区分大小写;后两种也可以写成 multiply-basemultiply-total
数值15-3.50.220%必须是有限数字;末尾带 % 时先除以 100,因此 20% 的内部值是 0.2

三种运算的含义如下:

运算方式计算方式
add当前值加上输入值
multiply_base当前值加上“属性基础值 × 输入值”
multiply_total当前值乘以 1 + 输入值

例如,属性基础值为 100,依次提供 add 15multiply_base 10%multiply_total -5%,最终结果为 (100 + 15 + 100 × 0.10) × 0.95 = 118.75。运算阶段固定为 addmultiply_basemultiply_total,不由文字在列表中的先后顺序决定。

完整调用示例:

api.sources.replaceSourceFromLines(
    player,
    AttributeSourceKey("myplugin", "legacy-panel"),
    listOf(
        "# 固定攻击力",
        "symphony:attack_damage add 15",
        "symphony:attack_damage multiply_base 10%",
        "symphony:attack_damage multiply_total -5%",
        "symphony:arcane_resistance add 20%"
    )
)

symphony:arcane_resistance add 20% 表示加上 0.2,不是增加基础值的 20%;要按基础值增加,应使用 multiply_base 20%

解析时还需注意:

  • 每行开头和结尾的空白会被去除;空行以及去除空白后以 # 开头的整行注释会被忽略。
  • 不支持行尾注释,例如 symphony:attack_damage add 15 # 注释 会被判定为无效数字。
  • 列表最多包含 512 行,空行和注释也计入数量;每个原始字符串最多 512 个字符。
  • 属性 ID 必须符合小写命名空间格式,并且已经注册。未知属性、未知运算方式、无效数字或任意一行格式错误,都会使本次调用返回 SourceUpdateResult.Rejected,不会写入部分结果。
  • 每个有效行会生成一个 line-<原始行号> 修改器,优先级固定为 0,也不能在文字中设置有效期、持久标记或说明。

需要设置修改器 ID、优先级、有效期或说明时,应直接构造 AttributeModifier,不要使用文字格式。

从 ItemStack 写入

外部装备栏可以把 Overture 物品登记为完整来源:

val result = api.sources.replaceSourceFromItem(
    player,
    AttributeSourceKey("myplugin", "extra-slot:ring-1"),
    ringItem
)

物品中的属性、套装部件、词条、宝石、强化和技能会一起读取。套装数量会合并普通装备栏、主副手和所有外部物品来源。

外部槽位清空时,必须使用同一个来源键调用 removeSource。需要查看已经登记的外部物品时,可读取:

val currentItems = api.sources.itemSources(player)

普通原版物品和没有 Symphony 组件的 Overture 物品不会产生有效内容。传入空气物品相当于清空该来源。

套装显示更新

外部物品改变套装数量后会触发 SetCountsChangedEvent。外部背包或额外装备界面应监听该事件,更新自己持有物品的 Lore:

@EventHandler
fun onSetCountsChanged(event: SetCountsChangedEvent) {
    extraInventory.refreshSetLore(event.entity.uniqueId, event.counts)
}

普通背包中的显示由 Symphony 与 Overture 更新;不在 Bukkit 物品栏中的副本,由保存该副本的外部系统负责重建。显示规则见套装

处理写入结果

四个写入方法都返回 SourceUpdateResult

结果含义
Applied来源已经改变,结果中包含实体修订号、受影响属性和套装档位变化
Unchanged新旧内容相同,没有产生新的属性快照
Rejected输入无法解析或不符合要求,可读取 reasoncause

写入失败时不要自行修改 Symphony 的 NBT,也不要假定部分数据已经生效。

来源键的约定

namespace 应使用附属插件自己的小写名称,value 用来定位具体槽位或数据项,例如:

myplugin:extra-slot:ring-1
myplugin:extra-slot:ring-2
myplugin:temporary-blessing

来源值最长 256 个字符,不能包含换行和空字符。多个独立槽位不能共用同一个键,否则后写入的物品会覆盖前一个。

线程要求

写入与移除来源必须在 Bukkit 主线程调用。数据库或网络读取应由附属插件提前完成,再把已经准备好的结果提交给 sources

自动装备栏和副手的读取规则见属性来源,属性快照的读取方式见属性 API

On this page