Minecraft Kotlinプラグイン開発 中級編 Part.1 コマンドの引数の設定

## 初めに
今回の記事では[入門編 Part.4](https://qiita.com/tooooowa/items/b02d0f06bdacb637c060)で作成したコマンドを触っていきます。  
また、その応用で後半では新たに足し算をするコマンドも作成します。

入門編の続きになるので中級編へ入る前に、入門編の一連の流れは先にやってください。

今回紹介するコマンドの引数は
自作コマンドを作るときにたくさん使うのでしっかり練習していきましょう！

**前** → [番外編 plugin.ymlの高度な編集](https://qiita.com/tooooowa/items/e32143047f2913a13330)
**次** → [中級編 Part.2 チェストGUIの作成](https://qiita.com/tooooowa/items/0e03ed15504d9b253898)

**目次** →  [目次と今後の展望](https://qiita.com/tooooowa/items/7809ec65dee757570250)


## /debugコマンドでプレイヤー名を呼び出す
入門編で作成した`/debug`コマンドを触っていきます。
前回のコードは以下のようになっています。
```DebugCommand.kt
package com.github.tooooowa.tutorialplugin // この行は環境によって異なります

import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender

object DebugCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        sender.sendMessage("こんにちは")
        return true
    }
}
```
この状態だとコマンドを実行したときに`こんにちは`と常に帰ってきます。

ずっと同じ内容が返ってくるコマンドだと面白くないので、
コマンドを実行したプレイヤー名を表示してみましょう！

```kotlin
sender.sendMessage("こんにちは")
```
具体的には上記の"こんにちは"の部分を変えることでメッセージが変更できます。

まずは`〇〇さん、こんにちは`と表示したいので実行したプレイヤー名を取得します。
このコマンドの関数では`sender`が実行者と前に教えました。
そのためメッセージの中に`sender`の名前(`name`)を表示させます。

```kotlin
sender.sendMessage("${sender.name}さん、こんにちは")
```
`""`の中で変数や定数を使う時は`${ }`で囲みます。覚えておきましょう。

:::note info
`{}`の中が英数字だけの場合`{}`を省略可能です。(例: `${sender}`→`$sender`)
:::

これで試しにビルドしてみましょう。
マイクラ内にプラグインを実装して以下のように表示されたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/6a4314a6-9567-dace-9513-f37c05d57216.png)
動かない場合は以下の文と比べてみてください。
```DebugCommand.kt
package com.github.tooooowa.tutorialplugin // この行は環境によって異なります

import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender

object DebugCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        sender.sendMessage("${sender.name}さん、こんにちは")
        return true
    }

}
```
## /debugコマンドに引数を追加
次に今のコマンドに引数を追加します。
完成形では`[プレイヤー名]さん、[引数]`と表示させます。

まずは`plugin.yml`に引数があるということを記述します。
```plugin.yml
name: TutorialPlugin
version: '${version}'
main: com.github.tooooowa.tutorialplugin.TutorialPlugin # ここは環境によって異なります
api-version: '1.20'
commands:
  debug:
    usage: "/debug <text>"
    description: "デバッグ用のコマンドです"
    permission: tutorialplugin.commands.debug
```
今回は7行目の`usage: "/debug"` を `usage: "/debug <text>"`に変更しました。

ルールではないですが必須な引数を`<>`、無くてもいい引数は`[]`で括ります。
このコマンドでは`<text>`の部分は必須なので`<>`で括りました。

### コマンドのコードの変更
次にコマンドのコードを変更します。
今回は送るメッセージの内容を改変するだけなので
また`sendMessage`の中身を変更するだけで可能です。

引数を取得する時は`args`を使用します。
今度変数に関してはもう少し詳しく紹介するので、今はざっと紹介しておくと
`args`はリストの形式の変数で保存されており、`/debug [引数1] [引数2]`のように
コマンドを実行すると全てがこの`args`に保存されます。
リスト形式の変数では変数名の後に`[数値]`を付けることでその番号の引数を取得できます。
今回の場合は１つ目の引数を取得したいので`args[0]`と入力します。

:::note warn
引数の番号では0からスタートです (引数1: `args[0]` 引数2: `args[1]` 引数3: `args[2]`)
:::
記入すると以下のようなコードになります。
```DebugCommand.kt
package com.github.tooooowa.tutorialplugin // この行は環境によって異なります

import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender

object DebugCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        sender.sendMessage("${sender.name}さん、${args[0]}")
        return true
    }

}
```
これをサーバーに導入し `/debug テスト` と入力して画像のように表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/f182d805-560d-b518-030f-ec91c1b97d78.png)

### 引数に関してよくあるミスの紹介
この今用意したコマンドで引数を付けずに
コマンドを実行すると以下のようにエラーが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/e24a7a98-5964-51e0-47f4-a9e9660fe2fc.png)
`/debug`とだけ入力してコマンドを実行した結果↑

このように引数が必要な処理で引数を入れない場合はエラーが出るので、
自分でコマンドを作る時は注意しましょう。

:::note info
このエラーが出た際はコンソールを見ると赤文字でとても長いエラーが出てます。
このようなエラーはプラグイン制作でよく見ることがありますが、
長すぎて翻訳できません。
なのでChatGPTなどのAIを通して翻訳と要約をしてもらうのがおすすめです。
するとエラーの原因を分かりやすく答えてくれます。
:::

## 足し算コマンドの作成
引数を追加する方法を覚えたら次は試しに足し算のコマンドを作ってみましょう。
今回は引数を2つ使用し、2つの和を出力します。
また、ここで変数も少し使っていきます。
### plugin.ymlにコマンドを追加
まずは`plugin.yml`に新しくコマンドを追加します。
`/sum <数値1> <数値2>` で2つの引数の和が返ってくるようにします。
権限の欄はこのコマンドを全員が使えるようにするので行ごと削除します。
```plugin.yml
name: TutorialPlugin
version: '${version}'
main: com.github.tooooowa.tutorialplugin.TutorialPlugin # ここは環境によって異なります
api-version: '1.20'
commands:
  debug:
    usage: "/debug"
    description: "デバッグ用のコマンドです"
    permission: tutorialplugin.commands.debug
  sum:
    usage: "/<command> <number> <number>"
    description: "足し算用のコマンドです"
```
`.yml`の形式では基本的に上のように空白2つを`:`の後には入れます。
yml形式はマイクラのプラグインを触っていると見る場面が多いので覚えておきましょう。

### コマンドのオブジェクトの追加
メインクラスと同じ階層に新しくコマンド用のオブジェクトを作成します。
今回は`SumCommand`と名付けました。
オブジェクトの作成方法を忘れてしまった方は[<INS>コチラの記事</INS>](https://qiita.com/tooooowa/items/b02d0f06bdacb637c060)に一度戻ってみてください。
中にコマンドが実行されたときの処理を書きます。
```SumCommand.kt
package com.github.tooooowa.tutorialplugin // ここは環境によって異なります

import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender

object SumCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        // 引数の数が2より小さい=引数が1つもしくは0の時に以下の処理を実行
        if (args.size < 2) {
            sender.sendMessage("コマンドの使用方法が間違っています。")
            return false
        }
        // ここから下に処理を追加
        
        return true
    }
}
```
`if`を使用して、引数が足りない時にエラーを送って実行を中断する処理を追加しました。
最初で紹介した通り、引数が足りないとコマンド実行時に長いエラーが起きてしまうため
出来るだけ条件分岐を使用して回避させましょう。
#### if文の使いかた
入門編では紹介しなかったif文の使いかたです。
```kotlin
if (/*条件式*/) {
    // 処理
}
```
基本は上の形でifの後の`()`で条件を記述します。
条件は今回だと引数`args`の保存されてる数が2より小さいとしているため
引数が0個もしくは1個の場合この中の処理を実行します。
```SumCommand.kt
// (import文は省略)
object SumCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        // 引数の数が2より小さい=引数が1つもしくは0の時に以下の処理を実行
        if (args.size < 2) {
            sender.sendMessage("コマンドの使用方法が間違っています。")
            return false
        }
        // ここから下に処理を追加
        val num1 = args[0].toInt()
        val num2 = args[1].toInt()
        val sum = num1 + num2
        sender.sendMessage("$num1 + $num2 = $sum")
        return true
    }
}
```
足し算の処理は上のように書きました。
追加した部分を上から解説していくと
まずは変数`num1` `num2`に引数を代入しています。

この時、変数名のあとに`.toInt()`と書くことで
引数は元々文字列の`String`で保存されているのを数字の`Int`型に変換しています。
コマンドの引数は常に`String`で保存されているのでこの構文はよく使います。
覚えておきましょう！

その後sumに2つの和を代入しています。
代入した結果を`sendMessage`で出力して`return true`で処理終了です。
部分毎に分けて考えると難しくないのでゆっくり理解していきましょう。

#### 変数の使い方
変数は機能が多くて全て紹介するとそれだけで一つの記事になってしまうので
今は使う場所だけ紹介します。

今回の文では変数を定義し、値を代入しています。

`val num1 = args[0].toInt()`
この文は変数`num1` に `args[0]`を数字として代入するという文です。

変数の定義ではまず変数名の前に`val`か`var`を付けます。
`val`はその変数の内容を一度設定したら変えられませんが、
`var`では定義した後にまた値を変更できます。
今回は変数の中身を変える必要はないので`val`を付けました。

基本的にKotlinでは"代入する"という処理に対して`=`を使います。
数学とかで使う`=`とは少し使いかたが違うので注意しましょう。

### メインクラスに登録処理を追加
入門編と全く同じやり方で登録処理を追加します。
コマンド名を`sum`に変えて、Executorを`SumCommand`に変更します。
```TutorialPlugin.kt
package com.github.tooooowa.tutorialplugin

import org.bukkit.plugin.java.JavaPlugin

class TutorialPlugin : JavaPlugin() {
    override fun onEnable() {
        // Plugin startup logic
        server.pluginManager.registerEvents(EventListener, this)
        getCommand("debug")?.setExecutor(DebugCommand)
        getCommand("sum")?.setExecutor(SumCommand)
    }

    override fun onDisable() {
        // Plugin shutdown logic
    }
}
```
## 実行
ビルドしてサーバーに入れてみましょう。

まずは `/sum` と実行してみます。(この時引数は設定しません)
以下のようにエラーが出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/bbedd455-ce4e-04f5-8fd6-39ad32cb052a.png)

次に`/sum 2 5`と入力します。
以下のように足し算がちゃんとされれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/34459cfc-b5dc-17d0-e11b-54c9815b2eeb.png)
## 終わりに
今回は足し算のコマンドを作りながらif文と変数について勉強しました
次回はチェストを使ったGUIを作成していきます。
お疲れ様でした！

**前** → [番外編 plugin.ymlの高度な編集](https://qiita.com/tooooowa/items/e32143047f2913a13330)
**次** → [中級編 Part.2 チェストGUIの作成](https://qiita.com/tooooowa/items/0e03ed15504d9b253898)

**目次** →  [目次と今後の展望](https://qiita.com/tooooowa/items/7809ec65dee757570250)

## 参考
[https://qiita.com/sya-ri/items/f69f1489b60650a7dd41](https://qiita.com/sya-ri/items/f69f1489b60650a7dd41)