跳到主要内容

表达式语法

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>
```bash

它的工作方式与 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 值的索引 |

## 常量

### 常量

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

| 常量 | 值 | 说明 |
|--------|-------------------------|---------------------------|
| `e` | 2.7182818284590452354 | 自然对数的底数 |
| `pi` | 3.14159265358979323846 | 圆的周长与直径之比 |
| `true` | 1 | 布尔操作中表示真 |
| `false`| 0 | 布尔操作中表示假 |

## 代码块语句

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

```bash
{ x=5; y=6; }
```bash

它们主要用于控制结构。

## 控制结构

### if/else

```java
if (<condition>) <true-branch>
if (<condition>) <true-branch> else <false-branch>
```bash

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

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

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

### 循环

循环最多可以循环 256 次。

#### while

```java
while (<condition>) <body>
do <body> while (<condition>);
```bash

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

#### Java/C 风格的 for

```java
for (<init>; <condition>; <increment>) <body>
```bash

* `<init>`、`<condition>` 和 `<increment>` 是单个表达式。
* `<body>` 可以是用分号分隔的单个语句或代码块语句。

**执行步骤**

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

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

#### 简单 for

```java
for (<counter> = <first>, <last>) <body>
```bash

* `<counter>` 是一个用于计数迭代的变量。
* `<first>` 和 `<last>` 是单个表达式。
* `<body>` 可以是用分号分隔的单个语句或代码块语句。

**执行步骤**

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

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

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