腳本API

出自Minecraft基岩版开发Wiki
Mojang官方使用腳本API編寫的測試腳本。

腳本API(Script API)是Minecraft國際版中的一個腳本系統,可在附加包中實現腳本運算。目前腳本API在主機版上不可用[1],其他平台上均可使用。

腳本API支援使用JavaScript語言(以下簡稱JS)編寫,因此其靈活性要遠大於資料驅動,可為附加包的創作提供更多可能,但腳本API無法取代資料驅動的底層註冊與定義功能,例如加入方塊、實體、物品等內容。在附加包的實際開發過程中,腳本API可以彌補資料驅動在邏輯運算方面靈活性的不足,從而實現更複雜的效果,而且可以在一定程度上減小附加包編寫過程中的繁瑣程度。同時,腳本API與Molang的對接也可以使資料驅動的靈活性更進一層。

在遊戲測試方面,Mojang加入了GameTest框架[注 1],用於對原版遊戲進行測試。在遊戲中透過/gametest指令可以載入一個預製的結構並執行對應腳本來進行遊戲測試,最終會將測試結果意見回饋給玩家。

啟用[編輯]

腳本系統[編輯]

啟用該腳本系統需要在附加包的清單檔案中加入型別為腳本的清單模組。範例如下:

{
  "format_version": 2,
  "header": {
    "description": "Test",
    "name": "Example Pack",
    "uuid": "f6d6da21-232a-4f86-b74a-9303cd91f5be",
    "version": [ 0, 0, 1 ],
    "min_engine_version": [ 1, 19, 0 ]
  },
  "modules": [
    {
      "type": "data",
      "uuid": "472fcc44-df74-4189-9d38-4d6ce686dae8",
      "version": [ 0, 0, 1 ]
    },
    {
      "type": "script",
      "uuid": "d9519751-f5f8-48f8-a058-92348a13868f",
      "version": [ 0, 0, 1 ],
      "language": "javascript",
      "entry": "scripts/Main.js"
    }
  ]
}

清單模組的型別(即type欄位)為script時表示該包需啟用腳本系統。其中language欄位的值需填寫為javascriptentry欄位填寫載入附加包時載入的JS檔案。JS檔案都儲存在行為包的scripts資料夾中:

  •  Addon.mcaddon
    •  Resource Pack
    •  Behavior Pack
      •  scripts
        •  Main.js
        •  ……
      •  ……
      •  manifest.json
      •  pack_icon.png

因此需要將entry的值填寫為scripts/<file_name>.js

依此成功啟用腳本API後,還需要在清單檔案中加入腳本API的模組作為依賴項,才能將原生介面匯入並使用。

測試功能[編輯]

要啟用腳本API在新版本中的測試功能,需要開啟「搶鮮版API」實驗性玩法選項。

安全性[編輯]

JS中的eval()Function()不能直接在腳本系統中使用,若要啟用這兩項功能,需透過在清單檔案功能欄位中加入"script_eval"字串來啟用:

"capabilities": [ "script_eval" ]

多載[編輯]

使用/reload指令可以對腳本系統進行熱多載。

模組[編輯]

腳本API提供的原生模組包含了很多的介面。原生模組需要在清單檔案中的dependencies欄位作為包的依賴項載入,並在腳本中使用import陳述式匯入到腳本的作用域中。例如在清單檔案中透過模組名載入:

"dependencies": [
  {
    "module_name": "@minecraft/server",
    "version": "1.0.0"
  }
]

或透過UUID載入:

"dependencies": [
  {
    "uuid": "b26a4d4c-afdf-4690-88f8-931846312678",
    "version": "1.0.0"
  }
]

然後在JS檔案中匯入之前載入的模組:

import * as Minecraft from "@minecraft/server";

版本[編輯]

模組的版本用於指定遊戲使用對應版本的介面來載入腳本檔案,而不因為遊戲更新受到影響。Mojang於1.19.40.23版本修改了模組名之後,創作者在清單檔案中載入任意版本的模組都應使用新名稱,而在JS檔案中透過import陳述式匯入模組時,要使用對應版本的模組名。

需要注意的一點是,模組的搶鮮版本(即版本號帶「beta」字樣的版本)在腳本API更新下一個版本時不會被保留,因此使用了模組搶鮮版本的附加包需在新版本中修改模組版本號,否則將會拋出內容記錄錯誤並無法正常載入腳本。

列表[編輯]

模組 UUID 可用性
描述
@minecraft/client c1b4d019-b5cf-4e20-956d-8014a3e8c824 僅用戶端
@minecraft/common 77ec12b4-1b2b-4c98-8d34-d1cd63f849d5 可用
@minecraft/debug-utilities 1796ea86-0daf-4409-99ee-fd6467cf1203 可用 該模組包含一些系統除錯工具。
@minecraft/math N/A NPM包
@minecraft/server b26a4d4c-afdf-4690-88f8-931846312678 可用 該模組包含了與原版世界遊戲機制有關的介面。
@minecraft/server-admin 53d7f2bf-bf9c-49c4-ad1f-7c803d947920 可用 該模組包含與BDS有關的介面。這些介面允許在BDS的JSON檔案中組態變數和秘密,且不能在用戶端使用。
@minecraft/server-editor 1d565354-296d-11ed-a261-0242ac120002 可用 該模組包含與編輯器有關的介面。
@minecraft/server-editor-bindings 8518d9c7-a1f5-4bf3-acc7-78e87df595fc 可用
@minecraft/server-gametest 6f4b6893-1bb6-42fd-b458-7fa3d0c89616 可用 GameTest框架模組,該模組提供了與原版遊戲機制有關的用於測試的介面。
@minecraft/server-identity d8e7cb98-b05f-11ec-b909-0242ac120002 僅開發人員版
@minecraft/server-live-events-utilities 538443f1-63a6-4f02-b191-7bc828f225e0 僅開發人員版
@minecraft/server-net 777b1798-13a6-401c-9cba-0cf17e31a81b 可用 該模組包含執行基於HTTP請求的介面,且只能在BDS伺服器端上使用。
@minecraft/server-ui 2bd50a27-ab5f-4f40-a596-3641627c635e 可用 該模組包含了基於對話框的UI介面。
@minecraft/vanilla-data N/A NPM包

腳本編寫[編輯]

腳本API目前僅支援JS,但也可先使用TypeScript(以下簡稱TS)編寫再轉化為JS來執行。官方在腳本API文件中引入了部分TS概念並適當使用TS進行演示[2],這有利於開發人員對腳本API的理解,提高編寫程式碼過程的便捷性。本Wiki的腳本API相關頁面也將使用部分TS概念進行演示。

列舉[編輯]

列舉(Enumeration)包含了一組命名常數,可以使腳本編寫中的某些特定值更規範統一。列舉值的呼叫方式與物件屬性的呼叫方式一致,例如呼叫Direction列舉的值進行比較判斷:

import { world, Direction } from "@minecraft/server";

world.beforeEvents.itemUseOn.subscribe(data => {
    if(data.blockFace == Direction.Up) {
        world.sendMessage("你右键点击了方块顶面。");
    };
});

介面[編輯]

介面(Interface)是一種用於描述物件內容格式的TS型別。在腳本API的編寫中,介面表示傳入參數的格式或者傳回值格式。

JS中以介面指定格式物件編寫即可,下面是一個同時使用EntityQueryOptions介面和Vector3介面的範例:

import { world } from "@minecraft/server";

const queryOptions = {
    closest: 2,
    gameMode: "creative",
    location: {
        x: 1,
        y: 64,
        z: 1
    } // Vector3
}; // EntityQueryOptions
const target = world.getDimension("overworld").getPlayers(queryOptions);
world.sendMessage(`${target[1].name}是距离位置 1,64,1 第二近的创造模式玩家。`);

型別別名[編輯]

官方在文件中引入了型別別名(Type Alias),用於為腳本API的編寫提供便利。型別別名是TS中的一種型別,其本質是一種名稱映射。在取得NPM包後型別別名可用於TS的編寫,其並不存在於遊戲的腳本引擎中。

核心功能[編輯]

在腳本API中,大多數核心功能都在@minecraft/server模組中,可以使用其與Minecraft中的實體、方塊、維度等進行互動。

唯讀模式[編輯]

唯讀模式(Read-only Mode)是Mojang定義的一種非唯讀屬性或函式的鎖定狀態[3],在此狀態下腳本系統將禁止寫入某些屬性或呼叫某些函式,並且會拋出內容記錄錯誤[注 2]。此模式是Mojang對前事件作出的一種限制。

在傳入前事件的回呼函式中進行任何改變世界狀態的操作都將受到此限制,相關的屬性和方法會被設定為唯讀模式。例如以下操作:

import { world } from "@minecraft/server";

world.beforeEvents.itemUseOn.subscribe(data => {
    data.block.setType("minecraft:stone");
});

但可透過使用system.run()等方式來延遲執行操作,從而錯開前事件的觸發時間。

動態屬性[編輯]

動態屬性(Dynamic Property)是腳本系統儲存自訂資料的一種格式。目前動態屬性可以儲存在實體、物品和世界上。相較於資料驅動中屬性(或狀態)的「靜態性」,動態屬性可以實時增刪,且動態屬性的型別不固定,腳本系統以此可以實現資料的動態儲存。

用法[編輯]

官方提供了以下5個方法來對動態屬性進行操作:

  • clearDynamicProperties:清除該物件上的所有動態屬性。
  • getDynamicProperty:取得該物件上指定動態屬性的值。
  • getDynamicPropertyIds:取得該物件上所有動態屬性的ID。
  • getDynamicPropertyTotalByteCount:取得該物件上儲存的所有動態屬性的總字節數。
  • setDynamicProperty:在該物件上設定一個動態屬性。

這些方法可從World、​EntityItemStack三個類中呼叫。

動態屬性可以儲存布林型、數值型、字串型和三維向量型的資料,單個動態屬性的資料大小限制在32KB以內。大量的動態屬性資料可能會導致某些裝置上載入緩慢。

儲存[編輯]

動態屬性以NBT的形式儲存,其資料內容位於DynamicProperties複合標籤下。每個行為包的動態屬性儲存在以該行為包UUID命名的複合標籤內。

動態屬性NBT結構:
  •  DynamicProperties:實體的動態屬性集合。
    •  <UUID>:該動態屬性所屬行為包的UUID。
      •  <dynamic_property_id>[①]:布林型、數值型或字串型動態屬性。
      •  <dynamic_property_id>[②]:三維向量型動態屬性。
        • :X軸分量。
        • :Y軸分量。
        • :Z軸分量。
      •  ……

設定在實體或物品上的動態屬性儲存於其NBT內,若該實體或物品被清除,則其攜帶的動態屬性資料也會隨之一同消失。結構可以儲存實體或物品的動態屬性,且動態屬性的包UUID資訊不會丟失。

卸載行為包並重新載入世界不會使該行為包設定的動態屬性消失,動態屬性資料仍然會保留在存檔中,重新裝載該行為包後可以正常讀寫以前設定的動態屬性。

包獨立性[編輯]

每個附加包的腳本都是獨立的,它們之間互不相通。不能透過一個已啟用腳本API的附加包來使其他未啟用腳本API的附加包接入腳本系統,附加包之間的JS檔案也不能互相依賴或呼叫。

動態屬性在儲存時會記錄建立它的行為包的UUID並以此作區分,因此不同行為包建立的動態屬性也是相互獨立的。一個行為包不能刪除、建立或讀寫屬於另一個行為包的動態屬性。

透過/scriptevent指令可以一定程度上實現包與包之間的資料和邏輯互通。

看門狗[編輯]

看門狗(Watchdog)是一個效能監視器,用於監控腳本引擎中執行緩慢的腳本。

歷史[編輯]

基岩版
1.16.2101.16.210.60加入了GameTest框架。要啟用該框架,需要在實驗性玩法選項中開啟「GameTest框架」實驗性玩法。
1.19.201.19.20.20加入了看門狗。
?GameTest框架更名為腳本API。
1.19.401.19.40.23重新命名了所有模組:
  • mojang-gametest → @minecraft/server-gametest
  • mojang-minecraft → @minecraft/server
  • mojang-minecraft-ui → @minecraft/server-ui
  • mojang-minecraft-server-admin → @minecraft/server-admin
  • mojang-net → @minecraft/server-net
現在eval()Function()在使用前必須在清單檔案的capabilities欄位中加入"script_eval"
匯入模組時不再使用"script/<prefix>"的形式,而是"./<name>.js"
1.19.801.19.80.20現在執行時錯誤會以JavaScript錯誤的形式拋出。
修復了部分基類的繼承問題,並為部分類加入了新的基類。

你知道嗎[編輯]

  • 腳本API在社群曾被稱呼為「Plugin系統」。
  • 腳本API是基於QuickJS引擎實現的,因此它對原生JavaScript語法有著較好的支援。

畫廊[編輯]

參考[編輯]

  1. Minecraft Beta - 1.16.210.60 (Xbox One/Windows 10/Android)  — Minecraft Feedback,2021年2月18日。
  2. 官方腳本API微軟文件
  3. Minecraft Beta - 1.20.0.20  — Minecraft Feedback,2023年4月12日。

註釋[編輯]

  1. 腳本API原名如此,更名後GameTest框架成為其中一個模組
  2. [Scripting][error]-ReferenceError: Native function [<scope>] does not have required privileges.

Template:Navbox Addon