【Kotlin+Spigot】2.1 参加・退出メッセージを変更する

## 0. 初めに
`build.gradle` や `plugin.yml` の設定は終わらせた前提で進めます。
[**プロジェクトを作成する**](https://qiita.com/sya-ri/items/1ecccdba38fd3260f5ff) を参考にメインクラスを作るまで終わらせておいてください。

## 1. 処理の流れ
今回の内容はいたって簡単です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/4a6e381d-5485-a14a-3887-96b0b0c8e0ab.png)
イベントってこんなもんなんです。とても簡単で便利なので色々やってみましょう！

## 2. イベント登録を理解する
**PlayerJoinEvent** を使う場合のプログラムを追って理解していきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/9829a891-7464-3c1e-cdf5-1d51034cc738.png)

```EventListener.kt
class EventListener: Listener {

}
```
メインクラスとは別に、**イベントを受け取るためのクラス** を作成しておきます。
(※`class` と `object` の違いは 後の記事で解説します。)
メインクラスの時は **JavaPlugin()** というものをクラス名の後に書きました。
**イベントを受け取るためのクラス** では **Listener** というものをクラス名の後に書きます。
後ろに書くことを **継承** といいます。継承の目的は、クラスに対して定義付けをすることです。
「イベントを受け取るためのクラス」や「プラグインのメインクラス」であることを定義しています。

しかし、これだけだとイベントを受け取る器が出来ただけです。実際にイベントを受け取るためには

```kotlin
server.pluginManager.registerEvents(EventListener(), this)
```
これを呼び出す必要があります。`onEnable` に書いておけばいいでしょう。
`registerEvents` を日本語で言うと「イベントを登録する」です。

```Main.kt
class Main: JavaPlugin() {
    override fun onEnable() {
        server.pluginManager.registerEvents(EventListener(), this)
    }
}
```

あとは実際のイベントを書くだけです。

```EventListener.kt
class EventListener: Listener {
    @EventHandler
    fun on(e: PlayerJoinEvent){
        /* イベントが呼び出されたときの処理を書く */
    }
}
```
`@EventHandler` をつけるとイベントの関数だと定義できます。
逆に言うと、忘れると何も起きません。
また、関数の引数にイベントの種類を書きます。今回であれば、`PlayerJoinEvent` です。
関数の引数については後で解説します。
コメントにある通り、中括弧の中に呼び出されたときの処理を書きます。

## 3. メッセージを変更する
中括弧の中に「メッセージを変更」の処理を書きましょう。

```EventListener.kt
class EventListener: Listener {
    @EventHandler
    fun on(e: PlayerJoinEvent){
        val p = e.player
        e.joinMessage = "${p.displayName} がサーバーに入りました"
    }
}
```

`val` というのは変数です。
**「変数」は「値を保存するもの」** です。
`e.player` で取得できるのはサーバーに入ってきたプレイヤーです。
一時的に変数として保存しておくことで、取得にかかる時間や、入力文字数が減ります。
それだけ？と思うかもしれませんが、前者の方はとても重要なことです。
変数として値を保存しておくことを意識してやってみましょう。
`p.displayName` で取得できるのはプレイヤーの名前です。
`${変数}` と書くことで文字列の中に変数の値を埋め込めることができます。
`e.joinMessage` に文字列を代入することでメッセージが変更できます。
**「代入」は「値を置き換える動作」** だと思ってください。

この状態で .jar を生成してサーバーで試してみましょう。

こんな感じにログインメッセージが変わっていたら成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/a267ba94-9444-5ab2-8c2f-7d2eeecc74aa.png)

## 4. メッセージに色を付けてみる
「真っ白な字なんて・・・」って思っている方もいるかもしれません。
色を変えるだけで見栄えがぐっと良くなります。
こんな感じにしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/69e10e71-47fb-d415-4700-37824e1a6128.png)

基本は簡単です。`§` を使ってカラーコードを書けばいいだけです。

```kotlin
e.joinMessage = "${p.displayName} がサーバーに入りました"
```
`§b` と `§f` を書き足します。しかし、これはやらなくていいです。
`§` というのは `セクション` と入力すると変換できるんですが問題があります。

```kotlin
e.joinMessage = "§b${p.displayName} §fがサーバーに入りました"
```

セクションには二つの問題があります。
・入力しにくい
・マイクラのチャットで書けない
だから普通は `&` をセクションの代わりに使います。
でもただ置き換えるだけでは出来ません。
「`&` を `§` に置き換える」そういう処理が必要です。

```kotlin
e.joinMessage =  ChatColor.translateAlternateColorCodes('&', "&b${p.displayName} &fがサーバーに入りました")
```

いきなり長くなりました。
「セクションには入力しにくいという問題がある。」とか言っておきながら、もっと面倒くさくなったと思いませんか？
最低でも私は思います。であれば、**関数** として定義しておけばいい。そういう発想になります。
関数を作る目的は、「長い処理・面倒な処理をまとめる」といったことが多いです。
積極的に 処理のパーツ分け をしていきましょう。

さて、「文字列を色付き文字列に変換する」関数の処理の流れを考えてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/8c69dee8-b575-9938-0b68-22e1d4d752c0.png)
この図を元に言い換えると、
「文字列を一つ受け取って、何らかの処理をして、文字列を一つ返す」です。
もっとプログラムっぽくいうと
「文字列を引数とする 関数で 戻り値は文字列」といった感じですかね。
実際にプログラムにしてみましょう。

```kotlin
    fun getColored(text: String): String {
        return ChatColor.translateAlternateColorCodes('&', text)
    }
```

分解して見ていきましょう。
・**`fun`** function の略で「関数」という意味です。

・**`getColored`** 関数の名前です。分かりやすい名前を付けるように心がけましょう。
今回は「色付き文字列を取得する」関数なので `get: 取得` `Colored: 色付き` としています。
関数名の始まりは `get` や `is` など動詞から始まると分かりやすいです。
その後に別の英単語を繋げますが、頭文字は大文字にします。
一つ目の単語の頭文字は小文字。それ以降は大文字 という名前の付け方を `camelCase` と言います。

・**`(text: String)`** 関数の引数です。関数が受け取る値です。
複数受け取ることも可能ですが、今回は文字列(String)一つのみです。

・**`: String`** 関数の戻り値です。関数が返す値です。

・**`return`** ここでその関数を終了させる。ということです。
もしも、戻り値があるのであれば、その値をその後ろにつけましょう。

・**`ChatColor.translateAlternateColorCodes('&', text)`**
`&` を `§` に置き換える関数です。`text` というのは引数に書いてあるものです。

分解してみると分かりやすいですね。分解できると分かりやすいというメリットだけではないんです。
例えば、受け取る値を一つ増やす。なら 引数の部分に足せばいいんだ。といったように対応がしっかりと出来ます。プログラムを分解できるということはプログラムを理解しているということだと私は思います。

この関数を実際に実装してみましょう。

```EventListener.kt
class EventListener: Listener {
    @EventHandler
    fun on(e: PlayerJoinEvent){
        val p = e.player
        e.joinMessage = getColored("&b${p.displayName} &fがサーバーに入りました")
    }

    fun getColored(text: String): String {
        return ChatColor.translateAlternateColorCodes('&', text)
    }
}
```
こんな書き換えになると思います。さぁこの調子で Quit メッセージも変えてみましょう！

```EventListener.kt
class EventListener: Listener {
    @EventHandler
    fun on(e: PlayerJoinEvent){
        val p = e.player
        e.joinMessage = getColored("&b${p.displayName} &fがサーバーに入りました")
    }

    @EventHandler
    fun on(e: PlayerQuitEvent){
        val p = e.player
        e.quitMessage = getColored("&b${p.displayName} &fがサーバーを出ました")
    }

    fun getColored(text: String): String {
        return ChatColor.translateAlternateColorCodes('&', text)
    }
}
```
とても簡単ですね。しかし、まだ終わりではありません。
`getColored` という関数。これからも使うことがありそうなくらい便利な関数ですよね。
使いたくなったらそのクラス毎に実装するのも面倒なので、`Util` みたいなクラスを定義しましょう！
いつものように新規ファイルで `Object` を `Util` という名前で作成！
以下のようにしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/09eb3965-59da-5774-82b8-c824b52497e7.png)
`getColored` はこちらに移動しましょう。

```Util.kt
object Util {
    fun getColored(text: String): String {
        return ChatColor.translateAlternateColorCodes('&', text)
    }
}
```

`EventListener` の方から `getColored` を消してしまったので
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628547/9d599a0a-6528-29ac-6eb8-295e7e3d86cd.png)
赤くなっていると思います。これまで同様、importしましょう。

3つのファイルが出来たところで今回は終了です。お疲れ様でした。
退出メッセージは自分では見えないのでテストがしにくいかもしれませんが、
参加メッセージと同じように書いていれば問題ないでしょう。

## リンク
### [次の記事に進む](https://qiita.com/sya-ri/items/f69f1489b60650a7dd41)
### [目次に戻る](https://qiita.com/sya-ri/items/bc7eb01ed687b9ff9566#%E7%9B%AE%E6%AC%A1)