表达式
命令官模组凭借动态实体数据,实现了运算表达式的功能。
算术使用 EvalEx 来实现运算功能。掌握它并非必要,但多有好处。这里的区别是,所有函数、变量、常量都对大小写有严格的准确度要求,并且所有函数名都是驼峰式大小写(除第一个词语,其它首字母大写,不加标点),而不是蛇式(全大写,且用_划分)。
额外功能与运算符
本模组在 EvalEx 的基础上,添加了一些额外功能。
这里的“匿名函数”指带有 it
形式参数的一般表达式。比如:arrayFind(arrayOf(0, 1, 2), it == 1)
。匿名函数的形式参数都有 λ
作为标记。
可变实际参数(VarArgs)都有 ...
标记(你可以无限指定实际参数)
计算相关
函数 | 描述 | 实参 | 示例 |
---|---|---|---|
random | 在指定范围内生成随机数。 | min , max | random(0, 23) |
clamp | 将其他两个实际参数约束在范围内。 | value , min , max | clamp(12, 14, 16) |
lerp | 平滑地将初值过渡到末值。 | delta , start , end | lerp(0.5, 10, 16) |
数组
所有的函数都会构建新的数组,不对原本的造成影响。
函数 | 描述 | 实参 | 示例 |
---|---|---|---|
arrayOf | 指定对象构建数组。 | args... | arrayOf(0, 23) |
arrayMap | 对数组中的所有对象应用更改。 | array , function(λ) | arrayMap(arrayOf(0,1,2), sqrt(it)) |
arrayFind | 过滤掉所有不符合条件的对象。 | array , predicate(λ) | arrayFind(arrayOf(0,1,2), it == 1) |
arrayAnyMatch | 检查是否数组中存在符合条件的对象。 | array , predicate(λ) | arrayAnyMatch(arrayOf(0,1,2), it == 1) |
arrayNoneMatch | 检查是否数组中完全没有符合条件的对象。 | array , predicate(λ) | arrayNoneMatch(arrayOf(0,1,2), it == 1) |
arrayAllMatch | 检查是否数组中的全部对象符合条件。 | array , predicate(λ) | arrayAllMatch(arrayOf(0,1,2), it == 1) |
arrayFindFirst | 返回数组中的第一个对象,若为空数组,返回 null 。 | array | arrayFindFirst(arrayOf(0, 23)) |
注册表
函数 | 描述 | 实参 | 示例 |
---|---|---|---|
Registry | 返回一个静态内容注册表。 | identifier | Registry('entity_type') |
Item | 返回注册表中的一个物品。 | identifier | Item('diamond') |
Block | 返回注册表中的一个方块。 | identifier | Block('chest') |
DynamicRegistry | 返回一个动态内容注册表。 | identifier | DynamicRegistry('worldgen/biome') |
Biome | 返回注册表中的一个群系。 | identifier | Biome('the_void') |
DimensionType | 返回注册表中的一个维度。 | identifier | DimensionType('overworld') |
杂项
函数 | 描述 | 实参 | 示例 |
---|---|---|---|
structContainsKey | 检查是否结构中包含指定键值。 | struct , key... | structContainsKey(block_state.properties, 'candles') |
hasContext | 检查是否表达式的形式参数可用。 | key... | hasContext('tool') |
length | 返回指定对象的长度或 0。 | value | length('Hello World!') |
strFormat | 将字符串转化为指定格式。 | pattern , args... | strFormat('Hello %s World!', 23) |
ifMatches | 类似于内置的 if ,但介入匿名函数。 | value , predicate(λ) , ifTrue(λ) , ifFalse(λ) | ifMatches(arrayFind(arrayOf(0,1,2), it == 1), length(it) > 0, it[0], 0) |
chain | 用匿名函数串连多个函数,it 是最终结果。 | value , actions(λ)... | chain(23, it + 3, sqrt(it)) |
运算符
函数 | 描述 | 实参 | 示例 |
---|---|---|---|
?. | 尝试从结构中获取字段,或返回 null 。 | struct , key | struct?.field |
? | 如果 a 为 null ,返回 b 。 | a , b | struct?.y ? 5 |
读取上下文数据
因为算术的上下文为原版的战利品系统,你可以通过一种叫"提取"的特殊句法来读取源数据。
标识符.字段
标识符.方法
标识符.方法.字段.方法
注意,你的用到的字段与上下文必须存在,不然表达式是无效的。
示例:
minecraft:this_entity.getX
this_entity.getHealth
minecraft:this_entity.isInWaterOrRain
this_entity.blockPosition.getX
origin.x
origin.reverse.y
minecraft:level.getDayTime
命令官拓展:
为拓展用途,本模组为对象新增了一些特别的字段。
nbt
(物品,实体,方块实体)
可用于物品,实体和方块实体。你能够用它读取对象的 NBT 数据。尽管便捷,这个检查的性能不尽人意,频繁调用(比如每刻)可能会导致游戏卡顿。
示例:this_entity.nbt.Air
properties
(方块状态)
可用于状态,比如方块状态。
示例:block_state.properties.candles
attributes
(活体)
你可以用它获取活体的数据。这个键值是标识符,所以可以写 generic.luck
,也可以写 minecraft:generic.luck
。
示例:this_entity.attributes.'generic.luck'
storage
(存档,区块,实体,方块实体)
你可以用它获取持久型数据。这一数据可以通过 /cmd:data
来读取或修改。
P.S.
如果你不得不在表达式中进行复杂的检查,你可以考虑延迟执行它,如果可以,你还可以通过 level.getDayTime % 20 == 0
为表达式添加 1 秒的“冷却”。同理,% 40
对应 2 秒,% 10
对应 0.5 秒。
表达式使用的是 Mojang 的映射(首次载入时下载),这意味着几乎所有公共的字段和 get 类型的方法都可以在表达式里使用。如果本模组无法设置映射,你可能需要依赖于平台的名称(比如 Fabric 的中间映射)。
一些例子
这是原版矿车速度的计算公式:
if(this_entity.isInWater, 4, 8) / 20
, and furnace: if(this_entity.isInWater, 3, 4) / 20
这个表达式能够将游戏时间转化为现实时间。https://bukkit.org/threads/how-can-i-convert-minecraft-long-time-to-real-hours-and-minutes.122912/
strFormat('%02.0f:%02.0f', floor((level.getDayTime / 1000 + 8) % 24), floor(60 * (level.getDayTime % 1000) / 1000))
所以它的结果会是:00:00
,或 13:45
这样的。
使用表达式
通过使用 cmd:arithmetica
命令,你可以快速上手。记得用 "
括住表达式来满足格式要求。
其他使用情境见:
JSON 命令宏
详情见命令页面中,命令宏的相关内容。链接
战利品数字提供器
在条件中使用 commander:arithmetica
提供器:
{
"condition": "minecraft:value_check",
"value": {
"type": "commander:arithmetica",
"value": "round(random(5, 15))"
},
"range": {
"min": 12.3,
"max": 32
}
}
战利品条件
使用 commander:expression
条件:
{
"condition": "commander:expression",
"value": "level.isDay"
}
execute
命令
你可以将表达式作为 execute if
命令的条件。
/execute if cmd:expression "level.isDay" run say 现在是白天!
scoreboard players
命令
你能够以表达式为修饰,作为玩家谓词。你可以通过 score
变量获取当前分数。
当前版本还没有提供实体上下文。
/scoreboard players cmd:operate @s test_objective "(score * 1.5) + level.storage.my_score_modifier"