注目キーワード

「CustomCommand」に引数を設定する方法を解説! – 1.21.80で変わったScriptAPI

はじめに

本記事は、以下の自分でコマンドを作ることができるシステム、CustomCommandについての記事の続編です。まだご覧になっていない方は、先にこちらからご覧になることをおススメします:

環境構築やCustomCommandの概要については上記の記事で解説しています。

さて、本記事ではこのCustomCommandにおいて引数を設定する方法について説明していきます。

Character
引数を設定できるとだいぶできることが増えます

引数とは?

簡単に言えば、コマンドを実行する際に、そのコマンドに与える値のことを引数といいます。分かりやすく言うとターゲットセレクターの「@a」とか場所を表す「~ ~ ~」がそうですね。

Character
元はプログラミング・数学の用語です

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

YouTube動画

本ページの内容について解説したYouTube動画を作成しました。こちらより視聴できます:

スクリプト

以下では変数serverが突拍子もなく出てきますが、これは以下のimport文で定義されています:

import * as server from "@minecraft/server";
Copied!

さて、引数を設定するにあたって必要となるのが、前回も軽く触れましたがmandatoryParametersとoptionalParametersです。前者は必須となる引数(ないとエラーを吐く)であり、後者は任意の引数(なくてもいい)をそれぞれ定義します。ともに配列形式で引数を設定することとなっており、nameとtypeのプロパティが必要です。

以下は具体的に引数を設定した例です:

mandatoryParameters:[
    {name:"test",type:server.CustomCommandParamType.String}
 ],
Copied!

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))
Copied!

すると文字列なら”abc”と、座標なら{“x”:0,”y”:0,”z”:0}のようにそれぞれ表示されると思います。これは先ほど指定したtypeによって異なります。あとはこの形式に従ってargを解析し、必要な情報を抽出するだけですね。例えばtypeが文字列の場合、

origin.sourceEntity.sendMessage(arg)
Copied!

といったスクリプトでその文字列の出力ができますし、座標の場合は

origin.sourceEntity.sendMessage(String(arg.x));
Copied!

でx座標の出力ができます。y座標やz座標も同様です。

なお、ここではsendMessageで出力するために、String関数で敢えて座標の数値を文字列にしています。単に座標を取得するだけならarg.xでOKです。また、ここで取得される座標は一般的に小数なので、ブロックを配置やコマンドの実行を行う際にそのまま使うとエラーとなります。その場合、

Math.floor(arg.x)
Copied!

のような形で整数値に変換する必要があります。

複数の引数を出力する

コメントにてご指摘いただきました。複数の引数を取る場合、「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)
    })
})
Copied!

あるいは、「…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)
    })
})
Copied!

選択肢から選ぶ引数

以下のように、選択肢から引数を1つ選んで入力する形式を作成することもできます:

鍵を握るのが、「server.CustomCommandParamType.Enum」と、registerEnum関数です。

Character
ちなみにEnumは「列挙型」という意味です

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)
    })
})
Copied!

ここでは、コマンド「lq:test」の引数「lq:arg」について、a,b,cの中から一つ選んで入力する形式としています。なお、ここでは引数の名前に名前空間が必須なので注意しましょう

registerEnumで定義する引数の名前と、registerCommand内で定義する引数の名前は同一である必要があります。今回でいえば「lq:test」ですね。

おしまい

ということで、全2回にわたってコマンドを自作できる機能、CustomCommandについて解説してきました。ここまで言っておいて何なのですが、たぶんscripteventのほうが使い勝手がいいと思います。というのも、CustomCommandは「ベータ版の機能である」という点で今後仕様が変わる可能性が否めず、安定版で動作するscripteventに軍配が上がるからです。

ただ、何のコマンドにも依存することなく、チャット欄などで簡単にコマンドを実行できるという簡便さは、他に代えがたいメリットです。新しい物好きの方は、是非試してみるといいのではないでしょうか。

最新情報をチェックしよう!