Minecraft Kotlinプラグイン開発 中級編 Part.4 コマンドの実行

## 初めに
今回はプレイヤーとしてマイクラのコマンドを実行する方法と
コンソールからコマンドを実行する方法を紹介します。

バニラのコマンドをある程度知ってる人であれば、
この方法を使うと自由度が格段に広がります。

:::note warn
この方法はコマンドを挟んで処理してる形でコマンドを経由させてる状態なので、
処理的にはこの方法を使わないほうが軽いため非推奨です。
今後自分でいろいろな構文を覚えたらコマンドの部分を自分で変えてみましょう。
今回紹介する方法はそれまでの応急処置的なものです！
:::

**前** → [中級編 Part.3 GUIのクリック検知](https://qiita.com/tooooowa/items/9df53fea8ced007765b4)
**次** → [番外編2 プラグインフォルダへ直接ビルドする方法](https://qiita.com/tooooowa/items/9df54031db9382109356)

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


## プレイヤーとしてコマンドを実行
<ins>[前回](https://qiita.com/tooooowa/items/0e03ed15504d9b253898)</ins>作成したGUIの中のクリック処理を一部変更します。

今回はダイヤモンドがクリックされた時に自分を10マス上にtpさせてみます。
具体的には"`/tp @s ~ ~10 ~`"というコマンドをプレイヤーから実行してみます。

```EventListener.kt
package com.github.tooooowa.tutorialplugin // ここは環境によって異なります

import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerJoinEvent

object EventListener: Listener {
    @EventHandler
    fun onJoin (event: PlayerJoinEvent) {
        event.joinMessage = "§e${event.player.name}がサーバーに参加しました。"
    }
    @EventHandler
    fun onInventoryClick (event: InventoryClickEvent) {
        if (TutorialPlugin.guiMap[event.whoClicked.uniqueId] == event.inventory) {
            event.isCancelled = true
            if (event.currentItem == null) return

            // ここの下の行に変数にプレイヤーを保存する処理を追加
            val player = Bukkit.getPlayer(event.whoClicked.name)

            // ダイヤモンドのときの処理 (ここも変更しました)
            if (event.currentItem!!.type == Material.DIAMOND) {
                player?.performCommand("tp @s ~ ~10 ~")
            }

            // エメラルドのときの処理
            if (event.currentItem!!.type == Material.EMERALD) {
                event.whoClicked.gameMode = GameMode.SURVIVAL
            }

        }
    }
}
```
クリエイティブモードに変更する処理を削除して、
プレイヤーを変数に保存する処理と
その変数に保存されているプレイヤーとしてコマンドを実行させる処理を追加しました。
```kotlin
val player = Bukkit.getPlayer(event.whoClicked.name)
```
この1行で変数`player`にクリックしたプレイヤーを入れています。

プレイヤーを指定する方法で、`event.whoClicked`をゲームモード変更には使用していますが
プレイヤーとしてコマンドを実行するにはプレイヤーの型の変数じゃないと行けないので
このように`Bukkit.getPlayer()`を使用してプレイヤーを変数に取得しています。

関数`Bukkit.getPlayer()`は引数「`()`の中」に名前もしくはUUIDを入れて使用します。
今回は`event.whoClicked.named`でクリックした人の名前を入れています。

```kotlin
player?.performCommand("tp @s ~ ~10 ~")
```
この文でプレイヤーとしてコマンドを実行しています。
この関数では引数の中に実行させたいコマンドを記入します。
**※最初に付ける/は省略します**

普段つける `.` とは違い、ここでは `.?` を使用しています。
これはKotlinの機能で変数が空からでもnullとして実行するという意味です。
今回はplayerが空のことはないので、ビルド時のエラーを防ぐために `?.` を付けます。

基本的には、IntelliJ IDEA のコードの赤い下線でエラーが出るので、
それを見ながら色々修正しています。

### デバッグ
これでクリックすると以下の画像のように出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/8b28778d-a8f0-50d7-82da-da598ef4d975.png)

:::note warn
この方法だとプレイヤーから実行することになるので
ログは出ますしそのプレイヤーがコマンドを実行する権限がないと実行できません
:::


## コンソールとしてコマンドを実行
今度はコンソールとしてプレイヤーにエメラルドを付与するコードを追加してみます。
具体的には `/give [プレイヤー名] emerald` を実行します。
プレイヤー名を使う所ではさっき使った`player`変数を再び使用します。

エメラルドのクリック時のイベントを変更します。
```EventListener.kt
package com.github.tooooowa.tutorialplugin // ここは環境によって異なります

import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerJoinEvent

object EventListener: Listener {
    @EventHandler
    fun onJoin (event: PlayerJoinEvent) {
        event.joinMessage = "§e${event.player.name}がサーバーに参加しました。"
    }
    @EventHandler
    fun onInventoryClick (event: InventoryClickEvent) {
        if (TutorialPlugin.guiMap[event.whoClicked.uniqueId] == event.inventory) {
            event.isCancelled = true
            if (event.currentItem == null) return
            val player = Bukkit.getPlayer(event.whoClicked.name)

            // ダイヤモンドのときの処理
            if (event.currentItem!!.type == Material.DIAMOND) {
                player?.performCommand("tp @s ~ ~10 ~")
            }

            // エメラルドのときの処理 (ここを変更しました)
            if (event.currentItem!!.type == Material.EMERALD) {
                Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "give ${player?.name} diamond")
            }

        }
    }
}
```
追加したのは以下の一文のみです。

```kt
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "give ${player?.name} diamond")
```
`Bukkit.dispatchCommand( 引数1 , 引数2 )`では引数1でコンソールを取得して、
引数2で実行させたいコマンドを記入します。

引数1のコンソールの部分は常に`Bukkit.getConsoleSender()`固定で大丈夫です。
引数2ではプレイヤーとして実行のときと同じく **初めの / は省略します**

### デバッグ
実行してみるとダイヤモンドが1つ貰えます。

この画像のようにOPを持っている場合はチャットにログが出ます。
プレイヤーとして実行とは違いこの場合は
プレイヤーに `/give` コマンドを使う権限がなくても正常に動きます。

うまくこれらを使い分けて行きましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682428/b87a0eb2-0f90-394c-87d2-0b70ca79a425.png)

## 終わりに
今回はプレイヤーとして、コンソールとしてコマンドを実行する方法を学習しました。

基本コマンドを知っている方であれば
これで自分の作りたいものを作れる段階に近づくと思うので活用していきましょう！

また、これから色んな構文を学習していき少しずつコマンドから
プラグインの機能自体で完結出来るようにしていきましょう。

次回の記事は権限に関してです。お疲れ様でした！

**前** → [中級編 Part.3 GUIのクリック検知](https://qiita.com/tooooowa/items/9df53fea8ced007765b4)
**次** → [番外編2 プラグインフォルダへ直接ビルドする方法](https://qiita.com/tooooowa/items/9df54031db9382109356)

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

## 参考
[https://www.youtube.com/watch?v=hPzg4tXcu5I](https://www.youtube.com/watch?v=hPzg4tXcu5I)
[https://www.spigotmc.org/threads/run-console-command.82908/](https://www.spigotmc.org/threads/run-console-command.82908/)