はじめに
本記事は、以下の自分でコマンドを作ることができるシステム、CustomCommandについての記事の続編です。まだご覧になっていない方は、先にこちらからご覧になることをおススメします:
環境構築やCustomCommandの概要については上記の記事で解説しています。
さて、本記事ではこのCustomCommandにおいて引数を設定する方法について説明していきます。
引数とは?
簡単に言えば、コマンドを実行する際に、そのコマンドに与える値のことを引数といいます。分かりやすく言うとターゲットセレクターの「@a」とか場所を表す「~ ~ ~」がそうですね。

本記事は、カスタムコマンドにこの「引数」を設定してより自由度を上げよう、という趣旨です。

YouTube動画
本ページの内容について解説したYouTube動画を作成しました。こちらより視聴できます:
スクリプト
以下では変数serverが突拍子もなく出てきますが、これは以下のimport文で定義されています:
import * as server from "@minecraft/server";
さて、引数を設定するにあたって必要となるのが、前回も軽く触れましたがmandatoryParametersとoptionalParametersです。前者は必須となる引数(ないとエラーを吐く)であり、後者は任意の引数(なくてもいい)をそれぞれ定義します。ともに配列形式で引数を設定することとなっており、nameとtypeのプロパティが必要です。
以下は具体的に引数を設定した例です:
mandatoryParameters:[
{name:"test",type:server.CustomCommandParamType.String}
],
nameはこの引数の名前です。String形式で指定すること以外は特に留意することはないでしょう。問題は次のtypeです。これはこの引数の種類であり、予め決められたCustomCommandParamTypeの中から選ぶ必要があります。主要なものを挙げると以下:
種類 | 意味 | 例 |
server.CustomCommandParamType.String | 任意の文字列 | abc |
server.CustomCommandParamType.PlayerSelector | ターゲットセレクター | @a |
server.CustomCommandParamType.Location | 座標 | ~ ~1 ~ |
server.CustomCommandParamType.ItemType | アイテムの種類 | minecraft:diamond |
server.CustomCommandParamType.Integer | 整数値 | 3 |
server.CustomCommandParamType.Boolean | 真偽値 | true |
詳細は公式ドキュメントが詳しいです。
optionalParametersも同様の形式で指定します。
実行関数
続いて、この引数を受けて実行する関数を定義しましょう。前回「origin.sourceEntity.sendMessage(“test”)」とした部分ですね。
まず、この引数を受けて格納される変数argの中身を確認してみましょう。以下のスクリプトで確認できます:
origin.sourceEntity.sendMessage(JSON.stringify(arg))
すると文字列なら”abc”と、座標なら{“x”:0,”y”:0,”z”:0}のようにそれぞれ表示されると思います。これは先ほど指定したtypeによって異なります。あとはこの形式に従ってargを解析し、必要な情報を抽出するだけですね。例えばtypeが文字列の場合、
origin.sourceEntity.sendMessage(arg)
といったスクリプトでその文字列の出力ができますし、座標の場合は
origin.sourceEntity.sendMessage(String(arg.x));
でx座標の出力ができます。y座標やz座標も同様です。
なお、ここではsendMessageで出力するために、String関数で敢えて座標の数値を文字列にしています。単に座標を取得するだけならarg.xでOKです。また、ここで取得される座標は一般的に小数なので、ブロックを配置やコマンドの実行を行う際にそのまま使うとエラーとなります。その場合、
Math.floor(arg.x)
のような形で整数値に変換する必要があります。
複数の引数を出力する
コメントにてご指摘いただきました。複数の引数を取る場合、「arg1」、「arg2」のように複数の引数を用意し、それらを用いて関数内で処理を行うことになります。例を挙げると以下:
server.system.beforeEvents.startup.subscribe(ev => {
ev.customCommandRegistry.registerCommand({
name:"lq:test",
description:"これはテスト用のコマンドです",
permissionLevel : server.CommandPermissionLevel.Any,
mandatoryParameters:[
{name:"test",type:server.CustomCommandParamType.String},
{name:"test2",type:server.CustomCommandParamType.String}
],
optionalParameters:[
]
},(origin, arg1, arg2) => {
server.system.runTimeout(() => {
origin.sourceEntity.runCommand("say test")
origin.sourceEntity.sendMessage(arg1)
origin.sourceEntity.sendMessage(arg2)
},1)
})
})
あるいは、「…arg」(残余引数)を引数とすることで、arg[0]やarg[1]をそれぞれ参照することもできます:
server.system.beforeEvents.startup.subscribe(ev => {
ev.customCommandRegistry.registerCommand({
name:"lq:test",
description:"これはテスト用のコマンドです",
permissionLevel : server.CommandPermissionLevel.Any,
mandatoryParameters:[
{name:"test",type:server.CustomCommandParamType.String},
{name:"test2",type:server.CustomCommandParamType.String}
],
optionalParameters:[
]
},(origin, ...arg) => {
server.system.runTimeout(() => {
origin.sourceEntity.runCommand("say test")
origin.sourceEntity.sendMessage(arg[0])
origin.sourceEntity.sendMessage(arg[1])
},1)
})
})
選択肢から選ぶ引数
以下のように、選択肢から引数を1つ選んで入力する形式を作成することもできます:

鍵を握るのが、「server.CustomCommandParamType.Enum」と、registerEnum関数です。
registerEnumで列挙型の選択肢を定義し、CustomCommandParamType型のEnumで実際にコマンドにおける列挙型引数を定義します。
以下は、server.CustomCommandParamType.Enumを用いて列挙型の引数を定義するスクリプトの例です:
server.system.beforeEvents.startup.subscribe(ev => {
ev.customCommandRegistry.registerEnum("lq:arg",["a","b","c"]);
ev.customCommandRegistry.registerCommand({
name:"lq:test",
description:"これはテスト用のコマンドです",
permissionLevel : server.CommandPermissionLevel.Any,
mandatoryParameters:[
{name:"lq:arg",type:server.CustomCommandParamType.Enum}
],
optionalParameters:[
]
},(origin,arg) => {
server.system.runTimeout(() => {
origin.sourceEntity.sendMessage(String(arg));
},1)
})
})
ここでは、コマンド「lq:test」の引数「lq:arg」について、a,b,cの中から一つ選んで入力する形式としています。なお、ここでは引数の名前に名前空間が必須なので注意しましょう。
registerEnumで定義する引数の名前と、registerCommand内で定義する引数の名前は同一である必要があります。今回でいえば「lq:test」ですね。
おしまい
ということで、全2回にわたってコマンドを自作できる機能、CustomCommandについて解説してきました。ここまで言っておいて何なのですが、たぶんscripteventのほうが使い勝手がいいと思います。というのも、CustomCommandは「ベータ版の機能である」という点で今後仕様が変わる可能性が否めず、安定版で動作するscripteventに軍配が上がるからです。
ただ、何のコマンドにも依存することなく、チャット欄などで簡単にコマンドを実行できるという簡便さは、他に代えがたいメリットです。新しい物好きの方は、是非試してみるといいのではないでしょうか。