メインコンテンツまでスキップ

NegiLibについて

EasyMenu 7では、内部アーキテクチャの刷新に伴い、UIの描画処理を独立した描画基盤ライブラリ NegiLib へ分離しました。

このページでは、EasyMenuにおけるNegiLibの役割と、他プラグインからEasyMenuを操作するための開発者向けAPIについて解説します。


なぜ描画処理を分離したのか?​

従来のメニュープラグインは、メニュー定義(YAML)とMinecraftのインベントリ操作コードが密結合していました。

EasyMenu 7では、以下の明確な役割分担を行っています。

EasyMenu 7 = YAMLの解釈、メニュー構造・意味論、アクション、条件判定、状態管理
NegiLib 1 = 画面描画、セッション管理、Foliaスケジューラー、サーバー環境の差異吸収

役割分担によるメリット​

  1. 単一設定からマルチUIへの対応: EasyMenuは「何を表示するか」だけを決定し、NegiLibが「現在のサーバー環境でどう描画するか」を担当するため、同じYAML設定のままインベントリGUIにもNative Dialogにも自動対応できます。
  2. 高い堅牢性とパフォーマンス: NegiLibがFoliaのリージョンスケジューラー上で安全に非同期処理とメインスレッド処理を調停するため、Paper、Purpur、Foliaのいずれでもスレッドセーフかつ高速に動作します。
  3. 将来の拡張性: 将来新しいクライアント画面形式が登場した場合でも、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が無効なときは空です。

値意味
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バージョンで動作確認してください。