2
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 3 years have passed since last update.

【Kotlin+Spigot】2.2 コマンドを新しく作る

Last updated at Posted at 2020-04-30

0. 初めに

build.gradleplugin.yml の設定は終わらせた前提で進めます。
プロジェクトを作成する を参考にメインクラスを作るまで終わらせておいてください。

1. plugin.yml にコマンドを登録する

プロジェクトを作った段階で以下の5つは設定し終わっていると思います。

plugin.yml
name: "NewCommand"
version: "1.0"
api-version: "1.15"
main: me.syari.p_2_2_new_command.Main
author: sya_ri

author 以降に コマンド登録を書いていきます。
今回は、/hello というコマンドを登録してみましょう。

plugin.yml
name: "NewCommand"
version: "1.0"
api-version: "1.15"
main: me.syari.p_2_2_new_command.Main
author: sya_ri
commands:
  hello: # コマンドの名前
    usage: "/<command>" # コマンドの短い説明
    description: "挨拶します" # コマンドの説明
    aliases: # コマンドの別名
      - hi

commands というセクションの中にコマンドを書いていきます。
残りは全てコメントに書いてある通りです。補足的に説明をすると、
aliases というのを登録しておくとそのコマンドでも同じ処理をしてくれます。
今回であれば、/hello と打っても、/hi と打っても処理は同じです。
また、設定項目の省略も可能です。permissionpermission-message という項目もありますが省略しています。
aliases は無ければ省略しましょう。usagedescription は書いておいた方がいいでしょう。

2. コマンドの処理を書く

新規ファイルで HelloCommand というオブジェクトを作ってください。
CommandExecutor というのを継承してください。
これを継承することで、コマンドの処理を書けるようになります。

HelloCommand.kt
object HelloCommand: CommandExecutor {

}

そうするとこのように赤くなると思います。Implement members をクリックしましょう。
image.png
onCommand が選択されていると思うので、OK をクリックしましょう。
以下のように自動でコード生成されます。
image.png
onCommand というのがコマンドの処理を書く関数になります。
この関数の引数について説明します。
sender: CommandSender コマンドを実行したプレイヤーやコンソール が入っています。
command: Command ほとんど使いません。plugin.yml で設定したものを取得出来ます。
label: String コマンドラベルです(/ラベル)。 今回であれば hellohi になります。
args: Array<out String> コマンドの引数 が全て入っています(/ラベル 引数0 引数1 引数2 ...)。
また、戻り値は Boolean になっていますが、基本的に true を返しておけば大丈夫です。(異常終了だったら false)

では実際の処理を書きましょう。
とりあえず自分に挨拶を返してもらいましょう。

    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        sender.sendMessage("Hello ${sender.name}")
        return true
    }

コマンドの処理は終わりです。

3. コマンドを登録する。

イベントの時同様に処理をしてもらう為には登録しなければなりません。
plugin.yml でやったじゃないか!!」と思う人もいるかもしれませんが、あれで登録したのは
どのプラグインで処理をするか」だけです。どのクラスで処理をするか は登録してません。
イベント同様、onEnable に書きます。

    override fun onEnable() {
        getCommand("hello")?.setExecutor(HelloCommand)
    }

getCommand("hello") でhelloコマンドを取得します。しかし、コマンドが存在しない可能性もありますね。
存在しないコマンドであれば null という値が入っています。
?. というのは存在するのであればそれ以降の処理をする。といった感覚です。
setExecutor(HelloCommand) で実行クラスを変更しています。

さあ、プラグインをサーバーで試してましょう。

コンソールから実行すると
image.png

プレイヤーから実行すると
image.png

こうなっていたら成功です。

4. コマンド登録できたか通知する

このままだと、もしもタイプミスしてしまった時にコマンドが登録出来なかったことに気付くのが難しくなります。
登録できたかどうかをコンソール出力してみましょう。
さて、コマンドが登録できない場合はどういった時でしょうか?
答えは、getCommand の戻り値が null であった時です。
であれば、null かどうかを比較して処理を分岐してあげればいいのです。
image.png
こんな感じになります。実際にプログラムにしましょう。

    override fun onEnable() {
        val helloCommand = getCommand("hello")
        if(helloCommand != null){
            helloCommand.setExecutor(HelloCommand)
            logger.info("/hello を登録しました")
        } else {
            logger.severe("/hello を登録できませんでした")
        }
    }

getCommand の戻り値を helloCommand という変数で保存しています。
helloCommandnull でなければ 登録 & 成功メッセージ
それ以外(helloCommandnull)であれば 失敗メッセージ
if は条件分岐です。括弧の中は Boolean です。if(true) であれば実行されます。
else も条件分岐ですが、他・それ以外 みたいな意味です。直前の iffalse であれば実行されます。

if(false){
    // 実行されない
} else {
    // 実行される
}

if else は基本構文なので覚えておきましょう。(else if もありますが、Kotlin では不要。次の記事で解説します。)

さて、サーバーでテストしてみましょう。
image.png
このようにメッセージがあれば成功です。

いつも通り関数化しましょう。

Main.kt
class Main: JavaPlugin() {
    override fun onEnable() {
        registerCommand("hello", HelloCommand)
    }

    private fun registerCommand(label: String, executor: CommandExecutor){
        val command = getCommand(label)
        if(command != null){
            command.setExecutor(executor)
            logger.info("/$label を登録しました")
        } else {
            logger.severe("/$label を登録できませんでした")
        }
    }
}

今回は、コマンドラベルと処理クラスの2つあるので、引数は2つです。
それぞれ labelexecutor としています。
この関数は Main でしか使わないので fun の前に private と付けておきます。
サーバーでテストしてみて、同じようにメッセージが出たら成功です。
また、registerCommand("hello", HelloCommand)"hello""hell" みたいに違うコマンドにして
「登録できませんでした」 というメッセージが出たら成功です。

これで、終了です。お疲れ様でした。

5. 【+α】 Kotlin っぽくかく

内容が難しいかもしれません。ここまでの内容で頭がパンパンの人は見ないでください。

**見てみる**
理解できなくても不安がらないでください。あくまで紹介程度です。 難しく考えず、「こう書けるんだ」程度に思ってください。

こう書けます。

    private fun registerCommand(label: String, executor: CommandExecutor){
        getCommand(label)?.run {
            setExecutor(executor)
            logger.info("/$label を登録しました")
        } ?: logger.severe("/$label を登録できませんでした")
    }

新しく出てきたものが2つあります。
?.run {}null でなければ中括弧の中を実行する。
?:null であれば別の処理をする。といった感じです。

場合分けして考えてみましょう。
1. getCommandnull ではなかった場合
単純に run {} の中が実行されます。

/* null ではない getCommand(label) */.run {
    setExecutor(executor)
    logger.info("/$label を登録しました")
}

2. getCommandnull だった場合
getCommandnull だと ?.run {} も null になります。
?: の挙動は null ?: /* これが実行される */ こういう感じなので
失敗メッセージのみが残ります。

/* 全部 null になって ?: 以降だけ残る
getCommand(label)?.run {
    setExecutor(executor)
    logger.info("/$label を登録しました")
} ?: */ logger.severe("/$label を登録できませんでした")

Kotlin ならではの書き方というのがあります。
それを使うと変数宣言の量が減ったり、分かりやすく書けたり することもあります。
あくまで、「そういうこともある」 というだけなので、覚える必要はないです。
自分ひとりで構想を立てて、実際にプラグインを作れるようになってからで十分です。
それでも、「やったことがある」 という記憶は役に立ちます。お疲れ様でした。

リンク

次の記事に進む

目次に戻る

2
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
2
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?