教學:編寫腳本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模組