教程:编写脚本API/server模块基础

来自Minecraft基岩版开发Wiki
server模块基础
系列教程
所属系列
难度
初级
实践设备
WindowsAndroid
所需软件

引言[编辑]

@minecraft/server 模块是脚本中很重要的一个模块,它管理着大部分方法和事件,像看门狗调用也是这个模块的一部分,进行这些学习可以帮助我们。

事件[编辑]

这里的事件是脚本api中的一个概念,通过订阅事件,我们可以监听游戏中发生的各种事情。

监听事件[编辑]

监听事件本质是订阅一个事件并对此事件进行处理的过程。
我们通过subscribe来订阅事件,用unsubscribe来完成退订。
把事件按运行方式分,可以分为AfterEventBeforeEvent两种,AfterEvent是在事件发生之后进行操作,BeforeEvent则可以在事件发生之前操作甚至取消事件的产生。
如果按照server模块中事类归属的类来区分的话,分为系统事件和世界事件。
接下来我们拿ItemUseBeforeEvent这个World事件为例,观察事件是如何被订阅并处理的。

import * as mc from '@minecraft/server';

mc.world.beforeEvents.itemUse.subscribe();

这样我们就完成了对ItemUseBeforeEvent的订阅,接下来我们需要对其进行处理,这里有两种方法。

箭头函数[编辑]

箭头函数是JavaScript中的一个功能强大的特性,它提供了一种更加简洁的方式来编写函数表达式。
事件的订阅处理就允许我们使用箭头函数,像下面这样。

mc.world.beforeEvents.itemUse.subscribe((event) => {   //使用event来储存有关事件的数据
    mc.world.sendMessage("你已使用道具");
});

我们不妨拿到游戏中去测试一番。

效果展示
使用function()[编辑]

除了使用箭头函数以外,subscribe的参数也支持直接使用函数名,不过需要您在清单文件中允许,具体的操作方法请见开始之前
接下来仍然用ItemUseBeforeEvent进行展示:

import * as mc from '@minecraft/server';

function itemUseEvent(event){   //使用event来接收数据
    mc.world.sendMessage("你已使用道具");
};
mc.world.beforeEvents.itemUse.subscribe(itemUseEvent);
event数据[编辑]

event数据是监听事件被触发时,返回的有关内容,拿ItemUseBeforeEvent举例,它只有一个回退属性cancel: boolean,来完成事件的取消。

系统事件[编辑]

当Minecraft附加系统范围内发生特定类型的事件时,系统事件会被触发。
这里我们不多介绍,以 看门狗事件 为例。
在某些情况下,看门狗会试图终止脚本,如果你有特殊需要,不想让其被终止,我们就可以使用 BeforeEvent的回退机制,这个功能在Before特权系统中有具体介绍,接下来我们就看一下具体代码:

mc.system.beforeEvents.watchdogTerminate.subscribe((event) => {  //订阅事件
	event.cancel = true;  //取消事件
	console.warn('看门狗终止被取消,类型为' + event.terminateReason);  //发送警告
});

要注意的是:

内存不足异常,不会被回退。

下面枚举一些经常会用到的系统事件,并给予展示:

世界事件[编辑]

世界事件API提供了许多事件API,当特定类型的事件发生在Minecraft的世界中,它们就会被监听到,下面给出一个示例:

mc.world.afterEvents.playerBreakBlock.subscribe((event) => {
    event.player.sendMessage(  //这是一个方法,用于对单独的玩家发送消息
        `你打破了${event.block.typeId}`   //block.typeId指的是方块类型
    );
});

接下来枚举一些经常会用到的世界事件,并给予展示:

脚本事件[编辑]

脚本事件事实上属于 system 事件,由于它的特殊性,我们将它单独拿出来讲。
如果您阅读过 脚本API 就应该知道/scriptevent命令可以完成包与包之间的互通。这种互通,具体的完成方法在以后会讲,现在请来了解一下它的原理。

我们通过订阅 scriptEventReceive 事件,可以获取到 scriptevent 命令给予的一些信息,并作出响应。

简单观察一下这个命令的基本语法:

scriptevent <messageId: string> <message: string>

我们可以找到messageId,这个是消息的id,用于指明这个消息是对哪个脚本发送的。问题在于,这个不是唯一标识符,如果您的脚本跟另外一个脚本同时注册了这个事件,并用相同的标识符响应,就可能出现混乱,同时订阅时间的时候,一个脚本甚至可以响应多个不同id的消息,这是需要注意的。
接下来我们看看scriptEventReceive事件具体有哪些参数:

  • id:string:对应着scriptevent命令中的<messageId: string>
  • sourceType:string/ScriptEventSource:表示着执行这条命令者的类型,可以是 方块(例如命令方块),实体(可以是玩家),NPC 等

下面是 ScriptEventSource 的列举:

Block = "Block",  //方块
Entity = "Entity",   //实体
NPCDialogue = "NPCDialogue",   //npc对话
Server = "Server"   //服务器,可以是脚本api使用的runCommand方法,也可以是服务器主机
  • initiator?:npc:对应npc对话中的npc
  • sourceBlock?:block:对应执行的方块
  • sourceEntity?:entity:对应执行的实体

要注意的是:

如果使用 execute 命令,那么 sourceType 等也会改变。

接下来我们来具体实践一下:

mc.system.afterEvents.scriptEventReceive.subscribe((event) => {
    mc.world.sendMessage(`您成功执行了scriptevent命令,其id为${event.id},消息为${event.message},来源类型为${event.sourceType}`);
});

Before特权系统[编辑]

Before特权系统,指的是Before事件拥有的强大回退能力。
其可以取消将(或已)产生的事件,比如发送消息:

mc.world.beforeEvents.chatSend.subscribe((event) =>{
    event.cancel = true;
    event.player.sendMessage("消息发送已被取消");
});

同样,这个特权系统拥有强大的回退能力,但也有一定的限制。为了防止两个事件同时产生,在游戏时间点中间发生级联变化。特权系统不允许您使用可以引起其他事件的方法(例如:world.setTime()-设置游戏时间)。但我们拥有一些方法绕过他们:

进行提权[编辑]

进行提权可能是最简单有效的方法了,我们来看下面这一段代码:

mc.world.beforeEvents.chatSend.subscribe(event => {
	event.cancel = true;
    mc.world.setTime(13000);
});

正常来说就会在玩家发送一条消息之后,将游戏时间设置为 13000(夜晚),但它却会抛出一条无权限错误。
而如果使用system.run()而将权限提高到 System 层级的话,就不会产生错误:

mc.world.beforeEvents.chatSend.subscribe(event => {
	event.cancel = true;
	system.run(() => {
        mc.world.setTime(13000);
    });
});

async稍后执行[编辑]

通过使用等待时间超过滴答的 async 函数,可以绕过特权系统。

mc.world.beforeEvents.chatSend.subscribe(async (event) => {
    event.cancel = true;
    await sleep(10);   //sleep函数需要自己定义
    mc.world.setTime(13000);
});

这个方法有一个很有趣的地方,本来我们订阅的是Before事件,应当在消息发送之前就将其回退掉,但现在我们却可以等待一段时间,再将其回退,就好像撤回了一般。

看门狗[编辑]

看门狗是脚本API的一个性能系统,一般情况下,当有脚本的时候它被启用。

配置[编辑]

自1.19.20以来,有一组监视器配置用于管理脚本环境的性能。这些选项不能在世界或服务器中修改,但可以通过专用服务器中的 server.properties 进行修改。以下是默认的看门狗设置,在所有设备上都是相同的。

命令[编辑]

我的世界中允许使用 /script watchdog 命令来对开门狗进行一些操作

引用[编辑]

1.官方文档:Minecraft中的脚本介绍
2.官方文档:脚本api参考文档
3.官方文档:minecraft/server模块