0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Minecraft 1.20.x forgeでMOD開発 カスタムコマンドの実装

Posted at

こちらの続きになります。

今回やりたいこと

MOD内で使用している言語切り替えるためのカスタムコマンドを実装していきます。
ローカライズのためのリソースの読み込みとかは完全にjavaの領分なので、今回はカスタムコマンドの実装のみ書いていきます。

コード

イベントハンドラはRegisterCommandsEventを使います。

    @SubscribeEvent
    public void onRegisterLocalizeCommand(RegisterCommandsEvent event)

コマンドの組み立て

まず、langというコマンドを実装します。

LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("lang").executes( context -> {
        // コマンド実行者にメッセージ送信
        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("test message"));
        return Command.SINGLE_SUCCESS;
    });

以上が基本形です。
Commands.literal()に作成したいコマンドの文字列。
executes()にデリゲートでコマンドの処理を差し込む感じです。
返り値にはCommand.SINGLE_SUCCESSというパッと見成功パターンの整数型しか用意されていません。
しかもこの整数をどこかで使っている感じもないので、Commandインターフェースを拡張してあげて以下のように失敗パターンの整数も用意してあげると可読性が増すかもしれません。

// Command<S>を拡張するインターフェース
public interface ICommandEx extends Command {
  int SINGLE_FAILURE = 0;
}
builder = Commands.literal("lang").executes( context -> {
        // コマンド実行者にメッセージ送信
        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("test message"));

        // 例外が発生する可能性のある処理
        if(){
            return ICommandEx.SINGLE_FAILURE;
        }

        return ICommandEx.SINGLE_SUCCESS;
    });

実際こんな感じで返す値を0にしても動作上は何も変わりませんでした。
この値で正否判定を行っているわけではなさそうです。
可読性のためだけに書いているだけなので、今回は普通にCommand.SINGLE_SUCCESS;で統一します。

コマンドの分岐

then()というメソッドが定義されているのでここでコマンドの分岐を書いていきます。

LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("lang")
        .then(Commands.literal("en")
                .executes(context -> {
                        // 言語切替処理省略
                        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("[Dev]:MOD language is now English."));
                        return Command.SINGLE_SUCCESS;
                }))
        .then(Commands.literal("ja")
                .executes(context -> {
                        // 言語切替処理省略
                        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("[Dev]:MODの言語が日本語になりました。"));
                        return Command.SINGLE_SUCCESS;
                }));

そのままですね。
基本形からthenでコマンドを派生していけるといった感じです。

コマンドの登録

最後にイベントハンドラからコマンドを登録して完了です。

@SubscribeEvent
public void onRegisterLocalizeCommand(RegisterCommandsEvent event) {

        LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("lang")
                .then(Commands.literal("en")
                        .executes(context -> {
                        // 処理省略
                        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("[Dev]:MOD language is now English."));
                        return Command.SINGLE_SUCCESS;
                        }))
                .then(Commands.literal("ja")
                        .executes(context -> {
                        // 処理省略
                        context.getSource().getPlayerOrException().sendSystemMessage(Component.nullToEmpty("[Dev]:MODの言語が日本語になりました。"));
                        return Command.SINGLE_SUCCESS;
                        }));
        // コマンドの登録
        event.getDispatcher().register(builder);
}

動作確認

スクリーンショット 2023-06-29 12.54.08.png

しっかりTAB補完も効いてコマンドも実行できました。

感想

サーバーサイドのみの実装だとクライアントのUIにあまり干渉できないので、アクションを起こさせたいときなどはこういったカスタムコマンドで操作させることになると思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?