条件系统 (Condition System)
条件系统用来做条件判断——给它一个表达式,它告诉你是 true 还是 false。支持比较运算符、逻辑组合和自动类型推断。最常见的用法是配合动作系统的 @if 前缀,不过其他模块也可以单独调用。
基本语法
条件表达式的基本形式:
<左值> <运算符> <右值>yaml
# 示例
"@if=%player_level%>=10 givemoney amount=500"
"@if=%player_world%==world sendmessage message=你在主世界"支持的运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
== | 等于 | %player_world%==world |
!= | 不等于 | %player_world%!=world_nether |
< | 小于 | %player_level%<10 |
<= | 小于等于 | %player_health%<=5 |
> | 大于 | %player_level%>20 |
>= | 大于等于 | %balance%>=1000 |
逻辑组合符
多个条件可以用逻辑组合符连接起来:
| 组合符 | 说明 | 示例 |
|---|---|---|
&& | 逻辑与(全部满足) | %player_level%>=10&&%player_world%==world |
|| | 逻辑或(任一满足) | %player_world%==world||%player_world%==world_the_end |
yaml
actions:
# 等级 >= 10 且在主世界
- "@if=%player_level%>=10&&%player_world%==world givemoney amount=500"
# 在主世界或末地
- "@if=%player_world%==world||%player_world%==world_the_end sendmessage message=<green>安全区域"注意
&& 和 || 不能混用在同一个 @if 表达式中。这是为了避免运算符优先级带来的歧义。如果需要更复杂的逻辑组合,用下面的结构化条件配置。
结构化条件配置
当内联的 @if 表达式不够用时(比如需要混合 AND 和 OR,或者条件特别多),可以在 YAML 里用结构化的方式来写。
all_of — 全部满足
所有子条件都为 true 时整体才为 true,相当于逻辑与:
yaml
conditions:
type: all_of
conditions:
- "%player_level% >= 10"
- "%player_world% == world"
- "%balance% >= 500"any_of — 任一满足
任意一个子条件为 true 就行,相当于逻辑或:
yaml
conditions:
type: any_of
conditions:
- "%player_world% == world"
- "%player_world% == world_the_end"
- "%player_world% == world_nether"at_least — 至少满足 N 个
至少有 count 个子条件为 true 时整体为 true。这在 all_of 和 any_of 之间提供了一个中间地带——比如"四个条件里满足任意两个就行":
yaml
conditions:
type: at_least
count: 2
conditions:
- "%player_level% >= 10"
- "%balance% >= 1000"
- "%player_health% >= 15"
- "%player_food_level% >= 18"exactly — 恰好满足 N 个
恰好有 count 个子条件为 true 时整体为 true。适合"互斥选择"的场景——比如玩家只能在三个世界中的一个:
yaml
conditions:
type: exactly
count: 1
conditions:
- "%player_world% == world"
- "%player_world% == world_nether"
- "%player_world% == world_the_end"嵌套组合
结构化条件可以嵌套,用来构建任意复杂的逻辑。比如下面这个例子表示"等级 >= 10,且(在主世界或末地),且(余额 >= 500 或者是 OP)":
yaml
conditions:
type: all_of
conditions:
- "%player_level% >= 10"
- type: any_of
conditions:
- "%player_world% == world"
- "%player_world% == world_the_end"
- type: at_least
count: 1
conditions:
- "%balance% >= 500"
- "%player_is_op% == true"类型推断
条件系统会自动判断比较值的类型,你不需要手动声明:
| 推断规则 | 说明 | 示例 |
|---|---|---|
| 两侧均为数值 | 按数值比较 | %player_level%>=10 → 数值比较 |
| 任一侧为非数值 | 按字符串比较 | %player_world%==world → 字符串比较 |
| 布尔值 | true / false 按字符串比较 | %player_is_op%==true → 字符串比较 |
yaml
# 数值比较 — 支持所有运算符
"@if=%player_level%>=10 ..." # 10, 11, 12... 均满足
"@if=%balance%<100 ..." # 99.9, 50, 0 均满足
# 字符串比较 — 只支持 == 和 !=
"@if=%player_world%==world ..." # 精确匹配 "world"
"@if=%player_name%!=Steve ..." # 不等于 "Steve"注意
对字符串用 <, <=, >, >= 时,系统会按字典序比较。这通常不是你想要的效果,所以字符串比较建议只用 == 和 !=。
在 @if 前缀中使用
@if 是条件系统最常见的入口:
yaml
actions:
# 简单条件
- "@if=%player_level%>=10 givemoney amount=500"
# 组合条件
- "@if=%player_level%>=20&&%player_world%==world givemoney amount=2000"
# 和其他控制前缀一起用
- "@if=%player_level%>=30 @chance=0.5 @delay=20 givemoney amount=5000"编程接口
除了在 YAML 配置里用,条件系统也可以在代码里直接调用:
java
ConditionService conditionService = EmakiServiceRegistry.get(ConditionService.class);
// 求值简单条件
Map<String, String> placeholders = Map.of(
"player_level", "15",
"player_world", "world"
);
boolean result = conditionService.evaluate("%player_level% >= 10", placeholders);
// true
// 求值结构化条件
ConditionConfig config = ConditionConfig.allOf(
SimpleCondition.of("%player_level%", ">=", "10"),
SimpleCondition.of("%player_world%", "==", "world")
);
boolean result2 = conditionService.evaluate(config, placeholders);
// true提示
条件求值本身很轻量,不涉及 I/O 或复杂计算,在高频路径中用也没问题。占位符会在求值前被替换成实际值,所以条件表达式里可以用任何已注册的占位符。