Nukkit in Kotlin

# Nukkit in Kotlin
PMMP開発者且つNukkitに初めて挑戦する人、NukkitやってたけどKotlinとかGradleとか使ってみたい人向けです。マサカリ待ってます。

KotlinとGradleでNukkitプラグインの入門です。
最終的な目標はKotlinとGradleを習得しつつ、最低限プラグインを自由に書いていけるようになること。

## KotlinとGradleを選んだ理由

### Kotlin
2017年からAndroidの公式言語として採用されたKotlin。開発はJetBrainsが行っており、その言語機能の威力は~~もう少し頑張ってほしい~~絶大といっても過言でないでしょう。そんなKotlinを使ってJavaでは実現できない高速でストレスレスな開発を体験して、今後のプログラミングライフを充実させていってほしいです。Kotlin布教。

### Gradle
Mavenがクソの一言に尽きる。

## Kotlinのメリットは？
JVM上で動作するのでJavaの資産を余すことなく使えます。また、モダンな記法で文章量を減らし、素早く直感的な開発ができます。一度使えばJavaにはもう戻れません。

## Gradleのメリットは？
こちらもJVM上で動作するGroovyを用いて、普段書いているプログラミングの要領でビルドスクリプトを書くことができます。また、Kotlinを使ってビルドスクリプトを書く方法もあり、今回はこちらで書いていきます。

## 準備
比較的導入は簡単なのでここでは詳しく書きません。

* Nukkit
 * 導入方法はここでは省略します。
* 開発環境
 * 僕はIntelliJ IDEAを使っています。お好きにどうぞ。IntelliJ IDEAはもとからGradleがバンドルされていますが、他のIDEにはプラグインとして提供されているものもあるので各自インストールをしてください。

ここからはIntelliJ IDEA上でプロジェクトを作成していきます。

### プロジェクトの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271071/b38f9e19-f190-8c7f-d8c1-a0ef0583fade.png)

新規プロジェクトの作成を押し、次へ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271071/5c09a14f-3e6c-2b7d-e801-c9f3b9ae8426.png)

Gradleの項目からKotlin DSL ビルド・スクリプトとKotlin/JVMを選択し、次へ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271071/5fc7111a-a947-d883-a18d-c61865189d46.png)

名前・ロケーション・グループID・アーティファクトID・バージョンを適当に入力し、完了

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271071/212d74d6-c4d2-8f93-4a0c-745728bcecf3.png)

この画面が表示されたら前準備は終了です。

### ディレクトリの構成

ディレクトリの構成は下記のようになっています。各プラグインに合わせて適宜変更してください。

```
Sample/
  ├build.gradle.kts
  ├settings.gradle.kts
  ├src/main/kotlin/com/example/sampleSamplePlugin.kt
  ├gradle
  ├gradle.properties
  ├gradlew
  └gradlew.bat
```

## 早速書いていこう
#### とは言いましたが
> PMMP開発者且つNukkitに初めて挑戦する人、NukkitやってたけどKotlinとかGradleとか使ってみたい人向けです。

とある通り、ある程度プラグインの書き方を知っている方向けです。初めてプログラミングを行う方やプラグインを作ったことがない方は「Nukkitプラグインの作り方」等で検索していただけると丁寧に解説している記事がいくつかあるので、そちらを参考にしていただければ幸いです。haniokasaiさんの記事がとても分かりやすいです。

## Gradle
ここでは詳しいことは書きません。使いたいライブラリを検索するとだいたいGradleでの導入方法が載っています。XMLと違ってさっぱりした記述ですし、最悪コピペでも何となく意味が分かります。

画面左にある`build.gradle.kts`をクリックして開き、以下のように編集してください。


``` kotlin:build.gradle.kts
plugins {
	kotlin("jvm") version "1.3.60"
	id("net.minecrell.plugin-yml.nukkit") version "0.3.0"
	id("com.github.johnrengelman.shadow") version "5.2.0"
}

group = "com.example"
version = "1.0-SNAPSHOT"

repositories {
    jcenter()
    maven {
        url = uri("https://repo.nukkitx.com/main/")
    }
}

dependencies {
	implementation(kotlin("stdlib"))
	compileOnly("cn.nukkit:nukkit:1.0-SNAPSHOT")
	testCompileOnly("cn.nukkit:nukkit:1.0-SNAPSHOT")
}

tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    
}

nukkit {
    name = "Sample"
    main = "com.example.sample.SamplePlugin"
    api = listOf("1.0.9")
    authors = listOf("your name")
}
```

Jarファイルをビルドするにはターミナルから`gradlew shadowJar`を起動すると`build/lib`フォルダに成果物が生成されます。

## プラグイン本体

まず、`SamplePlugin.kt`ファイルを作成します。今回は`com.example.sample`パッケージを追加した後。そのパッケージにSamplePlugin.ktを作成してください。
src/mainフォルダを右クリックしてメニューを表示させたのち、追加->パッケージを選択するとパッケージを追加できます。パッケージはほぼフォルダと同じ仕組みで、階層は`/`の代わりに`.`を使って表現します。よほどの例外がない限りはパッケージ名とフォルダ名の名前はすべて小文字にして合わせます。

### SamplePlugin.kt

まず初めに起動時にコンソールに「Hello, Wrold」と表示させます。

``` kotlin:SamplePlugin.kt
package com.example.sample    //名前空間

import cn.nukkit.plugin.PluginBase

class SamplePlugin: PluginBase() {    //クラス宣言
    val greetMessage = "Hello, world!"    //メンバ変数

    override fun onEnable() = logger.info(greetMessage)    //メソッド
}

```

#### 継承

Javaでは、`extends`を使って継承を行ってきましたが、Kotlinでは`:`を使って継承します。
継承するクラスを書くときは`クラス名()`、ここでは`PluginBase()`を使います。

#### 変数

変数名の前に`val`または`var`を書いて変数の宣言をします。`val`は一度宣言すると値の変更が不可能な不変(immutable)、`var`は宣言後も値の変更が可能な可変(mutable)となっています。
Kotlinは戻り値の型から変数の型を特定する型推論という機能を備えており、基本的に型を省略して記述量を減らすことができます。`val hoge: Hoge`や、`var fuga: Fuga`等、変数名の後に`: <型名>`と書くことで型の明示的な宣言ができます。
また、Kotlinは基本的にnullを代入することはできないnull安全な設計になっており、型名の後ろに`?`つけることでnullを代入できるようになるnull許容型になります。null許容型は元の型とは別の型となっており、null許容型からは元の型のメンバ変数やメソッドは呼び出せません。if式でnullではないことを明示し元の型にキャストしたり、

```kotlin
var hoge: Hoge? = Hoge()    //nullを返すかもしれない
hoge?.fuga()    //nullの場合はfuga()は呼び出されない。
```

上記のようにドット演算子の前に`?`を付けることでnullの場合はその文は無視、null出ない場合はそのまま元の型にキャストして呼び出しを続行することができます。

#### メソッドのシグニチャ

`fun <関数名>(): <戻り値の型>`です。
また戻り値がないメソッドではKotlinでは`void`の代わりに`Unit型`になり、省略することができます。

#### `{}`

関数が一文のときは`{}`を省略して代わりに`=`を使って書けるようになっています。
勿論二文以上あるときはいつも通り`{}`を使って書いていきます。

#### 文末の`;`

文末のセミコロンという文化はなくなりました。
結構セミコロンレスというのに慣れない方が多いそうですが、タイプ量がゴリゴリ減るので快適です。

#### logger.info()

`logger`がメンバ変数みたいになっていますが、メソッドです。
KotlinではgetXX()、setXX()をすべて見た目がメンバ変数になるように変換してくれます。例えば、getHoge()メソッドがあれば、hogeでメソッドを実行して返り値が返却されます。

## Jar生成

プラグインが完成したら、ターミナルで`./gradlew shadowJar`を打ち込んでください。`build/libs`にプラグインが生成されています。
生成し終わったらいつも通りpluginsフォルダに配置すればプラグインが読み込まれるようになります。

## まとめ

KotlinとGradleを使うことでこれまでの環境を改善することができ、開発スピードが爆速になります。
JavaとMavenを使っても実現不可能ではありませんが、やはり簡潔さというのは開発状況はもちろん、モチベーションにもつながります。ぜひこの機会にKotlinとGradleを使ったNukkitプラグインを作ってみてはいかがでしょうか？

~~気が向いたらKotlinを最大限に使ったプラグイン開発の仕方を記事にまとめようかと思います。~~[#2](https://qiita.com/UramnOIL/items/216a8698f63267f3bb78)ができました。