在Minecraft 1.20.x forge中进行MOD开发,实现自定义命令功能

这是前面的延续。

 

我想做的事情。

我们将实现在MOD内切换语言的自定义命令。资源的加载和本地化完全是Java的领域,所以这次只写自定义命令的实现代码。

代码 mǎ)

事件处理程序使用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にあまり干渉できないので、アクションを起こさせたいときなどはこういったカスタムコマンドで操作させることになると思います。

请参考

 

广告
将在 10 秒后关闭
bannerAds