MagmaCore 開発者ガイド
生成された Java リファレンスではクラス、メソッド、シグネチャを検索でき、各モジュールのソースバージョンとコミットも確認できます。
MagmaCore は利用側のプラグインに shade して組み込むライブラリです。単独のサーバープラグインではないため、プレイヤーが MagmaCore のプラグイン JAR をインストールできるかのように depend に記述しないでください。
依存関係とパッケージ化
現在の開発用座標は com.magmaguy:MagmaCore:2.2.0-SNAPSHOT です。これは MagmaGuy のリリースリポジトリに公開されており、スナップショットリポジトリには古い 1.x のスナップショットしかありません。スナップショットはバージョン文字列が同じでも内容が変わります。また、公開ビルドはプラグインのリリースごとに更新されるわけではないため、現在のプラグインに shade されている MagmaCore より古い場合があります。2026年10月5日に公開されたビルドには、後述の再起動不要の更新と対戦の API が含まれています。それより新しい未公開の変更に対してコンパイルするには、ライブラリ変更後に利用プラグインをビルドするの説明に従い、MagmaCore をソースからビルドして Maven Local に公開してください。再現可能なビルドが必要なら、解決されたアーティファクトを記録してください。
repositories {
maven("https://repo.magmaguy.com/releases")
}
dependencies {
implementation("com.magmaguy:MagmaCore:2.2.0-SNAPSHOT")
}
<repositories>
<repository>
<id>magmaguy-releases</id>
<url>https://repo.magmaguy.com/releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>MagmaCore</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
</dependencies>
この宣言で依存関係を解決します。最終プラグイン JAR に含めるよう、ビルドの shading タスクも設定してください。同じ連携要件を持つ既存の利用プラグインの relocation 規則に従い、パッケージ名を変える際は文字列によるリフレクション検索を確認します。配布物では org.luaj、org.reflections、javassist を com.magmaguy.shaded へ移動し、コンパイル時専用の javax.annotation クラスは含めません。
各プラグインはライブラリを個別に読み込めます。異なるプラグインのクラスローダーに属する同名の Java クラスは、別の型です。EliteMobs の Lua パワーサービスや位置レジストリのアダプターなど、明示的なプラグイン間 API を使ってください。他のプラグインが持つ非公開の MagmaCore オブジェクトを、自分の型へキャストしないでください。
モジュールと責任範囲
| モジュール | 責任範囲 |
|---|---|
core | プラグインのライフサイクル、設定、コマンド、メニュー、対戦、位置照会、Lua、Nightbreak コンテンツ、共通ユーティリティ |
nms:core | NMSManager、NMSAdapter、バージョン非依存の EasyMinecraftGoals インターフェース |
nms:v* | NMS インターフェースのサーバーバージョン別実装 |
dist | core と有効なアダプターを含む shaded 配布物 |
共通エンチャント、アイテム操作、アカウント処理、セットアップメニュー、カタログ、更新は core サービスの担当です。利用プラグインに動作を追加する際も、既存の担当コンポーネントを再利用してください。
プラグインのライフサイクル
最小構成のライフサイクルは、既存の利用プラグインと同じパターンにします。
package example;
import com.magmaguy.magmacore.MagmaCore;
import org.bukkit.plugin.java.JavaPlugin;
public final class CoreConsumer extends JavaPlugin {
@Override
public void onLoad() {
MagmaCore.createInstance(this);
}
@Override
public void onEnable() {
MagmaCore.onEnable(this);
}
@Override
public void onDisable() {
MagmaCore.shutdown(this);
}
}
この初期化はユーティリティオブジェクトの取得だけではありません。アカウント処理、共通コマンド、リスナー、一時ブロック対応も初期化します。createInstance(plugin, NightbreakPluginSpec) のオーバーロードでは、プラグイン固有の共通コマンド文面を指定します。
所有元プラグインを明示的に受け取るメソッドを優先してください。getInstance() は読み込まれたライブラリのシングルトンを指し、その要求元プラグインはインスタンス作成時に決まります。すべての利用プラグインの所有関係をそこから推測しないでください。
shutdown(plugin) は、そのプラグインのダウンローダー、コンテンツ更新、初期化、更新サービスの登録を解除し、さらに読み込まれたライブラリの共通ランタイムを終了します。レジストリの項目を 1 つ消すだけではありません。自分のプラグインの終了時に、自分が組み込んだライブラリへ呼び出します。連携をリセットする目的で他のプラグインのライブラリを終了しないでください。
createInstance は onLoad から呼び、他のプラグインがコンテンツをインポートする前に設定アーカイブの所有元を登録します。アーカイブ処理は対象プラグイン自身の shaded 実装で実行されます。自分の MagmaCore で他のプラグインの廃止規則を解釈しないでください。
段階的な起動には startInitialization を使い、非同期処理、同期処理、成功・失敗コールバックを渡します。非同期初期化を呼ぶ前に、該当する廃止設定をアーカイブします。Bukkit のワールド・エンティティ操作は同期段階に置いてください。長時間の非同期処理では段階の間に isShutdownRequested(plugin) を確認します。getInitializationState と isPluginReady で初期化マネージャーの状態を取得できます。
再起動不要のプラグイン更新
NightbreakPluginBootstrap.registerStandardCommands は、他の共通サブコマンドと一緒に applypluginupdate を登録します。このコマンドは、同じサーバーセッション内でプラグインを無効化し、JAR を置き換えて再度有効化することで、ダウンロード済みの更新を入れ替えます。そのため onDisable では、タスクのキャンセル、リスナーの登録解除、古いクラスローダーを生かし続けるあらゆる参照の解放を行う必要があります。メインクラスが com.magmaguy. 配下にあり、自分のプラグインに depend または softdepend している有効なプラグインは、一緒にリロードされます。それ以外のプラグインが自分のプラグインに依存している場合、入れ替えは拒否され、再起動を求めます。サーバー管理者側の手順は再起動せずに更新を適用するを参照してください。
プラグインの一部がその場でリロードできない場合は、更新チェックが始まる前に NightbreakPluginHotSwap.requireRestartForUpdates(plugin, reason) を呼び、NightbreakPluginUpdater.setAutoDownloadConfigDefault の第 2 引数に false を渡して、config.yml に applyPluginUpdatesWithoutRestart が表示されないようにします。それでも、依存先のプラグインが入れ替えられたときには、そのプラグインは現在の JAR のままリロードされます。NightbreakPluginUpdater.onPluginUpdateDownloaded(plugin, listener) は、検証済みの更新が update フォルダーに届いた後、ダウンロードスレッド上でリスナーを実行します。
NMS とパケットエンティティ
NMS が必要な場合だけ、com.magmaguy.easyminecraftgoals の NMSManager.initializeAdapter(plugin) で初期化します。アダプターに依存する処理の前に NMSManager.isEnabled() を確認してください。初期化が失敗したり、サーバーバージョンが未対応だったりする場合があります。
配布物には次のアダプター系統が含まれます。
| アダプター | Minecraft バージョン |
|---|---|
v1_21_R3 | 1.21.4 |
v1_21_R4 | 1.21.5 |
v1_21_R5 | 1.21.6, 1.21.7, 1.21.8 |
v1_21_R6 | 1.21.9, 1.21.10 |
v1_21_R7_spigot, v1_21_R7_paper | 1.21.11、Spigot と Paper は別実装 |
v26 | 26.1 と現在の 26.x アダプター系統 |
アダプターの選択は、将来のサーバーリリース全体の互換性を保証しません。NMSManager の実行時選択が、そのサーバーで読み込めるかを決めます。1.21.4 より前は現在のアダプター対象外です。
EasyMinecraftGoals はパケット専用エンティティ、その表示・操作の振り分け、移動・経路探索ヘルパーを管理します。通常のワールドエンティティではありません。担当 API を通じて管理し、アダプターがまだ使える間に自分が作成したオブジェクトを破棄してください。
位置と保護の照会
com.magmaguy.magmacore.location.LocationQueryRegistry は、isInAnyDungeon、isInAnyProtectedRegion、canBuild などのダンジョン・領域保護照会を提供します。
独自プロバイダーは registerDungeonLocator または registerProtectionProvider で登録し、所有元の無効化時に同じプロバイダーを登録解除します。レジストリには既存プラグイン用アダプターがあり、利用側で同じ MagmaCore クラスローダーを共有せずにプラグイン間のダンジョンプロバイダーを検出します。
操作に合った照会を使ってください。ダンジョンの外であることと、その場所で建築できることは同じではありません。Bukkit や保護プラグインに触れる照会はサーバースレッドで実行します。
対戦
対戦のライフサイクルは com.magmaguy.magmacore.match にあります。有効化時に MatchCore.enable(plugin) を一度呼び、Match を継承して、MatchSettings.builder() で作った MatchSettings をそのコンストラクターに渡します。サブクラスの構築が終わったら open() を呼びます。ゲームロジックは onJoin、onStart、onDeath、onLeave などの protected フックに記述します。MagmaCore.shutdown(plugin) は、そのプラグインに残っている対戦を破棄します。
コアは独自の Bukkit イベントを発行しません。設定に指定した MatchApi を呼び出すため、どのイベントを公開するかはプラグイン側で決められます。キャンセル可能なコールバックは、false を返すか例外を投げることでその段階を拒否します。各プラグインのコピーは自分の対戦だけを追跡します。プレイヤーのメタデータマーカー magmacore_match によって、プレイヤーがすでに対戦に参加していることを他のコピーに伝えます。
MatchSettings.builder().permission(...) は、参加に必要な権限を設定します。プレイヤーごとに判定したい場合、たとえばスタッフはその権限なしでも参加できるようにしたい場合は、hasJoinPermission(player) をオーバーライドします。死亡(LeaveReason.DIED)によって退出する参加者は、移動される前に体力が全回復するため、退出の過程で外れる最大体力ボーナスがあっても、満タンの比率が保たれます。対戦中のそのほかの退出ではダメージがそのまま残り、対戦が終了した時点でまだ参加しているプレイヤーは回復します。どちらの動作も、2026年10月5日に公開されたビルドより後に追加されたものです。
MatchInstance を含む com.magmaguy.magmacore.instance の旧対戦クラスは削除されました。InstanceProtector はそこに残っており、MagmaCore.enableWorldProtections(plugin) によって登録されます。
Lua の Mind ホスト
MagmaCore は、Lua で記述した Mind プログラムをホストプラグイン向けにコンパイルします。スクリプトの形式は行動プログラムで説明しています。ホストは独自の LuaMindModuleRegistry を作成し、openOwner(namespace) で自分の名前空間のオーナーを開き、オーナーの registerModule でモジュールを登録し、オーナーの validateProgram から LuaMindDefinition を取得します。定義の instantiate を呼ぶたびに、1 体のエンティティ用に、独自の Lua 環境を持つ新しいプログラムが構築されます。以下のフックは、2026年10月5日に公開されたビルドより新しいものです。
- モジュールの検査。
LuaMindModuleRegistry.inspectModule(sourceName, source)は、モジュールを登録せずに、その id、revision、依存関係、settingsのデフォルト値を読み取ります。LuaMindModuleDescriptor.settings()にはDouble、Boolean、String、List<String>の値が入ります。MagmaCore は設定をスクリプトに渡しません。クリーチャーごとの値を使いたいホストは、自身の値をこれらのデフォルトの上に統合して公開します。FreeMinecraftModels のペットがc.settingsで行っているとおりです。 - コールバックコンテキストの拡張。
LuaMindDefinition.instantiate(LuaMindContextExtension)は、すべてのコールバックのコンテキストテーブルに独自のフィールドを追加します。extend(table, context, contribution)は、Lua から見える前のテーブル、コールバックのMindContext、そのコールバックを宣言したモジュールの id(またはプログラム自身の id)を受け取ります。これはサーバースレッド上でコールバックの実行バジェットの範囲内で実行されるため、その CPU 時間はプログラムのcpu_microsに含まれ、例外はコールバックを失敗させます。フィールドの追加にはrawsetか、テーブル既存の__indexを他のすべてのキーに対して維持するLuaTableSupport.lazyFieldを使ってください。テーブルのメタテーブルや__indexを置き換えてはいけません。組み込みのセクションはそれらを通じて読み取られるためです。また、tick、generation、entity、memory、perception、actuator、actionsを上書きしてはいけません。extend内で組み込みセクションを読み取ると、そのコールバックのためにそのセクションが構築されます。エンティティごとの状態を保持する場合は、instantiateの呼び出しごとに別の拡張を渡してください。 - プローブ間隔。 Java のビヘイビアは
MindBehavior.probeInterval()をオーバーライドできます。これは Lua のprobe_intervalに相当し、停止中にcanStartを N ティックごとに問い合わせます。値は 1 からMindBehavior.MAX_PROBE_INTERVAL(200)の範囲でなければならず、MindProgramはそれ以外の値を拒否します。デフォルトの 1 は毎ティック問い合わせます。MindSensorは、そのボディが最初にティックされたティックに感知し、その後はエンティティごとの位相でintervalTicks()ティックごとに感知します。 - 飛行。
MindActuator.steerFlight(Vector)はそのビルドにすでに含まれており、FLYINGボディを 1 ティックの間その速度で飛ばし、MOVE と LOOK のリースを必要とします。新しいのは、その上限と Lua のsteer_flightです。MindActuator.MAX_FLIGHT_SPEEDは 1 ティックあたり 4 ブロックで、それより速い速度はこの値まで縮小されます。RouteFlightも速度をここで制限するため、毎秒 80 ブロックより速く設定したルートは、80 で飛行します。
ライブラリ変更後に利用プラグインをビルドする
JDK 21 を使い、./gradlew publishToMavenLocal、Windows では .\gradlew.bat publishToMavenLocal で MagmaCore を Maven Local に公開します。利用側がそのリポジトリと意図したバージョンを解決することを確認し、shaded JAR を再ビルドします。Maven Local のライブラリを差し替えても、ビルド済みプラグインは更新されません。
インストール済みプラグインの API は開発者向け目次を参照してください。通常は provided または compileOnly を使いますが、MagmaCore は組み込みライブラリとして扱います。