表达式语法

WorldEdit 表达式解析器的工作方式类似于 Java 及相关语言,但有一些微妙的区别:

  • 在大多数情况下,可以省略最终的分号。
  • 序列中的最后一个值始终会被返回,即使没有 return 语句。
  • 二元中缀运算符 ^ 是幂运算符而不是异或运算符,并且具有相应的优先级。
  • 有一个后缀阶乘运算符 (!)。
  • 有一个二元中缀近似运算符 (~=)。
  • 不支持对象

操作符

表达式解析器使用 Java 的优先级规则,但有以下例外和补充:

  • 二元幂运算符 (^) 的优先级在 2 和 3 之间
  • 后缀阶乘运算符 (!) 的优先级为 2
  • 近似运算符 (~=) 的优先级为 7

二元中缀

这些运算符位于两个操作数之间。

算术运算

运算符说明
+加法
-减法
*乘法
/除法
%取余
^幂运算

位运算

这些运算符将操作数解释为 32 位整数并对其位进行操作。

运算符说明
<<左移
>>右移

逻辑运算

这些运算符将大于零的值解释为 true,其他值解释为 false。它们返回 1 表示 true,返回 0 表示 false。

运算符说明
&&逻辑与
||逻辑或

比较运算

这些运算符比较其操作数,返回 1 表示 true,返回 0 表示 false。

运算符说明
<小于
>大于
<=小于或等于
>=大于或等于
==等于
!=不等于
~=近似

赋值运算

这些运算符需要左侧为变量。使用简单赋值运算符 (=) 将值赋给不存在的变量时会创建一个临时变量。

运算符说明
=简单赋值
+=加法赋值
-=减法赋值
*=乘法赋值
/=除法赋值
%=取余赋值
^=幂赋值

前缀

这些运算符位于其应用的表达式之前。

前缀运算符

运算符说明
-x负值
~x按位取反 (参见位运算符)
!x逻辑取反 (参见逻辑运算符)
++x前置递增
--x前置递减

后缀

这些运算符位于其应用的表达式之后。

后缀运算符

运算符说明
x!阶乘
x++后置递增
x--后置递减

三元中缀

三元运算符用于以紧凑的方式表示条件表达式:

<condition> ? <true-branch> : <false-branch>

它的工作方式与 if/else 语句完全相同,只不过分支只能是单一表达式。

函数

数学函数

表达式解析器提供以下来自 Java Math 库的函数:

函数说明
abs返回一个数的绝对值
acos返回值的反余弦值,返回的角度范围为 0.0 到 pi
asin返回值的反正弦值,返回的角度范围为 -pi/2 到 pi/2
atan2返回从直角坐标 (x, y) 转换为极坐标 (r, θ) 的角度 θ
atan返回值的反正切值,返回的角度范围为 -pi/2 到 pi/2
cbrt返回值的立方根
ceil返回大于或等于参数且最接近负无穷大的整数值
cos返回角度的三角余弦值
cosh返回值的双曲余弦值
exp返回欧拉数 e 的值的次幂
floor返回小于或等于参数且最接近正无穷大的整数值
ln返回值的自然对数 (以 e 为底)
log返回值的自然对数 (以 e 为底)
log10返回值的 10 为底的对数
max返回值中的最大值(支持 2 和 3 个参数)
min返回值中的最小值(支持 2 和 3 个参数)
rint返回最接近参数的值并等于一个数学整数
round返回最接近参数的值
sin返回角度的三角正弦值
sinh返回值的双曲正弦值
sqrt返回值的正确舍入正平方根
tan返回角度的三角正切值
tanh返回值的双曲正切值

其他函数

此外,还提供以下函数:

函数说明
rotate(x, y, angle)按给定角度(以弧度为单位)旋转给定坐标对
swap(x, y)交换两个给定变量的内容
random()返回一个小于 1.0 的随机正数
randint(max)返回一个小于 max 的随机正整数
perlin(seed, x, y, z, frequency, octaves, persisence)使用给定参数生成柏林噪声
voronoi(seed, x, y, z, frequency)使用给定参数生成沃罗诺伊噪声
ridgedmulti(seed, x, y, z, frequency, octaves)使用给定参数生成嶙峋的多重分形噪声

方块查询函数

以下函数可用于在编辑环境中查询世界中的方块。注意它们仍然使用旧版的 ID 和数据,因此对新(1.13 及以上)方块可能会有未定义的行为。

函数说明
query(x, y, z, type, data)如果给定坐标处的方块具有给定的旧 ID 和数据值,则返回 true。如果 type 或 data 是变量,则方块的 ID 和数据会分配给该变量
queryRel(dx, dy, dz, type, data)类似于 query,但使用相对于当前评估的方块坐标的偏移量
queryAbs(xp, yp, zp, type, data)类似于 query,但使用绝对世界坐标

缓冲区函数

这些函数提供对数据缓冲区(本质上是数组)的访问。提供两个缓冲区,一个是全局共享缓冲区,一个是表达式本地缓冲区。带有 g 前缀的函数访问全局缓冲区,不带 g 前缀的函数访问本地

缓冲区。

函数说明
(g)megabuf(index)返回缓冲区在给定索引处的值
(g)megabuf(index, value)设置缓冲区在给定索引处的值
(g)closest(x, y, z, index, count, stride)count次迭代和每次迭代之间stride的空间内,从给定的索引值开始,找到最接近的 x,y,z 值的索引

常量

常量

以下常量始终可用,且不能被赋值。

常量说明
e2.7182818284590452354自然对数的底数
pi3.14159265358979323846圆的周长与直径之比
true1布尔操作中表示真
false0布尔操作中表示假

代码块语句

代码块语句是用大括号括起来的一组语句:

{ x=5; y=6; }

它们主要用于控制结构。

控制结构

if/else

if (<condition>) <true-branch>
if (<condition>) <true-branch> else <false-branch>
  • <condition> 被评估以决定执行哪个分支。
  • 大于零的值解释为 true,其他值解释为 false。
  • <true-code><false-code> 可以是用分号分隔的单个语句或代码块语句。

注意: else 关键字总是与最后一个 if 关联。这允许像这样构造 elseif:

if (<condition 1>) <true-code 1> else if (<condition 2>) <true-code 2> else <false-code>

循环

循环最多可以循环 256 次。

while

while (<condition>) <body>
do <body> while (<condition>);
  • <condition> 被评估以决定是否继续循环。
  • <body> 可以是用分号分隔的单个语句或代码块语句。
  • do-while 在执行主体后检查条件。

Java/C 风格的 for

for (<init>; <condition>; <increment>) <body>
  • <init><condition><increment> 是单个表达式。
  • <body> 可以是用分号分隔的单个语句或代码块语句。

执行步骤

首先,<init> 只会评估一次,然后每次迭代按以下步骤进行:

  1. 如果 <condition> 的评估结果小于或等于零(即为 false),则循环终止。
  2. 执行 <body>
  3. 执行 <increment>

简单 for

for (<counter> = <first>, <last>) <body>
  • <counter> 是一个用于计数迭代的变量。
  • <first><last> 是单个表达式。
  • <body> 可以是用分号分隔的单个语句或代码块语句。

执行步骤

首先,内部计数器被设置为 <first>。然后,每次迭代按以下步骤进行:

  1. 如果内部计数器超过 <last>,则循环终止。
  2. <counter> 被设置为内部计数器。
  3. 执行 <body>
  4. 内部计数器增加 1.0。

<first><last> 仅评估一次。