Skip to content

变量, 表达式与占位符上下文矩阵 ​

CoreLib 和各模块里, 表达式变量, 模板变量, PlaceholderAPI 占位符, 运行时上下文分别在哪用, 各自能读到哪些键, 汇总如下

内容按当前线上实现里的 parser, service, model 和 PlaceholderAPI expansion 整理, 覆盖 CoreLib, Attribute, Strengthen, Skills, Item, Forge, Cooking, Gem, Level, Codex 这些模块

先区分四种同形语法 ​

很多地方都写成 %key%, 但它们其实不是同一套系统:

类型用途解析时机
表达式变量用来算数值, 布尔和随机配置在 ExpressionEngine 或模块自己的解析器求值时
内部模板变量用于 Action, 名称, Lore, 消息这类文本替换在对应模块构造文本或 ActionContext 时
PlaceholderAPI 占位符给计分板, 菜单, 聊天这类外部插件读在 PlaceholderAPI 请求时
运行时上下文伤害, 玩法事件, 技能调用等过程中随身带的数据 Map由用到这个上下文的表达式, 条件或模板读取

同名的变量只在它自己的作用域里有效. 别因为某个 PAPI 占位符存在, 就以为同名的短变量也能用在模块公式里

总览 ​

插件主要表达式上下文内部模板 / Action 上下文PlaceholderAPI
CoreLib调用方的 Map, 以及随机配置自己的 variables玩家, 阶段, 循环与调用方动态键无自有扩展, 只负责最后转交 PAPI
Attribute伤害阶段, 恢复, DamageContext伤害消息emakiattribute
Strengthen货币成本; 效果值只有限引用强化展示, 成功/失败动作emakistrengthen
Skills技能参数, 自定义变量, 升级成本技能脚本文本, 升级消息emakiskills
Item物品构建, EA 属性, 修复成本物品动作, 套装显示emakiitem
Forge材料 stat/EA 属性/容量随机值最终物品展示, 结果动作emakiforge
Cooking营养 Action 数量表达式食谱奖励与营养消息emakicooking
Gem宝石 stat/EA 属性, 成本, 镶嵌率镶嵌/升级/提取结果emakigem
Level升级需求, 来源经验, 属性, 成本等级操作与升级结果emakilevel
Codex没有自己的公式环境; 使用 GameplayEvent 条件变量触发器与成就完成文本无自有扩展

CoreLib ​

通用 ExpressionEngine ​

变量由调用方的 Map 注入, 写法是 %name%. CoreLib 不会给所有公式自动塞一组全局业务变量

  • 运算符: +, -, *, /, %, ^, 括号
  • 函数: ceil, floor, round, log10, min, max, pow
  • 最大表达式长度 256 字符, 最大递归深度 10
  • 禁止反引号, $, 反斜杠
  • 缺失变量, 自引用, 非数值变量, NaN 或无限结果会让详细求值失败; 简化接口遇到这类情况会退回 0
  • 随机配置自己的 variables 会盖住外部同名变量; 动态变量按实际 Map 的迭代顺序求值, 后一项可以引用前面已经解析出来的项

实现依据: ExpressionEngine, ExpressionRules, RandomExpressionEvaluator, BooleanExpressionEvaluator

ActionContext 内部变量 ​

变量说明
%player%, %player_name%玩家名称
%player_uuid%玩家 UUID
%player_world%世界名
%player_x%, %player_y%, %player_z%玩家坐标
%phase%当前动作阶段
<show_item>独立的内联 token; 只在上下文里存在 show_item 时才替换

以上 8 个变量是 CoreLib 唯一自动注入的一组. 没有 %template_<key>%, 也没有 %loop_*% 系列变量: 传给命名序列的额外参数, 在序列体内读作 %var.<名字>%

调用模块还可以通过 ActionContext.placeholders() 注入任意小写键. attributes() 不会自动变成模板变量

实现依据: PlaceholderRenderer, ActionInlineTokenResolver

GameplayEvent 变量 ​

事件变量
方块破坏 / 放置block_type
实体击杀 / 驯服entity_type
MythicMobs 击杀mythic_id, mythic_level
合成 / 熔炉取出result_type, result_amount
钓鱼fish_state
酿造完成potion_type

这些键来自真实 Bukkit 事件, 由 Level, Codex 等模块按事件类型来用

PlaceholderAPI 边界 ​

CoreLib 不注册自己的 PlaceholderAPI expansion. 解析时先处理内部变量和内联 token, 如果装了 PlaceholderAPI 又有玩家上下文, 再转给外部去解析

Attribute ​

自定义伤害阶段 stages[].expression ​

只有 CUSTOM 阶段用表达式

变量含义 / 单位
input, base进入当前阶段时的伤害点
flat固定属性的聚合值
percent百分比点数
chance触发概率, 0..100
multiplier倍率属性的百分比点
roll当前判定随机值, 0..100
crit是否触发, 取 1 或 0
DamageContext 任意键调用方或伤害服务写进去的运行时上下文

一条重要的界限: 实现会先写入上面这些固定键, 再合并 DamageContext. 所以 DamageContext 里的同名键会盖住固定键. ATTACKER / TARGET 来源先读当时的属性值, 读不到时可以退回上下文里的同名数值; CONTEXT 来源则只读上下文

实现依据: StageCalculator, DamageContextVariables

DamageContext 标准键 ​

  • 实体: attacker, attacker_name, attacker_type, attacker_uuid, source, source_name, target, target_name, target_type, target_uuid
  • 伤害类型: damage_type, damage_type_name, damage_type_id
  • 伤害数值: source_damage, input_damage, base_damage, damage, final_damage
  • 原因: cause, cause_name, cause_id, damage_cause, damage_cause_name, damage_cause_id
  • 投射物: projectile_type, projectile_uuid
  • 控制: allow_critical, allow_target_dodge, calculate_target_defense
  • 随机: damage_roll, damage_roll_flat, damage_roll_percent, damage_roll_chance, damage_roll_multiplier, 范围 0..1
  • 闪避: dodge_chance, dodge_roll, dodged, 概率/随机值范围 0..100
  • 摔落: fall_distance, jump_boost_level, vanilla_fall_damage, fall_damage_formula

这些键在 DamageContextVariables 里会被整理成小写的 identifier

恢复公式 recovery.expression ​

变量说明
input, base, damage, final_damage最终伤害点
flat, healing_flat固定恢复点数
percent, healing_percent恢复百分比点
percent_amount, healing_percent_amount按伤害折算出来的恢复量
gross, healing_gross抗性前的总恢复量
resistance, healing_resistance恢复抗性的百分比点

恢复的固定键是在继承 DamageContext 之后写入的, 所以会盖住上下文里的同名键. 默认结果是 gross * (1 - resistance / 100), 之后套用最小/最大值, 并把结果限制为非负

实现依据: DamageRecoveryCalculator

伤害消息模板 ​

message, attacker_message, target_message 用普通的 %key% 文本替换. 除了上面那些实体, 伤害类型, 伤害数值与原因键, 还提供:

source_type, source_uuid, critical, critical_text, critical_suffix, roll, attacker_health, attacker_max_health, target_health, target_max_health, distance

健康值和距离只从 DamageContext 读; 没注入时显示 0

实现依据: DamageMessageDispatcher

PlaceholderAPI: emakiattribute ​

  • %emakiattribute_<attribute_id>%
  • %emakiattribute_power%
  • %emakiattribute_resource_<id>_current%
  • %emakiattribute_resource_<id>_max%
  • %emakiattribute_resource_<id>_default%
  • %emakiattribute_resource_<id>_bonus%
  • %emakiattribute_resource_<id>_percent%
  • %emakiattribute_resource_<id>_regen%

解析资源时会把第一个下划线之前的部分当成资源 ID, 所以资源 ID 最好不要带下划线

Strengthen ​

成功率 ​

成功率不走 ExpressionEngine 公式. 实际算法是: 目标星级的基础成功率, 加上有效锻印等级乘以每级加成, 最后限制在 0..success_chance_cap

实现依据: ChanceCalculator

货币成本 cost_formula ​

变量说明
base_cost货币的基础成本
star目标星级, 也就是当前星级 + 1

公式结果必须有限且大于 0, 然后四舍五入成整数成本; 不然这一项成本会被跳过

效果值解析边界 ​

stars.<n>.variables, effects[type=variables].variables, ea_attributes 的线上实现只支持:

  • Number;
  • 数值字符串;
  • 整个值恰好为 %name% 的引用

%star% * 2 这种算术文本不会进 CoreLib ExpressionEngine, 会退回 0. 初始固定变量只有 star, 后面的动态键能不能引用前面的项, 取决于实际 Map 的迭代顺序

实现依据: StrengthenRecipe.resolveExpressions, StrengthenApiValues.evaluateNumber/evaluateMixed

展示与动作变量 ​

展示提供动态 stat 键, 以及 star, temper, max_temper, temper_color; 属性行另有 id, sign, value

成功/失败 Action 提供:

operation_id, strengthen_operation_id, strengthen_recipe_id, strengthen_recipe, strengthen_star, strengthen_temper, strengthen_show_item, strengthen_result_slot, strengthen_max_star, strengthen_success_rate, show_item, star, temper, dropped, protected, was_star

实现依据: StrengthenSnapshotBuilder, StrengthenActionCoordinator

PlaceholderAPI: emakistrengthen ​

mainhand_star, mainhand_temper, mainhand_recipe, mainhand_eligible, mainhand_success_count, mainhand_failure_count, mainhand_max_star, mainhand_success_rate, mainhand_crack_level

Skills ​

技能变量 ​

variables.* 使用:

变量说明
level, target_level, max_level技能等级上下文
skill_id, trigger_id技能与触发器 ID
is_passive是否被动技能, 1/0
player_level原版经验等级
player_health, player_max_healthBukkit 生命点
sneaking, has_target布尔量, 1/0

技能自定义的 variables 还可以引用已经解析的参数和之前定义的自定义变量. 参数本身不会自动拿到其他参数的求值结果, TriggerInvocation.extraVariables() 目前也还没有并进这套解析环境

实现依据: SkillParameterResolver, SkillVariableResolver

升级成本与文本 ​

升级货币 cost_formula 用上面这套固定上下文, 并额外提供 base_cost; 调用时 trigger_id=upgrade. 升级成功率来自静态成功率表, 不是公式

技能脚本文本可以用 level, skill_id, trigger_id, has_target, 以及已解析的参数和自定义动态键. 升级消息提供 player, skill_id, skill (技能显示名), level, current_level, target_level, max_level, success_rate, success_rate_raw, roman_level 和成本/结果动态键

PlaceholderAPI: emakiskills ​

  • 全局: cast_mode, global_cooldown, unlocked_count, slot_count, level_total
  • 技能: level_<skill_id>, cooldown_<skill_id>
  • 槽位: slot_<index>_skill|name|trigger|empty
  • 资源: resource_<id>_current|max|percent

冷却单位是秒, 槽位用从 0 开始的索引

Item ​

物品构建变量 ​

effects[type=variables].variables 没有固定的内置变量, 从空 Map 按顺序解析. 名称, Lore, 结构化展示与原版 attribute modifier 都能读这些动态键. EmakiItem 物品定义以前提供的顶层 variables 简写已经下线, 现在只有 effects 一个入口, 见物品定义与套装

effects[type=ea_attribute].ea_attributes 用一套独立的空上下文按顺序解析, 不继承构建变量. 不要在 EA 属性表达式里引用构建变量

实现依据: EmakiItemDefinitionParser, EmakiItemFactory, EmakiItemPdcWriter

修复成本 ​

变量说明
max_damage最大耐久
damage, current_damage, missing_durability当前缺失的耐久点
missing_ratio缺失比例, 0..1
restore_amount本次恢复的耐久点
restore_ratio恢复比例, 0..1
base_cost货币的基础成本

实现依据: ItemRepairService

动作, 套装与 PlaceholderAPI ​

物品 Action: player, item_id, item_trigger, item_name

套装上下文: item_id, set_id, piece_id, set_name, active, active_count, total, total_pieces, active_thresholds

emakiitem PAPI: held_id, held_name, held_components, held_components_raw, loaded_count, 以及 held_component_has_<id>, held_component_value_<id>, held_component_json_<id>

Forge ​

材料数值上下文 ​

  • capacity_cost 与 capacity_bonus.value 可以用随机数值配置, 但没有变量上下文; 结果四舍五入成容量整数
  • effects[type=variables].variables 每种材料都从空 Map 开始, 后一项可以引用当前材料前面解析出的 stat 动态键
  • effects[type=ea_attribute].ea_attributes 用另一套独立空 Map, 不继承 stat 变量

未发现独立的锻造成功率, 品质概率或货币成本 ExpressionEngine 公式

展示与动作 ​

最终名称/Lore 提供所有最终 stat 动态键, 以及 quality, quality_name, quality_multiplier, multiplier

结果 Action 提供: forge_recipe_id, forge_recipe_name, forge_source_item_name, forge_result_item_name, forge_quality, forge_multiplier, forge_multiplier_raw, forge_error_key, forge_failure_reason, forge_show_item, show_item

实现依据: ForgeMaterial, ForgeStatContributionBuilder, ForgeResultPostProcessor, ForgeActionCoordinator

PlaceholderAPI: emakiforge ​

recipe_count, craft_count_<recipe_id>, has_crafted_<recipe_id>, total_crafts, last_crafted, guarantee_<key>

Cooking ​

表达式与内部变量 ​

食谱的生产流程里没有通用的 ExpressionEngine 公式. 营养操作 Action 的 amount 可以写表达式, 变量来自当前 ActionContext 里能转成数字的 placeholder 和 attribute 动态键; 没有额外的固定变量. 单位是营养点, 出错时退回 0

食谱奖励 Action: recipe_id, recipe_name, station_type, cooking_recipe_id, cooking_recipe_name, cooking_station_type, cooking_outcome

营养消息: 动态的 nutrition_<type>, nutrition_<type>_max, nutrition_<type>_min, 以及 nutrition_type, nutrition_value, nutrition_threshold, nutrition_combo_count, nutrition_combo_required

实现依据: NutritionOperationAction, RunRecipeRewardAction, NutritionService

PlaceholderAPI: emakicooking ​

  • 配方数: recipe_count, recipe_count_<station_type>
  • 营养: nutrition_<type>, nutrition_<type>_max|min, nutrition_combo_count_<rule_id>
  • 工位: station_[<type>_]type|type_name|world|x|y|z|location|block|heat_block|burning|burning_seconds|heat|moisture|steam|input|input_source|input_amount|ingredient_count|recipe|recipe_id|progress|progress_target|progress_percent|completed|fluid|fluid_amount|player

fluid_amount 单位是 ml, burning_seconds 单位是秒

Gem ​

宝石数值与成本 ​

入口变量
宝石 variables / ea_attributeslevel, 以及前面已经解析的同类动态键
共鸣 EA 属性没有固定的初始键, 只有前面解析出的共鸣属性键
inlay_success.rate_formuladefault_chance, level_chance, configured_chance, level
镶嵌/提取/升级 cost_formulalevel, current_level, target_level, base_cost

镶嵌率单位是百分比点, 结果限制在 0..100. 升级成功率来自静态的等级成功率表, 不是公式. 成本在 amount >= 0 固定时优先用固定值, 否则把公式结果钳制为非负

实现依据: GemDefinition, GemResonanceLoader, GemInlayService, GemExtractService, GemUpgradeService

操作变量与 PlaceholderAPI ​

升级, 镶嵌, 提取链按场景提供 player, gem_id, gem (宝石显示名), level, current_level, target_level, success_rate, slot 等; 宝石展示上下文另有 display_name, old_display_name, gem_type 与各等级 stat 动态键. 货币消息提供 provider, currency, currency_id, name, display_name, required, available; 材料消息提供 item, material, display_name, required, available

emakigem PAPI: mainhand_opened_slots, mainhand_total_slots, mainhand_filled_slots, mainhand_item_definition_id, mainhand_resonance_count, 以及 mainhand_slot_<index>_gem|level|opened|type

Level ​

升级需求与成本 ​

入口变量
升级经验需求 formulacurrent_level, target_level, max_level, exp, total_exp
等级属性 attributes.<id>level, exp, total_exp
升级货币/材料成本target_level, type, base_cost, base_amount

固定的 values.<target_level> 优先于需求公式. 需求和货币结果都钳制为非负, 材料数量四舍五入成非负整数

来源经验 ​

exp_formula 只拿到当前 GameplayEvent 实际携带的键, 不会自动补上统一的玩家/等级变量:

  • 实体: entity_type
  • MythicMobs: mythic_id, mythic_level
  • 方块: block_type
  • 合成/熔炉: result_type, result_amount
  • 钓鱼: fish_state
  • 酿造: potion_type

Mythic drop 公式另有 amount, drop_amount, metadata_amount, generations, tick, 并携带文本上下文 player, type, drop

Level operation Action 的 amount 与 Cooking 营养动作一样: 只读 ActionContext 里能转成数字的动态键, 没有额外的固定变量

实现依据: RequirementService, SourceExperienceService, LevelGameplaySubscriber, LevelAttributeBridge, PlayerLevelService, MythicLevelDropBridge, LevelOperationAction

PlaceholderAPI: emakilevel ​

  • 玩家: level_<type>, exp_<type>, total_exp_<type>, totalexp_<type>, total_<type>, required_exp_<type>, requiredexp_<type>, required_<type>, progress_<type>, progress_percent_<type>
  • 排行: top_<type>_<rank>_name|level|total_exp|totalexp|total

排行榜 parser 按下划线分段, 类型 ID 最好不要带下划线

Codex ​

Codex 不调用自己的 ExpressionEngine, 也不注册 PlaceholderAPI expansion

成就触发条件 ​

触发条件用 CoreLib 的 ConditionEvaluator, 变量来自 GameplayEvent, 并额外提供 player, world:

block_type, entity_type, mythic_id, mythic_level, result_type, result_amount, fish_state, potion_type, player, world

实际能用哪些键取决于事件类型, 不会同时全部存在

触发器与完成文本 ​

触发/action 行可以读当前事件的键. 成就完成上下文另有 advancement_id, advancement_node, advancement_title, advancement_page (四个固定键)

Codex 先做本地的 %key% 替换; 有玩家且装了 PlaceholderAPI 时, 再消费其他插件注册的外部占位符

实现依据: CodexGameplaySubscriber, CodexTriggerService, AdvancementListener

配置时的通用检查清单 ​

  1. 先确认当前位置属于公式, 内部模板, PAPI 还是运行时上下文
  2. 只使用对应作用域列出的固定键与该配置明确产生的动态键
  3. 百分比可能使用 0..1 或 0..100; 以对应模块说明为准
  4. 动态键按 Map 顺序求值的模块, 不要依赖未经验证的 YAML/Map 重排行为
  5. Attribute, Level 等动态 ID parser 对下划线支持不一致, 资源/排行 ID 优先使用不含下划线的形式
  6. 若变量来自事件, 必须为不同事件配置分别处理缺失键