═══ 自定义超平坦图案 公式编写说明 ═══

一、格式

每层规则用分号 ";" 分隔。层规则有两种格式：

【普通格式】
  y=<起始>..<结束>: <表达式>
  y=<层>: <表达式>               ← 单层可省略范围
  y=<起始>..: <表达式>           ← 开区间：到该维度顶部
  y=..<结束>: <表达式>           ← 开区间：从该维度底部起
  y=..: <表达式>                 ← 整个维度（等同覆盖全部高度）

  开区间的 ly 基准：y=<起始>..: 从 <起始> 起算；y=..<结束> / y=..: 从该维度
  最低 y 起算（与 biome 行的简写一致）。

  重叠与覆盖：同一 y 上后写的层覆盖先写的层（开区间同样如此）。例如
  {y=-64..0: A; y=..: B} 的结果是 B 覆盖整维（A 完全被盖住）；
  想要"基座 + 局部覆盖"，把基座写在前面：{y=..: B; y=-64..0: A}。

【let 代码块格式】
  y=<起始>..<结束>: {
    let 变量 = <表达式>;
    let 变量 = <表达式>;
    ...
    <最终表达式>
  }

  在 { } 内声明的局部变量可在后续 let 和最终表达式中使用。
  变量覆盖当前块的 x / z / ly 同名变量，退出块后恢复。
  也支持元组绑定 let (a, b) = 多返回函数(...);（见第四节「元组 let」）。

【共享 let（可选）】
  在公式内容里直接写（不放进层里）：

    let 变量 = <表达式>;

  该变量可被本维度的全部层与 biome 行复用；按声明顺序求值（后面的可以引用
  前面的），层内 let 可以覆盖同名共享变量。例：

    {overworld=
      let sea = 62;
      let hills = seedhash(floordiv(x, 40), floordiv(z, 40), 7);
      y=0..sea: hills < 0.4 ? minecraft:sandstone : minecraft:stone;
      biome: hills < 0.5 ? minecraft:desert : minecraft:plains
    }

  还可以定义"参数化 let"（宏）——调用处会在编译期直接展开，没有运行时开销，
  而且能用不同坐标重复求值（做坡度、邻域判断）：

    {overworld=
      let h(px, pz) = 64 + noise2(px, pz, 900, 1) * 30;
      let rise(px, pz) = h(px + 1, pz) - h(px, pz);
      y=-64..319: y <= h(x, z) ? (rise(x, z) > 6 ? minecraft:stone : minecraft:grass_block)
                             : minecraft:air
    }

  宏可以再调用宏（自引用会被展开深度上限拦下）；块内同名 let 会遮蔽宏参数；
  宏名不能与内置函数重名（如 slope/step 等；普通 let 不受此限制）；
  声明顺序不限（都是编译期展开）。

【注释】
  支持 // 行内注释（该行 // 之后的内容被忽略，直到行尾）：
    let base = 64 + fbm2(x, z, 600, 4, 1) * 20; // 缓起伏陆地
  注释在解析前剥离，可以放心写在任何一行末尾；// 之后的本行内容都会被忽略。

【循环格式】
  y=<起始>..<结束>: <厚度>*[<表达式>],<厚度>*[<表达式>],...

  在指定 y 范围内，按逗号分隔的组循环铺设：每组的厚度层使用对应表达式，
  组完一轮后从第一组重新开始，直到填满整个 y 范围。

  例：
  y=-64..64: 3*[minecraft:bedrock],2*[minecraft:dirt],1*[(x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete]

  效果：周期 6 层（3+2+1），从底到顶重复：3×基岩, 2×泥土, 1×棋盘格, 3×基岩... 直到 y=64。

默认预设：

  y=-64: minecraft:bedrock;y=-63..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete

【多维度（可选）】

  默认公式只作用于主世界。若要用公式改造下界 / 末地，用分节语法把各维度的
  规则分别包在 { } 里：

    {overworld=
      y=-64: minecraft:bedrock;
      y=-63..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete
    }
    {the_nether=
      y=0..5: minecraft:netherrack;
      y=6..120: seedhash(x, z, 1) < 0.5 ? minecraft:basalt : minecraft:blackstone
    }

  ★ 维度名：overworld（主世界）、the_nether（下界）、the_end（末地）。
    可写简写 nether / end，也可加 minecraft: 前缀。
  ★ 没写到的维度 = 按原版生成：下界/末地的生物群系、特征与结构照常生成。
  ★ 别名：{the_end=overworld} 表示末地复用主世界的公式；别名目标必须在本公式
    里显式定义（链式允许，如 {the_end=nether}{nether=...} 需 nether 节存在）。
  ★ 节与节之间允许空白或分号；节内仍用分号分隔各层。
  ★ 各维度用自己的高度：层范围超出该维度高度时自动截断（例如 y=-64..319 在
    下界只有 0..255 生效）；ly 始终是"该层声明的起点"算起的层内坐标。
  ★ 旧写法（不带 {}）完全不变：仅作用于主世界。

  【主世界按原版生成】新建世界时，如果公式里没有 overworld 节（例如只写了下界
  公式），创建出的世界主世界将使用原版地形生成；下界/末地按各自公式。已有世界
  不受影响（生成器在创建时固化）。想显式要（空/平）的主世界，就写一个 overworld 节。

  【须知】公式接管的是地形 / 表面 / 洞穴：生物群系、特征与结构（堡垒、末地城、
  矿物、植被等）仍按原版生成，会落进你的公式地形里。两点建议：
  · 末地建议自行绘制主岛区域——末影龙战、黑曜石柱等原版机制依赖主岛；
  · 不画基岩顶就没有顶（下界高度上限仍为 256）。
  · 新语法（分节/seed）在旧版本模组里会解析报错（图案停用）：用新版本创建的
    世界不建议降级打开。
  · v1.2.0 之前创建的"公式化生成"世界没有下界/末地维度（旧版一直存在的问题，
    传送门无法使用）：升级不会给已有世界补上，新建世界即可获得。

【结构与群系指令（可选）】

  在每个维度的公式内容开头，可以写方括号指令（各出现一次、顺序任意；
  例外：叠加模式的 [terrain:vanilla] 必须写在最前）：

    {the_nether=
      [structure:none]
      y=0..5: minecraft:netherrack;
      y=6..120: seedhash(x, z, 1) < 0.5 ? minecraft:basalt : minecraft:blackstone
    }
    {overworld=
      [structure:only=villages,strongholds] [biome:vanilla]
      y=-64: minecraft:bedrock;
      y=-63..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete
    }

  ★ [structure:...] 控制该维度的自然结构生成（默认 all = 全开）：
      [structure:all]              全开（默认，省略不写也是全开）
      [structure:none]             全关
      [structure:only=a,b,c]       白名单：只生成列出的结构
      [structure:except=a,b,c]     黑名单：除列出的外都生成
    名单里可写"结构组名"（villages、strongholds、mineshafts、nether_complexes、
    end_cities…）或"具体结构名"（village_plains、fortress、bastion_remnant…），
    两种写法可以混用；自定义/模组结构写 命名空间:名称（如 mymod:tower）。

  ★ 结构表（原版；标 * 的为 26.3 新增，旧版本写上去也不会生成、不会报错）：
    【主世界】villages 村庄 · strongholds 要塞 · ruined_portals 废弃传送门 ·
      mineshafts 废弃矿井 · desert_pyramids 沙漠神殿 · jungle_temples 丛林神庙 ·
      igloos 冰屋 · swamp_huts 沼泽小屋 · shipwrecks 沉船 · buried_treasures 埋藏的宝藏 ·
      ocean_ruins 海底废墟 · ocean_monuments 海底神殿 · pillager_outposts 掠夺者前哨站 ·
      woodland_mansions 林地府邸 · ancient_cities 远古城市 · trail_ruins 古迹废墟 ·
      trial_chambers 试炼密室 · abandoned_camp 废弃营地*
    【下界】nether_complexes 下界要塞+堡垒遗迹 · nether_fossils 下界化石 ·
      ruined_portals 废弃传送门（下界变体）
    【末地】end_cities 末地城

  ★ [biome:...] 控制该维度的生物群系（默认保持现状：主世界平原、下界/末地原版）：
      [biome:vanilla]          该维度使用原版群系分布（按坐标生成，与公式地形无关）
      [biome:minecraft:desert] 整个维度固定为指定群系
    使用 [biome:...] 后：群系专属结构（沙漠神殿、丛林神庙、冰屋…）会按群系自然生成，
    刷怪、天气、水色随群系变化；装饰特性（树/花草/矿物等）也跟随新群系照常生成
    （超平坦基座换群系后同样会生长原版植被）。只影响新生成的区块（已生成区块不变）。

  ★ biome 行——按高度精细控制群系（3D：同一 xz 不同 y 可以是不同群系）：

      {overworld=
        [biome-fallback:3d]
        biome y=-64..30: minecraft:deep_dark;
        biome y=31..60: minecraft:lush_caves;
        biome: minecraft:desert
      }

      biome: <表达式>                    覆盖整个维度（最简写法）
      biome y=<起始>..<结束>: <表达式>   只覆盖这段高度（y=<层> 单层亦可）

    表达式返回群系 id（写 命名空间:名称，如 minecraft:desert；支持 let / 三元 /
    全部函数，共享 let 通用）；同一高度上后写的行覆盖先写的行。群系是 4×4×4
    一格（以格子起点坐标判定）。

  ★ biome 行还能直接读原版群系分布（M3；不读公式地形、不会成环）：
      vanilla                     该格的原版群系（与 [biome:vanilla] 逐格一致）
      biome_at(t, h, c, e, d, w)  查原版群系参数表：六参为浮点气候值
                                  （temperature/humidity/continentalness/
                                  erosion/depth/weirdness，内部按原版 ×10000 量化）
    例（温度高处回落原版，否则沙漠）：
      biome: climate(temperature, x, z) > 0.3 ? vanilla : minecraft:desert
      biome: biome_at(0.3, 0.5, 0.2, 0.0, 0.1, 0.4)
    末地没有参数表（biome_at 视为未命中走回退；超平坦主世界可用——参数表由
    原版主世界预设构造，与生成器类型无关）；
    方块层里的 vanilla 仅在叠加模式下合法（见下文）——flat 模式下写方块层会报错。

   ── 叠加模式（[terrain:vanilla]；M3.5）──
   在**原版噪声地形**上做公式后处理：维度内容开头写 [terrain:vanilla] 开启
   （必须是第一条指令），其余照常写层：
      {overworld=[terrain:vanilla] [surface:vanilla+patch]
        y=surf(-30..30): …}

     ★ 语义：
     - 未被任何层覆盖的坐标保持原版（等价于隐含首层 y=..: vanilla）；
     - vanilla = 该坐标的原版方块（层顺序无关的快照）；keep = 之前各层的结果；
       结果与当前值相同则不写；同一高度后写的层覆盖先写的；
     - 默认雕刻器为 vanilla（原版含水层）；[carvers:...] 仍可显式覆盖；
     - 只适用于带原版噪声地形的维度。新建「公式化生成」世界时，主世界节写了
       [terrain:vanilla] 会自动换成原版噪声主世界（叠加模式直接生效）；
       旧超平坦世界或 server_mode 的超平坦世界仍会停用该维度公式——改用
       普通世界预设即可。叠加模式的 biome 行不能读公式地形
       （terrain/surfis/blockis 报错）。
     ★ 叠加模式下可用的量：
       vanilla                     原版方块值（方块层）：保持原样
       vis(方块)                   当前坐标的原版方块是否是指定方块
       vsolid / vfluid / vair      原版方块是否固体 / 含流体 / 空气
       sy / sw                     该列原版含水面高度 / 液体面高度（无水时与 sy 相同）
                                   （sy = 最高非空气方块，原版 WORLD_SURFACE 语义；
                                    sw = 最高流体方块，无水时回落到 sy）
       curis(方块)                 surface 行：当前（补铺进行中）方块是否是指定方块
       sdist(x, z)                 到最近结构保护盒的水平距离（域内 0；无结构时很大）
     ★ sd/sdb/wd/slope 在叠加模式的 surface 行同样可用，基于**当前活方块**
       （H1 写入后的地形 + 本条与先前 surface 行的补铺结果）；curis 只在叠加
       模式的 surface 行合法（flat 模式会报错）。
     ★ 层范围可写 y=surf(a..b): <表达式>——以该列 sy 为基准（a、b 可为负；
       仅叠加模式；循环层不支持）。
     ★ 表面档位（写在维度内容开头）：
       [surface:vanilla]           默认：只跑原版材料/表面通道
       [surface:vanilla+patch]     原版之后再用 surface 行补铺（curis 找暴露面）
       [surface:none]              不跑原版材料/表面，只由 surface 行铺
     ★ 结构保护：[overlay:protect-structures] 默认开（部件包围盒水平外扩 24、
       垂直 ±4 内不修改——垂直小外扩不会冻结地下结构上方的地表）；
       [overlay:protect-structures=off] 关闭后可用 sdist 自行淡出。
     ★ 编辑器预览是近似（没有原版地形：vanilla 按空气、sy/sw 按 0）。

  ★ biome 行可以读"公式地形"（只按公式层计算、不读已生成的方块，所以群系填充
    时就能用；循环层同样支持）：
      terrain(x, z)              该列表面方块的 y（含水面；全空列 = 世界最低 y - 1）
      surfis(x, z, <方块>)       表面方块是否指定方块 → 真 / 假
      blockis(x, z, y, <方块>)   指定高度处是否指定方块 → 真 / 假
    例（按地表材质分群系）：
      biome: surfis(x, z, minecraft:sand) ? minecraft:desert : minecraft:plains
    末位方块参数按方块校验（可写三元等方块表达式）；这三个函数只能出现在
    biome 行里，写进方块层会报错。

  ★ 反过来，方块层也可以读群系：
      biomeis(x, z, y, <群系>)   指定位置的群系是否指定群系 → 真 / 假
    例（按群系铺地表材质）：
      y=-63..64: biomeis(x, z, 64, minecraft:desert) ? minecraft:sandstone : minecraft:stone
    末位也可以是**群系表达式**（三元等），例如按高度切换判定目标：
      y=-63..64: biomeis(x, z, 64, y > 0 ? minecraft:desert : minecraft:ocean) ? ...
    [biome:vanilla]、[biome:<单一群系>] 与 biome 行产生的群系都能读（读的是
    该位置实际生效的群系）。只允许写在方块层里；不能与"读地形的 biome 行"
    同时出现（会成环），也不能与 [biome-fallback:2d] 组合（参考高度需要尚未
    填充的群系）。群系表达式里不能再用地形查询（terrain/surfis/blockis）。
    编辑器预览无法求值 biomeis（按假分支显示）。

  ★ [biome-fallback:...] 决定 biome 行没覆盖到的高度怎么办（默认 none）：
      [biome-fallback:none] 不接管：biome 行必须覆盖整个维度，否则解析报错
      [biome-fallback:3d]   按实际高度交还原版（保留原版纵向分布：地表群系带、
                            深处洞穴群系）
      [biome-fallback:2d]   取该列公式地形的表面高度，采样一次原版后覆盖整列
                            （适合"表面按原版、深层自定"的分层玩法）

    注意：biome 行与 [biome:...] 不能同时写（互斥）；带命名空间的自定义群系在
    运行时向注册表解析，不存在时该维度的群系不接管（日志会提示）。只影响新生成
    的区块。

  ★ [features:...] 控制该维度的群系装饰特性（树/花草/矿物/荧石/玄武岩斑块与石柱…；
    开或关都只留公式地形与结构，不细分具体装饰物）：
      [features:all]   装饰照常（默认，省略不写也一样）：写了 [biome:...] 时按新群系
                       生成原版装饰；没有群系规则时保持各维度原本行为（下界/末地照常，
                       超平坦基座本身就没有装饰）
      [features:none]  关闭全部群系装饰特性

  ★ [carvers:...] 公式接管地形时是否放行原版雕刻器（峡谷/旧式洞穴）：
      [carvers:none]     默认：取消雕刻器，公式完全接管地形
      [carvers:vanilla]  放行：原版雕刻器会在公式地形上打出峡谷/洞穴
      [carvers:vanilla-ew] 放行，但跳过水方块本身——水中不会被掏出洞穴/峡谷
                        （水保持完整）；水下的固体（海床及其下方）照常雕刻
                        （ew = except water）
    所有维度都支持：
    · 噪声维度（普通世界 / 超平坦的下界·末地节）按该维度原版设置雕刻；
    · 超平坦主世界也行（1.2.6 起）——用"干燥代理"跑原版雕刻器：
      洞穴只留空气、不灌地下水，y=-54 以下仍是岩浆（与原版深部岩浆一致）。

  ★ 注意：
    · [structure:...] 只影响新生成的结构；/locate 与末影之眼仍按原版理论位置计算。
    · 主世界默认群系是平原，很多结构（如沙漠神殿）需要对应群系才会生成——
      想让它们都能出现，可以配合 [biome:vanilla]。
    · 用本版本"新建"的世界默认全部结构开启；本版本之前创建的旧世界，其结构
      覆盖表固化在存档里，[structure:...] 只能减少、不能增加。
    · 指令不写就保持旧行为，旧公式不受任何影响。


二、变量

  x    世界 X 坐标（整数，可正可负）
  z    世界 Z 坐标（整数，可正可负）
  ly   层内相对 y 坐标（从 0 开始，即 ly = 当前 y - 层起始 y）
  y    绝对 y 坐标（整数；= ly + 层起始 y）——地层/洞穴公式建议直接用 y
  seed 当前世界的种子（整数；同一世界内恒定，不同世界一般不同）

       用 seed 可以让同一公式在不同世界呈现不同结果。注意：种子按 64 位保存，
       公式按双精度小数运算（约 53 位有效），仅低位不同的种子可能得到相同值；
       需要完整精度时请改用 seedhash()。

  spawnx 出生点的 X 坐标（整数，取"出生区块中心"）
  spawnz 出生点的 Z 坐标（整数）

       用于把局部构造摆在出生点附近，例如以出生点为圆心、半径 20 的圆盘：
         (x - spawnx) * (x - spawnx) + (z - spawnz) * (z - spawnz) < 400
       取"出生区块中心"：世界创建时游戏先选定出生区块并写下中心，再扫描安全
       落点作为最终重生点——最早生成的出生点周边区块读到的就是中心值，之后
       所有区块也用它，因此不会出现"接缝"。它与最终重生点通常相差不超过一个
       区块。各维度同值（下界/末地的公式也指向同一个出生点）。


三、运算符

  算术：     +  -  *  /  %
  比较：     ==  !=  <  >  <=  >=
  逻辑：     &&  ||  !
  分组：     ( )

  三元条件： 条件 ? 值A : 值B


四、内置函数

  函数调用格式： 函数名(参数1, 参数2, ...)

  ── 整数运算 ──
  floordiv(a, b)   向负无穷取整除法，等价 Math.floorDiv(a, b)
  floormod(a, b)   向负无穷取模，结果始终 >= 0，等价 Math.floorMod(a, b)

  ── 通用数学 ──
  abs(x)           绝对值
  max(a, b)        取较大值
  min(a, b)        取较小值
  floor(x)         向下取整
  ceil(x)          向上取整
  round(x)         四舍五入
  sign(x)          符号函数（正数返回 1，负数返回 -1，0 返回 0）
  sqrt(x)          平方根
  pow(a, b)        幂运算 a^b
  exp(x)           e^x
  log(x)           自然对数 ln(x)
  log10(x)         以 10 为底对数

  ── 三角函数（参数 / 返回值均为弧度）──
  sin(x)           正弦
  cos(x)           余弦
  tan(x)           正切
  asin(x)          反正弦（返回值 -π/2 ~ π/2）
  acos(x)          反余弦（返回值 0 ~ π）
  atan(x)          反正切（返回值 -π/2 ~ π/2）
  todeg(rad)       弧度转角度
   torad(deg)       角度转弧度

   ── 随机 ──
   rand()                     从所有已注册方块（排除空气）中等概率随机选取一个
   rand(b1, b2, ...)          白名单模式——从指定的方块列表中随机选取
    randexcept(b1, b2, ...)    黑名单模式——从全部方块中排除指定的方块后随机选取

    ★ rand() 基于 (x, z, y) 坐标哈希生成"伪随机"值——同一坐标永远返回同一方块，
      不会闪烁变化。每个坐标的随机结果在创建时即确定且不会改变。
    ★ 注意：rand() 不使用世界种子——同一公式在任何世界的结果都一样。
      需要"随世界种子变化"的图案请用下面的 seedhash()。

   ── 种子散列 ──
   seedhash(a, b, ...)   把世界种子与全部参数（参数可为 0 个）做散列混合，
                         返回 [0,1) 的小数。同一世界、同一参数永远返回同一值；
                         不同世界一般不同——适合做"随世界种子变化"的噪声。

    ★ 例：seedhash(x, z, 0) < 0.5 ? minecraft:stone : minecraft:dirt
      （不同种子创建的世界图案不同；同一世界内完全确定、不会闪烁。）
    ★ 参数建议传整数格坐标（如 x、z 与通道号），便于构造格子类噪声：
      先 floordiv 到格子，再插值/多通道混合即可做光滑噪声。

   ── 平滑噪声（读取世界种子；连续、平滑，做地形/洞穴/岛屿）──
   noise2(x, z, 尺度, 盐)               2D 平滑噪声，[-1,1]
   noise3(x, y, z, 尺度, 盐)            3D 平滑噪声，[-1,1]
   fbm2(x, z, 尺度, 层数, 盐)           2D 多倍频叠加（层数 1..8），[-1,1]
   fbm3(x, y, z, 尺度, 层数, 盐)        3D 多倍频叠加，[-1,1]
   worley2(x, z, 尺度, 盐)              细胞噪声的最近特征点距离，[0,1]
   worley3(x, y, z, 尺度, 盐)           3D 细胞噪声，[0,1]
   worley2f2(x, z, 尺度, 盐)            第二近特征点距离 F2，[0,1]
   worley2edge(x, z, 尺度, 盐)          F2 - F1：细胞边缘线（≈0 处是边界），[0,1]

     ★ 尺度 = 特征尺度（单位：方块）：值越大、特征越大；换"盐"就换一套图案。
     ★ 与 seedhash 的分工：逐方块随机斑点/概率用 seedhash/rand；
       连续起伏的地形、洞穴、岛屿用 noise/fbm/worley。
     ★ worley2f2 / worley2edge 做"细胞边界/裂纹"：edge 接近 0 处连起来就是
       边界线（如 < 0.06 铺裂纹方块）；f2 是"双点距离"场。目前只有 2D 版。
     ★ 算法已冻结：同一公式+种子在任何版本都生成相同的世界。

   ── 噪声变体（1.3.0；算法同样冻结）──
   fbm2(x, z, 尺度, 层数, 盐, 倍频, 增益)      2D 多倍频：倍频∈[1.01,4]、增益∈[0,1]；
                                             每层错开晶格（减少轴向网格感）
   fbma2(x, z, 尺度, 盐, 振幅0, 振幅1, ...)    自定义振幅列表（1..8 个）；按 |振幅| 之和
                                             归一，[-1,1]
   ridged2(x, z, 尺度, 层数, 盐, 锐度)         山脊多重分形（1-|噪声|），[0,1]
   billow2(x, z, 尺度, 层数, 盐, 锐度)         圆丘多重分形（|噪声|），[0,1]
   fbm2e(x, z, 尺度, 层数, 盐, 侵蚀)           梯度衰减 fbm：坡陡处细节被抑制（侵蚀感）；
                                             侵蚀=0 时与 fbm2 完全一致，[-1,1]

     ★ 锐度越大山脊/圆丘越尖（1..8）；倍频/增益用于调整层间距与强度
       （如 倍频=2.2、增益=0.55 让细节更细碎）。

   ── 样条映射（自定义曲线；点按位置升序，越界取端点值）──
   spline(v, p0, v0, p1, v1, ...)    分段线性：过所有点、直来直去
   cspline(v, p0, v0, p1, v1, ...)   Catmull-Rom：过所有点、曲线更顺滑（可轻微过冲）

     ★ 用途：把噪声（或任意数值）按自定义曲线映射成高度/厚度，比多层三元可读：
       let h = 64 + spline(noise2(x, z, 1200, 1), -1, -30, -0.2, -6, 0.2, 8, 1, 60);
     ★ 至少两组"位置 值"点对（参数个数为 ≥5 的奇数）；位置必须升序
       （位置全为数字字面量时会提前校验）。算法已冻结。

   ── 元组 let（多返回函数：一次调用返回多个分量）──
   let (u, v) = warp2(x, z, 尺度, 幅度, 盐)        2D 域扭曲：u、v 是坐标偏移量
   let (u, v, w) = warp3(x, y, z, 尺度, 幅度, 盐)  3D 域扭曲偏移量
   let (值, gx, gz) = noise2g(x, z, 尺度, 盐)      平滑噪声值 + 解析梯度（每格变化率）
   let (f1, f2, 细胞, px, pz) = worley2c(x, z, 尺度, 盐)
                                                   最近/次近距离、细胞随机值 [0,1)、
                                                   最近特征点坐标（方块）
   let (gx, gz) = grad(表达式)                     任意表达式的中心差分梯度（步长 1 格）

     ★ 写法：let (名字, 名字, ...) = 多返回函数(...);  名字个数必须等于分量个数；
       多返回函数只能写在元组 let 的右边（写在别处会报错）。
     ★ 典型用法（把坐标"揉皱"后再采样噪声）：
         let (u, v) = warp2(x, z, 220, 40, 7);
         let base = fbm2(x + u, z + v, 900, 4, 1);
     ★ 分量与元组同享"与高度无关"的判定：不依赖 ly 时每列只算一次（同普通 let）。

   ── 常用助手 ──
   clamp(v, 低, 高)             夹取到 [低, 高]
   lerp(a, b, t)                线性插值 a + (b - a) * t
   smoothstep(t)                0..1 输入的三次平滑
   map(v, a, b, c, d)           把 [a,b] 线性映射到 [c,d]（原版 Mth.map）
   waterline(x, z, 水位)        该列的水位面高度：水位 ± 缓变噪声（特征约 512 格、
                               实际幅度约 ±3 格，随世界种子变化）。用来写
                               "低地淹水 / 洞穴蓄水"（与地形高度比较即可）。
   atan2(a, b)                  两参数反正切（Math.atan2(a, b)）
   fract(v)                     小数部分（负数也返回 [0,1)）
   step(边, v)                  v < 边 为 0，否则 1
   smootherstep(t)              0..1 输入的五次平滑（比 smoothstep 更缓）
   tanh(v)                      双曲正切
   hypot(a, b)                  √(a² + b²)
   bias(v, b) / gain(v, g)      Schlick 偏置 / 增益：塑形概率与曲线；b=g=0.5 时恒等
   saturate(v)                  夹取到 [0,1]
   select(条件, 真值, 假值)      与三元表达式等价
   terrace(v, 台阶数, 锐度)      阶地：把连续值变成阶梯（台阶高 1/台阶数，
                               锐度 1..256 控制台阶边缘陡峭度）
   min(a, b, c, ...)            最小/最大也支持多参数直接折叠

   ── 循环与空间助手 ──
   sum(k, a, b, 表达式)         循环求和：k 依次取 a..b（a、b 必须是整数字面量）。
                              如 sum(k, 0, 3, k * x) = 0*x + 1*x + 2*x + 3*x
   min/max(k, a, b, 表达式)     循环形式的最小/最大（4 参且首参是变量名时按循环处理）
   shift(表达式, dx, dz)        把表达式里出现的 x、z 换成 x+dx、z+dz
                              （dx、dz 里的 x、z 在原点求值）
   slope(表达式)                √(gx²+gz²)：中心差分坡度（步长 1 格）
   curv(表达式)                 拉普拉斯：二阶差分之和（山脊/沟谷处显著）
   isodist(表达式)              |值| / |梯度|：到零等值线的距离估计
                              （河流用法：isodist(噪声 - 阈值) < 河宽 → 河床）

     ★ 循环在编译期展开（单层 ≤64 次、嵌套总数 ≤64）；循环变量会遮蔽同名变量。
     ★ 空间助手用"步长 1 格"的中心差分；参数表达式会在偏移位置重新求值
       （外层的 let 绑定按中心列的值参与差分）。
     ★ min/max 的 4 参循环形式与多参数折叠：首参是变量名、a/b 为整数字面量、
       且表达式**引用该变量**时 → 循环；否则按 4 参折叠（例：min(h, 62, 70, y)）。

   ── 网格采样缓存与平滑（3D 密度地形省算力）──
   cache2d(表达式) / cache2d(表达式, 步长)          世界对齐网格的双线性插值
                                                   （步长 1..16，默认 4）
   cache3d(表达式) / cache3d(表达式, sx, sy, sz)    三维网格三线性插值
                                                   （默认 4, 8, 4；角点用绝对 y）
   blur2(表达式, r) / blur2(表达式, r, 步长)        网格点上的 (2r+1)² 盒卷积
                                                   （r 1..4；步长默认 4）

     ★ 值 = 网格角点上的表达式求值 + 插值；网格与世界坐标对齐、跨区块无缝，
       同一角点只算一次（各线程本地缓存）。
     ★ 表达式必须自包含：只能用内建量（x/y/z/ly/seed/spawnx/spawnz），
       不得引用 let 绑定，也不能用 terrain/surfis/blockis/biomeis/rand；
       cache2d 与 blur2 不得引用 ly 与 y，cache3d 不得引用 ly（可以用 y）。
     ★ blur2 的网格点值 = 以该点为中心、半径 r（间距 = 步长）的 (2r+1)² 个格点的
       表达式平均；查询点用相邻四点双线性插值——用来把 0/1 掩膜、河网距离等
       平滑成柔和过渡（例：blur2(riverMask, 3, 8) ≈ 24 格平滑带）。
     ★ 平滑尺度 = r × 步长 格：小于该尺度的细节被抹平；再套 0.4/0.6 之类阈值
       取色时，过渡带宽度与平滑尺度同量级（r=3、步长=8 → 过渡带约 15 格；
       r=4、步长=16 → 约 60 格）。默认 r=2、步长=4 只抹平 ~8 格内的细节。
     ★ 宏会在自包含检查之前展开：在 cache/blur2/rivernet 的表达式里可以调用
       宏（展开后仍须满足自包含）。
     ★ 适合"每格都算很贵的场"降采样（如 3D 密度、大尺度噪声）。

   ── 表面通道（surface 行：实心之后按深度/水/坡度铺面）──
   surface y=<a>..<b>: <表达式>       该高度范围内应用表面规则
   surface: <表达式>                 整维简写
   surface[maxdepth=N] y=..: ...     只对 sd <= N 的方块求值（1..64，默认 8）

     ★ 时机：公式地形铺完之后、写入区块之前（在雕刻器与特征之前，与原版一致）。
     ★ 表达式返回方块或 keep（保持当前方块）；同一 y 后写覆盖先写。
     ★ 变量（只在 surface 行合法）：
         sd     本方块上方连续实心数（顶面 = 0）
         sdb    本方块下方连续实心数（洞顶/洞底判断）
         wd     无水 = -1；否则上方连续流体块数（≥1）
         slope  本列顶面与四邻列顶面的最大高差（格距 1）
       （无括号的 slope 是这里的列量；slope(表达式) 是函数——按上下文区分）
     ★ 实心 = 非空气且非流体；邻列顶面取自表面修改前的地形
       （跨区块一致、与规则顺序无关）。
     ★ surface 行也可以读群系（biomeis(x, z, y, 群系)）——读的是当前已填充的群系。
     ★ 编辑器预览与结构落点按**表面修改前**的公式地形计算（surface 只在区块生成时生效）。
     ★ 例（水下铺沙 + 陡坡露石 + 其余保留）：
         surface wd >= 1 && sd == 0 ? minecraft:sand : keep;
         surface slope > 2 && sd <= 1 ? minecraft:stone : keep

   ── 河网（rivernet：非局部河流；配合 min 使用）──
   let (距离, 半宽, 水面, 流量) = rivernet(cs, 盐)       默认高度场
   let (…) = rivernet(coarse, cs, 盐)                   自定义高度场（列表达式）
   可在盐后追加可调参数：(…, w0, wk) 半宽基数/流量斜率；(…, w0, wk, warp) 再调蜿蜒幅度。
   全形式：rivernet(cs, 盐[, w0, wk[, warp]]) / rivernet(coarse, cs, 盐[, w0, wk[, warp]])。

     ★ 抖动网格节点 + 严格下降的下游 + 深度 3 的流量累积 →
       半宽 = w0 + wk·√流量（默认 w0=3、wk=1）。
     ★ 返回：距离=到最近河中线的距离；半宽=该处河道半宽；水面=水面高度
       （节点海拔沿线插值 − 3）；流量=上游累积量。
     ★ cs ∈ 64..512（整数字面量，节点间距：越大河网越稀、支流越少）；
       盐/w0/wk/warp 为数字字面量（w0/wk/warp ≥ 0）；
       海拔 ≤ 62 的节点是终点（汇入海）。省略 coarse 时用内部高度场
       （62 ± 28 的多倍频噪声）。warp = 蜿蜒幅度（格，默认 0.12×cs；0 = 直线折线）。
     ★ 外观：河道按"排水树"绘制——每个汇水盆地一棵（在汇流处相接），
       彼此之间隔着分水岭（没有河），这是设计形态而非缺陷；疏密 ≈ cs。
       想要更长、连成网络的河流，给 coarse 加大尺度坡度（例：径向坡
       76 - sqrt(x*x+z*z)*0.015），让水从高处一路流向海。
     ★ coarse 必须自包含（只能用内建量；不引用 ly/y；不含视图/随机函数）。
     ★ 附近没有河道时：距离=1e9、水面=1e9 —— 配合 min(base, …) 即"不接管"。
     ★ 例（河道 + 河床 + 水体；coarse 用与 base 同源的高度场，水面不超过地形太多）：
        let base = 60 + fbm2(x, z, 600, 4, 1) * 20;
        let (d, w, s, o) = rivernet(60 + fbm2(x, z, 600, 4, 1) * 20, 192, 7);
        let surf = min(s, base + 2);
        let bed = min(base, surf - 4 + max(d - w, 0) * 0.7);
        y=..: y <= bed ? (d < w && y > bed - 3 ? minecraft:sand : minecraft:stone)
             : (d < w && y <= surf ? minecraft:water : minecraft:air)
     ★ 调参：w0 控制最小河宽、wk 控制汇流后变宽的速度；warp 越大河道越蜿蜒。
       两处 fbm2 必须一致（同一高度场），否则水面与地形不同源会出现水柱。

   ── 共享气候（M3；生成与编辑器预览均可用）──
   climate(字段, x, z)          原版气候值（约 [-1,1]；2D 形式在 y=63 采样）
   climate(字段, x, y, z)       任意高度（多支持 depth）
   peaks(w)                     原版峰谷折叠 -3·(|(|w| - 2/3)| - 1/3)

     ★ 字段：temperature / humidity / continentalness / erosion / weirdness / depth
       （字段名是关键字，不能写成变量；数值为原版量化值，步进 1e-4，
       按原版 4 格分辨率采样：同一 4×4×4 格内取值相同）。
     ★ 地形直接用会有 4 格台阶——建议包一层 cache2d 做双线性平滑，例如
       cache2d(climate(temperature, x, z), 4)。
     ★ 取值来自该维度的原版气候采样器（与 F3 的 NoiseRouter 行一致；
       下界/末地用各自维度设置）；同一套参数同时驱动地形、群系与河流。
     ★ 编辑器预览按创建界面的种子本地构建气候（与最终世界一致）；
       没有气候视图的环境返回 0。

   ── 原版密度函数 / 噪声 / 地表高度（M3；生成与编辑器预览均可用）──
   df(注册名, x, y, z)          按注册名调用原版/数据包密度函数
                                （如 minecraft:overworld/ridges；单点求值）
   noise(注册名, x, y, z[, xzScale[, yScale]])
                                按注册名调用原版噪声（如 minecraft:temperature）
                                xzScale 作用于 x/z，yScale 只作用于 y（省略为 1）
   vheight(x, z)                原版地表高度估计（finalDensity 自顶向下扫描 + 二分）

     ★ 注册名要带命名空间（数据包里的条目也能用）；找不到的条目返回 0，
       每个缺失 id 只记一次日志。
     ★ df/noise 单点求值没有原版缓存——逐方块直接调用非常慢，务必用
       cache2d / cache3d 包一层，例如固定高度：cache2d(df(minecraft:overworld/ridges, x, 63, z), 4)
       （cache2d 不能引用变量 y；要按高度变化请用 cache3d）。
       vheight 自带列缓存（同一列只扫描一次），逐方块调用没有问题。
     ★ vheight 描述的是**原版噪声地形**（超平坦世界按该维度噪声设置估计），
       与公式层/叠加后的地形无关；整列无实心时返回维度最低 y。
     ★ vheight 每列要做几十次 finalDensity 采样（列缓存只保证同列一次）——
       逐列大量调用会明显拖慢生成；只在需要跨列决策处使用，
       或用格点判断（如 floormod(x, 8) == 0）缩小调用面。
     ★ 数值随该维度的噪声设置与种子而定（与 F3 对应条目一致）。

   ★ 三角函数的参数单位是弧度。如需使用角度，用 torad() 转换：
     例：sin(torad(30)) = 0.5

   ★ 涉及格子类图案（/ 和 % 运算）务必使用 floordiv 和 floormod 替代 / 和 %，
     否则负坐标区域会出现异常尺寸的格子。详见第五节示例。


五、表达式示例

▸ 均匀层（所有坐标返回同一个块）：

  y=-64: minecraft:bedrock


▸ 1×1 棋盘格（相邻方块交替）：

  y=-64..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 3×3 格子（大格子交替，无中心交换）：

  y=-64..64: (floordiv(x,3)+floordiv(z,3))%2==0 ? minecraft:white_concrete : minecraft:gray_concrete

  ★ 不能用 ((x/3)+(z/3))%2——负数除法向零截断，原点附近会形成 5×5 异常格子。


▸ 3×3 格子 + 中心交换（中心块取对面格子的颜色）：

  y=-64..64: (floordiv(x,3)+floordiv(z,3))%2==0
    ? (floormod(x,3)==1 && floormod(z,3)==1 ? minecraft:gray_concrete : minecraft:white_concrete)
    : (floormod(x,3)==1 && floormod(z,3)==1 ? minecraft:white_concrete : minecraft:gray_concrete)


▸ 沿 X 方向每 4 格换色（条纹）：

  y=-64..64: floordiv(x,4)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 沿 Z 方向的单格条纹：

  y=-64..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete

  注：1×1 棋盘格用 + 即可，不涉及 / 或 % 大数，无需 floordiv。


▸ 半径 20 格以内的圆形，圆形区域放白色，以外放灰色：

  y=-64..64: (x*x+z*z)<=400 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 多色棋盘格（4 种颜色，按 x,z 奇偶）：

  y=-64..64: x%2==0 ? (z%2==0 ? minecraft:white_concrete : minecraft:red_concrete)
                   : (z%2==0 ? minecraft:blue_concrete  : minecraft:yellow_concrete)


▸ 正弦波条纹（灰度变化）：

  y=-64..64: (x+z*3)%6<3 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 绝对值的图案（菱形区域）：

  y=-64..64: (abs(x)+abs(z))<=20 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 正弦波条纹（连续灰度渐变，需搭配彩色块呈现）：

  y=-64..64: sin(torad(x*10))>0 ? minecraft:white_concrete : minecraft:gray_concrete

  每个周期约 36 格（360° / 10° = 36）。

▸ 正弦波 ：

  y=-61: abs(z - (sin(x / 5.0) * 5)) <= 1 ? minecraft:white_concrete : minecraft:light_gray_concrete

▸ 圆形波纹（同心圆）：

  y=-64..64: sin(sqrt(x*x+z*z)*0.5)>0 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 循环层：3 层基岩 + 2 层泥土 + 1 层棋盘格交替（周期 6 层）：

  y=-64..64: 3*[minecraft:bedrock],2*[minecraft:dirt],1*[(x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete]


▸ 循环层：1 层白混凝土 + 1 层灰混凝土交替（每层都换色）：

  y=-64..64: 1*[minecraft:white_concrete],1*[minecraft:gray_concrete]

  效果与 (x+z)%2 棋盘格不同——这里是水平方向统一颜色，逐层交替。
  棋盘格是同一层内方块交替。


▸ 循环层 + 普通层混用：

  y=-64: minecraft:bedrock
  y=-63..64: 2*[minecraft:dirt],1*[(x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete]

  第 -64 层为基岩，第 -63~64 层按 2 泥土 + 1 棋盘格循环。


▸ 指定池随机：棋盘格白色部分随机替换为 3 种方块之一：

  y=-64..64: (x+z)%2==0 ? rand(minecraft:white_concrete, minecraft:dirt, minecraft:bedrock) : minecraft:gray_concrete


▸ 全方块随机（整个层从全部注册方块中随机抽取）：

  y=-64..64: rand()


▸ 条件随机 + 不同随机池：

  y=-64..64: (floordiv(x,4)+floordiv(z,4))%2==0 ? rand(minecraft:stone, minecraft:cobblestone) : rand(minecraft:oak_planks, minecraft:glass)


▸ 黑名单随机：从全部方块中排除石头、泥土、草方块后随机：

  y=-64..64: randexcept(minecraft:stone, minecraft:dirt, minecraft:grass_block)


▸ 立体模型（ly 用于 y 方向，配合 air 可实现镂空）：

  y=-64..64: (x+z)%2==0 && ly<10 ? minecraft:white_concrete : minecraft:air

  只在棋盘格的白色位置生成 10 层高的立柱，其余为空气。


▸ 随世界种子变化的图案（同一公式，不同种子的世界各不相同）：

  y=-64..64: seedhash(x, z, 0) < 0.5 ? minecraft:white_concrete : minecraft:gray_concrete

  做格子类噪声时先把坐标 floordiv 到格子，例如：
  y=-64..64: seedhash(floordiv(x,3), floordiv(z,3), 0) < 0.5 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 多维度（主世界棋盘格 + 下界公式 + 末地复用主世界）：

  {overworld=y=-64: minecraft:bedrock;y=-63..64: (x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete}
  {the_nether=y=0..40: seedhash(x, z, 7) < 0.5 ? minecraft:basalt : minecraft:blackstone}
  {the_end=overworld}

  末地没有写公式内容，而是用别名复用主世界的公式（各维度仍按自己的高度范围）。


▸ let 代码块——避免重复计算，提升复杂公式可读性：

  y=-64..319: {
    let cellX = floordiv(x, 192);
    let cellZ = floordiv(z, 192);
    let cellSeed = cellX*37.1 + cellZ*91.7;
    let offX = sin(cellSeed)*40;
    let offZ = cos(cellSeed*1.3)*40;
    let dx = x - (cellX*192 + 96 + offX);
    let dz = z - (cellZ*192 + 96 + offZ);
    dx*dx + dz*dz < 400 ? minecraft:white_concrete : minecraft:air
  }

  将长公式中的重复子表达式提取为变量，逻辑清晰易维护。


▸ 元组 let——一次拿到多个返回值（域扭曲）：

  y=-64..319: {
    let (u, v) = warp2(x, z, 240, 45, 7);
    let h = 64 + fbm2(x + u, z + v, 900, 4, 1) * 26;
    y <= h ? minecraft:stone : minecraft:air
  }

  warp2 返回两个偏移量，把坐标"揉皱"后再采样噪声，地形边缘更自然；
  多返回函数只能这样接收：let (名字, 名字, ...) = 多返回函数(...)。


▸ 出生点附近的局部构造（spawnx / spawnz）：

  y=-64..319: {
    let dx = x - spawnx;
    let dz = z - spawnz;
    dx*dx + dz*dz < 400 ? minecraft:white_concrete : minecraft:air
  }

  以世界出生点为圆心生成半径 20 的圆盘。想做"出生点纪念建筑 / 塔基"这类
  以出生点为中心的构造时，不必手抄坐标，直接用 spawnx / spawnz。


六、性能与规则

  · 噪声/细胞函数是"冻结契约"：同公式 + 同种子在任何版本生成相同的世界；
  · 地层与大面积噪声尽量放进共享 let（与 ly 无关的部分自动按列缓存）；
  · 逐方块随机斑点继续用 seedhash/rand，连续起伏用 noise/fbm/worley；
  · 往地形里挖洞（写 air 的分支）时，记得在末尾保留"原方块"分支——
    整列写成 air 会把地形挖光；
  · 只作用于局部的重计算要放进三元 / && / || 的分支里（引擎是惰性、短路的），
    并用廉价的包围盒/距离判断挡在最前——不需要计算的位置就真的不会算；
  · 共享 let 是惰性的：没被用到的绑定不计算；只在某个分支里用到的绑定，
    只有走到该分支的列才会算。与 ly 无关的部分按列缓存；只经气候（4×4×4
    量化数据）依赖高度的部分按 4×4×4 格缓存；
  · 层顺序（后写覆盖先写）不影响计算量，**层的 y 范围与分支结构**才决定成本；
  · 编辑器预览按"当前种子"渲染：创建世界界面里打开编辑器时会取种子框里的
    种子（空种子 = 界面当前的随机种子，创建时用的就是它）；改过种子后重新
    打开编辑器即可同步。进入世界后预览与真实种子一致。rand() 不依赖种子。


七、块（Block）

块用标准 Minecraft 资源 ID 表示：

  minecraft:white_concrete
  minecraft:gray_concrete
  minecraft:bedrock
  minecraft:dirt
  minecraft:grass_block
  minecraft:stone
  minecraft:glass
  minecraft:cobblestone
  minecraft:oak_planks

支持的颜色混凝土（switch 常量，无需注册表）：
  white_concrete, gray_concrete, black_concrete, red_concrete,
  blue_concrete, yellow_concrete, green_concrete, orange_concrete,
  purple_concrete, light_gray_concrete, light_blue_concrete,
  magenta_concrete, lime_concrete, pink_concrete, cyan_concrete,
  brown_concrete

其他块通过 BuiltInRegistries.BLOCK 注册表查询。


八、组合示例

▸ 1 层基岩 + 10 层泥土 + 1 层草方块 + 117 层 3×3 棋盘格：

  y=-64: minecraft:bedrock;y=-63..-54: minecraft:dirt;
  y=-53: minecraft:grass_block;
  y=-52..64: (floordiv(x,3)+floordiv(z,3))%2==0 ? minecraft:white_concrete : minecraft:gray_concrete


▸ 循环层：基岩底 + 泥棋盘循环铺满 -63~64（3 泥土,1 棋盘格...4 泥土,1 棋盘格）：

  y=-64: minecraft:bedrock;y=-63..64: 3*[minecraft:dirt],1*[(x+z)%2==0 ? minecraft:white_concrete : minecraft:gray_concrete]


▸ 深板岩式地层过渡（哈希噪声 × 高度斜坡，复刻原版观感）：

  y=-64..64: seedhash(x, y, z, 11) < clamp(map(y, 0, 8, 1, 0), 0, 1)
    ? minecraft:deepslate : minecraft:stone

  原理与原版深板岩一致：逐方块哈希噪声 < 概率（y≤0 恒为 1、y≥8 恒为 0，
  中间线性下降），所以过渡带里两种方块逐块交杂、不出现生硬的分界线。
  调参：map 里的 0 与 8 是过渡带的底与顶；哈希最后一个参数（11）换掉 =
  另一套随机图案；同一套路换方块名就能做各类"风化层 / 砂浆层"地层。


九、注意事项

1. 分号 ";" 必须在英文输入法下输入，中文分号 "；" 不能识别。
2. 所有 Minecraft 块 ID 必须在英文输入法下输入。
3. 嵌套三元条件时务必用括号明确优先级。
4. 格子类图案（涉及 / 和 %）必须使用 floordiv 和 floormod 函数，
    不能直接使用 / 和 % 运算符，否则负坐标区域会出现异常。
5. 不涉及大小判断的 % 运算（如 (x+z)%2）可直接用运算符，不受影响。
6. ly 是层内相对坐标；绝对 y 用变量 y（= ly + 层起始 y）。地层/洞穴公式建议用 y。
7. 循环格式中方括号 [ ] 内可以是任意复杂表达式（含三元、函数等）。
8. 循环格式中的逗号 "," 用于分隔每组，方括号内的逗号不影响解析。
9. rand() 为伪随机——同一坐标永远返回同一方块，创建时确定，不会因进出
   世界而改变。rand() 的全池模式排除空气（minecraft:air）。
10. 建议在生成顶层为非超平坦的地形时将“生成结构”一项设为“关”。


十、专用服务器

专用服务器没有创建世界界面，无法用编辑器写入公式标记。请在
config/ohmyworld.json 中设置 server_mode: true，公式将应用于服务器上
所有超平坦世界（非超平坦世界不受影响）。server_mode 下修改公式约 5 秒
自动生效（仅影响之后新生成的区块），无需重启服务器。

  server_mode 的公式同样支持分节语法：写了哪个维度，哪个维度被接管；
  没写的维度保持原版。服务器端主世界生成器由 level-type 决定：想要
  "主世界原版 + 公式化下界/末地"，把 level-type 设为 normal（默认）并只写
  the_nether / the_end 节即可。
  ★ 运行中新增/移除维度节：需要重启服务器（单人游戏退出重进）才会对已有
    生成器生效；只改各节内的公式内容则约 5 秒自动生效。
  ★ 排查问题时，可以把 config/ohmyworld.json 的 "debug_logs" 设为 true：
    日志会输出每个维度的接管决定、公式 marker 的读写、主世界替换决定等
    诊断信息（默认 false，正常游玩无需开启）。
