MinecraftでCitizensを使ったプラグインを作成する

# Citizensとは

<img src="http://wiki.citizensnpcs.co/images/1/1b/Wordmark.png"/>

https://wiki.citizensnpcs.co/Citizens_Wiki

Minecraft Spigotサーバー上でNPCを導入するプラグインです。

プラグイン単体でも使うことができますが、今回は自作のプラグインからCitizensの機能を使う方法を紹介します。

# 導入

plugin.ymlのdependにCitizensを追加します

```plugin.yml
name: SamplePlugin
version: @version@
api-version: 1.13
main: sample.sampleplugin
depend: [Citizens]
```

build.gradleにCitizensのライブラリを追加します

```build.gradle
repositories {
    //....
 
    maven {
        name = 'citizens'
        url = 'http://repo.citizensnpcs.co/'
    }
}

//....

dependencies {
    //....

    compile 'net.citizensnpcs:citizensapi:2.0.25-SNAPSHOT'
    compile('net.citizensnpcs:citizens:2.0.25-SNAPSHOT') {
        exclude group: 'org.bstats', module: 'bstats-bukkit'
    }
}
```

# NPCの作成

## CitizensAPIを使ってNPCを作成

```kotlin
import net.citizensnpcs.api.CitizensAPI
import net.citizensnpcs.api.npc.NPC
import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.EntityType

fun spawnNpc(location: Location, npcName: String, skin: String): Entity {
    val npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "dummy").apply {
        isProtected = false
        data().set(NPC.PLAYER_SKIN_UUID_METADATA, skin)
        data().set(NPC.PLAYER_SKIN_USE_LATEST, false)
        name = npcName
    }
    npc.spawn(location)
    return npc.entity
}
```

`CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "dummy")`を使ってNPCを作成できます。
`data().set(NPC.PLAYER_SKIN_UUID_METADATA, skin)`で`skin`にプレイヤー名を指定すると、指定したプレイヤーのスキンが反映されます。
`name`で表示されるNPCの名前を指定します。

## Traitの指定

上記で作成したNPCはただ立っているだけで何もしません、そこでプレイヤーが近づいたらプレイヤーの方を向くようにします。
CitizensではTraitというクラスを追加して、NPCの振る舞いを定義します。

```kotlin
import net.citizensnpcs.api.CitizensAPI
import net.citizensnpcs.api.npc.NPC
import net.citizensnpcs.trait.LookClose
import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.EntityType

fun spawnNpc(location: Location, npcName: String, skin: String): Entity {
    val npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "dummy").apply {
        isProtected = false
        data().set(NPC.PLAYER_SKIN_UUID_METADATA, skin)
        data().set(NPC.PLAYER_SKIN_USE_LATEST, false)
        addTrait(LookClose::class.java)
        getTrait(LookClose::class.java).lookClose(true)
        name = npcName
    }
    npc.spawn(location)
    return npc.entity
}
```

Citizensに標準で入ってくるLookCloseというTraitを追加しました。これにより、NPCをがプレイヤーの方を見るようになります。

## Traitの作成

Traitは独自に作ることができます。

```RandomTrait.kt
import net.citizensnpcs.api.trait.Trait
import org.bukkit.Location
import java.util.*

class RandomTrait : Trait("random") {
    override fun run() {
        val entity = npc.entity ?: return
        val rand = Random().nextInt(100)
        if (rand < 2) {
            if (entity.isOnGround && entity.velocity.length() <= 0.1) {
                val location = randomLocation(entity.location, 5.0, 5.0, 5.0)
                npc.navigator.setTarget(location)
            }
        }
    }

    private fun randomLocation(baseLocation: Location, x: Double, y: Double, z: Double): Location {
        val i = (Random().nextDouble() * 2 - 1) * x
        val j = (Random().nextDouble() * 2 - 1) * y
        val k = (Random().nextDouble() * 2 - 1) * z
        return baseLocation.clone().add(i, j, k)
    }
}
```

上記はランダムな方向へ移動するTraitです。
Citizensは毎TickごとにTraitの`run()`を実行する仕組みになっています。

```kotlin
fun spawnNpc(location: Location, npcName: String, skin: String): Entity {
    val npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "dummy").apply {
        isProtected = false
        data().set(NPC.PLAYER_SKIN_UUID_METADATA, skin)
        data().set(NPC.PLAYER_SKIN_USE_LATEST, false)
        addTrait(RandomTrait())
        name = npcName
    }
    npc.spawn(location)
    return npc.entity
}
```

作成したTraitをNPCに追加することで反映されます

# サーバーへの導入
Spigotサーバーのpluginsディレクトリに以下を入れます

- Citizensプラグイン本体
- 作成したプラグイン


# 終わりに

Citizensを使うことで簡単にNPCをカスタマイズできるので興味がある方は試してみてください