本篇教程由作者设定未经允许禁止转载。

前言

截至写这篇文章的时间,不论是社区还是官方wiki文档,都没有更新最新的api说明,同时社区中关于1.21.1以及其他近似版本的教程聊胜于无。

在这部分版本中使用这个模组写脚本,犹如海底捞针,实在是苦不堪言😅😅😅。

所以在这里提供一个1.21.1版本的该模组实用小脚本,并告知读者在没有文档的情况下一些容易踩坑的地方。

限制区块方块

很多时候有些方块堆积起来会影响服务器性能,或者是没有意义。

能够限制这些方块显得格外重要。

  1. 新建脚本

    限制方块需要用到 BlockEvents 接口,每种接口只有在对应的文件夹中才有。所以这个接口只能够作为 sever_scripts 文件夹下的脚本。

    我们前往 例:.minecraft\versions\1.21.1\kubejs\server_scripts 目录下创建一个 limitBlocks.js 文件

  2. 编写代码

    使用文本编辑器打开 limitBlocks.js 文件。编写如下代码:

  3. const blockLimits = {
      'minecraft:stone': 50,
      'minecraft:sand': 30,
      'mekanism:digital_miner': 1
    };

    BlockEvents.placed(event => {
      const player = event.player;
      const world = player.level;
      const rayTraceResult = player.rayTrace(16);
      const placedBlock = event.block;
      const blockId = placedBlock.getId().toString();
      const restrictedBlocks = Object.keys(blockLimits); // 获取所有受限制的方块ID

      // 如果放置的方块不在受限制的列表中,则直接返回
      if (!restrictedBlocks.includes(blockId)) return;

      // 计算放置方块位置所在区块的坐标
      const chunkX = Math.floor(rayTraceResult.hitX / 16);
      const chunkZ = Math.floor(rayTraceResult.hitZ / 16);

      // 初始化方块计数器
      let count = 0;
      for (let x = chunkX * 16; x < (chunkX + 1) * 16; x++) {
        for (let z = chunkZ * 16; z < (chunkZ + 1) * 16; z++) {
          for (let y = -64; y < 320; y++) {
            let blockAt = world.getBlock(x, y, z);
            if (blockAt.id.toString() === blockId) {
                count++;
            }
          }
        }
      }

      // 检查方块数量是否超过限制
      if (count > blockLimits[blockId]) {
        player.tell('该方块在区块的总数量已经达到上限 (' + blockLimits[blockId] + ' 个).');
        event.cancel(); // 正确取消事件的方法
      }
    });
  4. 细节讲解

    第一个大坑,调用 BlockEventsplaced 才能监视玩家放置方块的行为。我在第一步就卡住了,这个在官网根本找不到教程,花了我1个多小时去github看源码+乱猜😒。

    利用 eventplayer block 属性来获取触发这个事件的 玩家数据正在被放置的方块数据

    利用获取到的 player 进一步调用 level 和 rayTrace 获取 world  rayTrace 属性。16表示与玩家视线在16格内相交方块的方块数据。

    获取 world 是为了拿到被放置方块的世界,rayTrace 为了拿到被放置方块的坐标,以便找到区块。

    我在这两个获取卡了很久,这应该是第二个大坑,因为以往的文档可不是这么获取的。后续全靠自己猜测猜出来的获取方式。

    中间就是计算和推断了,这里比较基础就跳过了。

    最后一个大坑来了,阻止事件的调用方式要调用 cancel() 方法,注意这里是方法,意味着有圆括号。这里的改动只官网的一个小角落里有介绍。

    并且写在 cancel() 后面的代码就不会被执行了。(这个挺重要)

结束语

由于只是一个小小的代码,所以到这里就结束了,但是这整整花了我好几个小时去猜代码,一切祸根源自官方没有及时更新api文档,猜代码过程实在是一言难尽。所以在这里贴出一份1.21.1本的代码教程,帮助大家避坑。