NegiLibについて
EasyMenu 7では、内部アーキテクチャの刷新に伴い、UIの描画処理を独立した描画基盤ライブラリ NegiLib へ分離しました。
このページでは、EasyMenuにおけるNegiLibの役割と、他プラグインからEasyMenuを操作するための開発者向けAPIについて解説します。
なぜ描画処理を分離したのか?
従来のメニュープラグインは、メニュー定義(YAML)とMinecraftのインベントリ操作コードが密結合していました。
EasyMenu 7では、以下の明確な役割分担を行っています。
EasyMenu 7 = YAMLの解釈、メニュー構造・意味論、アクション、条件判定、状態管理
NegiLib 1 = 画面描画、セッション管理、Foliaスケジューラー、サーバー環境の差異吸収
役割分担によるメリット
- 単一設定からマルチUIへの対応: EasyMenuは「何を表示するか」だけを決定し、NegiLibが「現在のサーバー環境でどう描画するか」を担当するため、同じYAML設定のままインベントリGUIにもNative Dialogにも自動対応できます。
- 高い堅牢性とパフォーマンス: NegiLibがFoliaのリージョンスケジューラー上で安全に非同期処理とメインスレッド処理を調停するため、Paper、Purpur、Foliaのいずれでもスレッドセーフかつ高速に動作します。
- 将来の拡張性: 将来新しいクライアント画面形式が登場した場合でも、EasyMenuの設定や構文を変更することなく対応できます。
開発者向け連携API (EasyMenuApi)
他のプラグインからEasyMenuのメニューをプレイヤーに開かせたい場合は、EasyMenuApi を利用します。
公開されているのは org.mituba01.easymenu.api パッケージの EasyMenuApi インターフェース、EasyMenuProvider、MenuOpenResult だけです。それ以外のクラスは内部実装です。
依存関係
org.mituba01:easymenu の配布先(Mavenリポジトリ)はこのWikiでは案内していません。ローカルでビルドした EasyMenu-7.0.2.jar などを provided で参照してください。
EasyMenu-7.0.2.jar はサーバーに入っているものが実行時に使われるため、自分のプラグインにAPIクラスを同梱(shade)してはいけません。また、自分のプラグインの plugin.yml に depend: [EasyMenu](または softdepend)を書き、読み込み順を保証してください。
<dependency>
<groupId>org.mituba01</groupId>
<artifactId>easymenu</artifactId>
<version>7.0.2</version>
<scope>provided</scope>
</dependency>
メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
open(Player, String menuId) | CompletionStage<MenuOpenResult> | メニューを開く処理を始め、結果が出た時点で完了する非同期メソッドです。/submenu と同じ条件(open-when など)が適用されます。 |
isMenuLoaded(String menuId) | boolean | そのメニューが、現在のメニュー定義キャッシュに載っているか。 |
reload() | CompletionStage<Boolean> | 設定を再読み込みします。候補が検証で拒否された場合は false で完了します。 |
EasyMenuProvider.get() は Optional<EasyMenuApi> を返します。EasyMenuが無効なときは空です。
MenuOpenResult の種類
| 値 | 意味 |
|---|---|
OPENED | メニューが画面に表示された。 |
NOT_FOUND | メニューIDに対応する定義がない(または初期化に失敗した)。 |
DENIED | メニューはあるが、open-when の条件がこのプレイヤーを拒否した。 |
PRESENTATION_UNAVAILABLE | 要求された表示方式(native-required など)を満たす描画方式がなかった。 |
RENDER_FAILED | 選ばれた描画方式が、開く途中で失敗した。 |
SUPERSEDED | 新しいリクエストやリロードに置き換えられ、開かれなかった。 |
isSuccess() は OPENED のときだけ true を返します。DENIED と PRESENTATION_UNAVAILABLE では、プレイヤーにはEasyMenu自身が理由のメッセージを送ります。
Javaコードからの呼び出し例
import org.bukkit.entity.Player;
import org.mituba01.easymenu.api.EasyMenuProvider;
import org.mituba01.easymenu.api.MenuOpenResult;
public void openShopMenu(Player player) {
EasyMenuProvider.get().ifPresent(api ->
api.open(player, "shop").thenAccept(result -> {
if (!result.isSuccess()) {
getLogger().info("shop was not opened: " + result);
}
})
);
}
open は非同期なので、thenAccept の中はプレイヤーのスレッド(Foliaではリージョンスレッド)とは限りません。Bukkit APIを呼ぶ処理は、自分のプラグイン側で適切なスケジューラーへ渡してください。
isMenuLoaded が表すものisMenuLoaded は「プレイヤーが今そのメニューを開いているか」を調べるものではありません。メニュー定義がキャッシュ上にあるかだけを返します。
キャッシュは cache.submenu-expiry-seconds で期限切れになり、precache-submenus が false のときは使われるまで載りません。false が返ってもメニューが存在しないとは限らず、open は必要に応じて定義を読み込みます。
メニューの存在確認には使わず、open の結果(NOT_FOUND など)で判断してください。
open・isMenuLoaded・reload を持つ EasyMenuApi は、EasyMenu 7.0.2 で他プラグインから使うために公開されたインターフェースです。
将来のバージョン間での互換性は、このWikiでは保証していません。使用する際は、対象のEasyMenuバージョンで動作確認してください。