【ScriptAPI】カスタムコマンドを作ろう

スポンサーリンク

前提知識

・ビヘイビアパックの作り方が分かる。
・ScriptAPIの作り方が分かる。

分からない場合は、こちらをご覧ください。

カスタムコマンドを作ろう

今回は、v1.21.80でさらに便利になった「カスタムコマンド」の作り方を解説します。

「カスタムコマンド」とは、オリジナルのコマンドを追加できる機能のことです。例えば、ロビーにTPする「/lobby」や、OPでなくても使える「/kill」などのコマンドを作成することができます。

現時点では、この機能はベータ版のScriptAPIでのみ利用できます。
そのため、manifest.json の @minecraft/server バージョンは「2.0.0-beta」または「3.0.0-alpha」を指定してください。

saba:helloコマンド

さっそく簡単なコマンドを作ってみましょう。

/saba:hello – あいさつを行う。

コマンド内容:
・チャット欄に「[名前] Hello!」と送る。
・もしプレイヤー以外(モブやコマンドブロック)が実行したときは、失敗メッセージを返す。

コード

① 必要なクラスをインポート

まず最初に、@minecraft/server から必要なクラスをインポートします。

import { system, world, CommandPermissionLevel, CustomCommandStatus, CustomCommandOrigin } from "@minecraft/server";

② コマンドの登録

次に、saba:hello というカスタムコマンドを登録します。

system.beforeEvents.startup.subscribe(ev => {
    /**
     * saba:helloコマンドを定義
     * @type {import("@minecraft/server").CustomCommand}
     */
    const helloCommand = {
        name: "saba:hello", // コマンド名
        description: "あいさつを行う", // コマンド説明
        permissionLevel: CommandPermissionLevel.Any, // 権限レベル: 誰でも
        // 必須の引数
        mandatoryParameters: [], // なし
        // 引数
        optionalParameters: [], // なし
    }

    // helloコマンドを登録
    ev.customCommandRegistry.registerCommand(helloCommand, hello);
});

・コードにはJSDocを使って型を明示しています(@type)。これでVSCodeで補完が効くようになります。
・registerCommand() にはコマンド(helloCommand)と、そのコマンドの処理関数(hello)を渡します。

③ コマンドの処理関数の定義

最後にsaba:helloコマンドの処理関数を定義します。

/**
 * saba:helloコマンドの処理関数
 * @param {CustomCommandOrigin} origin 
 * @returns {import("@minecraft/server").CustomCommandResult}
 */
function hello(origin) {
    // origin には実行者エンティティやブロックが入る

    // もし実行者エンティティの種族がプレイヤーではないなら
    if (origin.sourceEntity?.typeId !== "minecraft:player") {
        // コマンド結果を返す
        return {
            status: CustomCommandStatus.Failure, // 失敗
            message: "実行者はプレイヤーである必要があります",
        }
    }

    const player = origin.sourceEntity;

    // 挨拶メッセージを送る
    world.sendMessage(`[${player.nameTag}] こんにちは!`);

    // コマンド結果を返す
    return {
        status: CustomCommandStatus.Success, // 成功
        message: undefined, // メッセージなし
    }
}

・origin には、実行タイプ(sourceType)や実行エンティティ(sourceEntity)、実行ブロック(sourceBlock)が入っています。
・コマンドの処理関数では、必ずコマンド結果を返す必要があります。

実行結果

%E3%81%82%E3%81%84%E3%81%95%E3%81%A4%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C.png

saba:sayコマンド

続いて、引数があるコマンドを作ってみましょう。

/saba:say <message: String> – 
メッセージを送信する

コマンド内容:
・チャット欄に「[名前] メッセージ内容」と送る。
・もしプレイヤー以外が実行したときは、失敗メッセージを返す。

コード

① インポート

// CustomCommandParamType を追加
import { system, world, CommandPermissionLevel, CustomCommandStatus, CustomCommandOrigin, CustomCommandParamType } from "@minecraft/server";

② コマンドの登録

system.beforeEvents.startup.subscribe(ev => {
    // 省略

    /**
     * saba:sayコマンドを定義
     * @type {import("@minecraft/server").CustomCommand}
     */
    const sayCommand = {
        name: "saba:say",
        description: "メッセージを送信する",
        permissionLevel: CommandPermissionLevel.Any,
        // 必須の引数
        mandatoryParameters: [
            // 一つ目の引数 文字列型
            { name: "message", type: CustomCommandParamType.String },
        ],
        optionalParameters: [],
    }

    ev.customCommandRegistry.registerCommand(sayCommand, say);
});

・madatoryParamters には必須の引数を指定します。
・name には引数名、typeには型が入ります。
 typeには、文字列や数値、座標やアイテムID、プレイヤーセレクター、エンティティセレクターなど色々指定できます。

③ コマンドの処理関数の定義

/**
 * saba:sayコマンドで呼び出される関数
 * @param {CustomCommandOrigin} origin
 * @param {string} message 
 * @returns {import("@minecraft/server").CustomCommandResult}
 */
function say(origin, message) {
    // 関数には (origin, 引数1, 引数2, 引数3...) のように値が渡される

    if (origin.sourceEntity?.typeId !== "minecraft:player") {
        return {
            status: CustomCommandStatus.Failure,
            message: "実行者はプレイヤーである必要があります",
        }
    }

    const player = origin.sourceEntity;

    // コマンドの引数 message の値を埋め込んで送る
    world.sendMessage(`[${player.nameTag}] ${message}`);

    return {
        status: CustomCommandStatus.Success,
        message: undefined,
    }
}

・コマンドの処理関数には、test(origin, 引数1, 引数2, 引数3…) のように、引数の値が渡されます。
・今回は、引数の型に文字列を指定しているので、messageには文字列が入っています。

実行結果

say%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C.png

今日作ったプログラムの完成品はこちらです。

最後に

いかがでしたか?

今回はカスタムコマンドの作り方を解説しました。

とても面白い機能なので、ぜひ試してみてください。

ただし、この機能はまだ開発中であるため変更される可能性があります。配布する際にはご注意ください。

もしご質問があれば、コメント欄でお気軽にどうぞ。

※投稿記事に含まれるファイルやリンクにより発生した被害についてクラフターズコロニーは責任を取りません
投稿通報

コメント

  1. 待ってました

  2. ありがたすぎる

  3. runCommandを使うことはできますか?

    • できます

  4. runcommandはどうやって記述するのでしょうか?
    私が思い浮かべているコード: player.runcommand(“コマンド”);

    • world.sendMessage() を使用している箇所で、
      player.runCommand() を使えばできます。

  5. 助けてください
    作ったやつがエラー吐いて動かないんです
    https://minecraft-mcworld.com/153317/

    • 19行目のregisterCommand()の第二引数で渡している、「timerCommandFunc」が間違っています。

      このtimerCommandFunc関数では、コマンドの実行結果(成功したのか、失敗したのか)を返す(return)必要があります。

    • ev=> {が e=> {になっています

  6. 最近xも投稿ないけどどうしたんだろう

コメント通報