KotlinでBukkitプラグインを書く
この記事は 木更津高専 Advent Calendar 2024 参加記事です。
前 → 920MHzに比べると国技館のBluetoothはカスや by @kokastar
次 → 今年もプロ研が学園祭Webサイト制作をした話 by @naotiki
はじめに
Kotlinの公式ドキュメントにあるGet started with Kotlinでは、Kotlinの特徴について以下のように書いてあります。
Kotlin is a modern but already mature programming language designed to make developers happier. It's concise, safe, interoperable with Java and other languages, and provides many ways to reuse code between multiple platforms for productive programming.
Kotlinの動作するプラットフォームの1つにJava仮想マシン(JVM)があるので、Javaの代わりにKotlinを使用することができます。
さらに、Javaのコードで定義されたメソッドをKotlinで呼び出したり、逆にKotlinのコードで定義されたメソッドをJavaで呼び出すこともできます。
そこで、この記事では、通常Javaで記述されるBukkitプラグインを、Kotlinで書くにあたっての特徴や留意点をまとめたいと思います。
注意点
今回の記事では、Kotlinでプラグインを書く際のポイントについてまとめるため、プラグインの作り方については触れません。
プラグインの作成については、以下のような記事が参考になります。必要ならば併せてお読み下さい。
環境
- IntelliJ IDEA 2024.3
- Kotlin 2.1.0
- Minecraft Development 2024.3-1.8.2
プロジェクトの作成
Minecraft Developmentの導入
ランチャーのPluginsを開き、Minecraft Development
をインストールします。
Marketplaceでminecraftと検索すれば、大抵最も上位に表示されます。
新規プロジェクトの作成
ランチャーのProjectsの中にあるNew Project
を開き、GeneratorsからMinecraft
を選択します。
Plugin Name
、Main Class
、Artifact ID
、Group ID
はJavaで作成するときと同様に入力します。
Language
は、今回使用するKotlin
を選びます。
プログラミング
以下のページに書いてある内容が全てですが、特にプラグインを作成するときに登場するものを紹介します。
ゲッターとセッター
Java上で定義されたゲッターとセッターは、Kotlin上ではプロパティとして表現されます(synthetic properties)。
したがって、以下のJavaとKotlinのコードは同様に動作します。
package org.example.samplePlugin;
import org.bukkit.plugin.java.JavaPlugin;
public final class SamplePlugin extends JavaPlugin {
@Override
public void onEnable() {
// Plugin startup logic
saveDefaultConfig();
final FileConfiguration config = getConfig();
final String hoge = config.getString("fuga.piyo");
getLogger().info("Enabled samplePlugin");
}
@Override
public void onDisable() {
// Plugin shutdown logic
getLogger().info("Disabled samplePlugin");
}
}
package org.example.samplePlugin
import org.bukkit.plugin.java.JavaPlugin
class SamplePlugin : JavaPlugin() {
override fun onEnable() {
// Plugin startup logic
saveDefaultConfig()
val hoge = config.getString("fuga.piyo")
logger.info("Enabled samplePlugin")
}
override fun onDisable() {
// Plugin shutdown logic
logger.info("Disabled samplePlugin")
}
}
メソッドの型
Bukkitのオブジェクトを返すメソッドには、必ず@NotNull
もしくは@Nullable
のアノテーションがあります。
このうち、@NotNull
アノテーションがあるメソッドはT
を、@Nullable
アノテーションがあるメソッドはT?
を返します。
package org.example.samplePlugin
import org.bukkit.configuration.file.FileConfiguration
import org.bukkit.plugin.java.JavaPlugin
import java.io.InputStream
class SamplePlugin : JavaPlugin() {
override fun onEnable() {
// Plugin startup logic
// @NotNull public FileConfiguration getConfig()
val hoge: FileConfiguration = config
// @Nullable public InputStream getResource(@NotNull String filename)
val fuga: InputStream? = getResource("fuga.json")
}
override fun onDisable() {
// Plugin shutdown logic
}
}
イベントの自作
イベントを自作するときには、以下のようにgetHandlers()
、getHandlerList()
を実装する必要があります。
getHandlerList()
はEventクラスに含まれていないものの、Javadocには必ず実装するように書いてあります。
All events require a static method named getHandlerList() which returns the same HandlerList as getHandlers().
ビルドは通ってしまいますが、実装しないと実行時に落ちてしまいます。
private static final HandlerList handlers = new HandlerList();
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
ところが、Kotlinにはstaticメソッドがありません。
一応、Companion objectsを用いれば、クラスレベルの関数とプロパティを定義することができます。 しかし、これは本当のstaticメソッド(とフィールド)では無いので、Java側はstaticメソッドと同じように呼び出すことができません。
そこで、@JvmStatic
アノテーションを利用します。
@JvmStatic
アノテーションを入れると、Companion objects内で定義された関数をstaticメソッドとして生成できます。
すなわち、自作イベントは以下のように記述されます。
package org.example.samplePlugin
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
class SampleEvent(): Event() {
override fun getHandlers(): HandlerList {
// 変数名がhandlersのときは
// SampleEvent.handlersとしないと循環参照になる
return handlerList
}
companion object {
@JvmStatic
private val handlerList = HandlerList()
@JvmStatic
fun getHandlerList(): HandlerList {
return handlerList
}
}
}
ライブラリの追加
他のGradleを用いた開発と同様に、build.gradle.kts
を編集することでライブラリを追加することができます。
変更したら、右上に象のマークが現れるので、それをクリックして変更を反映します。
ビルド
サイドバーにあるGradleをクリックして、その後[プラグイン名]/Tasks/build/build
(画像右側の選択部分)をダブルクリックしてビルドします。
ビルドが完了すると、プロジェクト内にbuild
というディレクトリが作成され、その中のlibs
の中に[プラグイン名]-[バージョン].jar
と[プラグイン名]-[バージョン]-all.jar
が生成されます。
allの付いている方には依存ライブラリも含まれている(所謂fat JAR)ので、原則こちらを使うようにしましょう。
さいごに
モダンな言語を利用する方が、開発も非常にやりやすく、そして恐らく安全です。
Minecraftサーバーのプラグインを開発する際は、Kotlinを使うことも検討してみてはいかがでしょうか。
Discussion