minecraft-plugin-development について
Paper、Spigot、Bukkit エコシステムの Java プラグイン開発向けスキルです。ゲームプレイ、状態、設定、ライフサイクルの実装を案内し、一般的な構成や検証の参考資料も備えています。
主な機能
- 01Paper、Spigot、Bukkit プラグイン開発ガイド
- 02コマンドとリスナー登録の確認
- 03ゲーム状態とマッチフローの設計
- 04設定と永続データのパターン
- 05スレッド、タスク、ライフサイクルの安全策
- 06ビルドと実行時検証のガイド
活用シーン
- 01アリーナやウェーブ型ミニゲーム機能の実装
- 02コマンド、リスナー、設定可能なルールの追加
- 03プレイヤー状態やマッチのライフサイクル問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill minecraft-plugin-developmentインストール後、Claude Code で/minecraft-plugin-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/bootstrap-registration.mdbuild-test-and-runtime-validation.mdconfig-data-and-async.mdmaps-heroes-and-feature-modules.mdminigame-instance-flow.mdpersistent-progression-and-events.mdproject-patterns.mdstate-sessions-and-phases.md詳細
Minecraft プラグイン開発
Paper、Spigot、Bukkit のエコシステムで Minecraft サーバープラグインを開発する際に、このスキルを使用します。
このスキルは、戦闘システム、ウェーブ戦やボス戦、戦争モードやチームモード、アリーナ、キットシステム、クールダウンベースのアビリティ、スコアボード、設定駆動型のゲームルールなど、ゲームプレイ要素の多いプラグインで特に役立ちます。
実際の Paper プラグインに基づいた実装パターンを参照するには、必要に応じて以下を読み込んでください。
references/project-patterns.md:実際のゲームプレイプラグインで見られる、ハイレベルなアーキテクチャパターンreferences/bootstrap-registration.md:onEnable、コマンドの配線、リスナーの登録、シャットダウン時の要件references/state-sessions-and-phases.md:プレイヤーセッションのモデル化、ゲームフェーズ、マッチの状態、再接続に対応したロジックreferences/config-data-and-async.md:設定マネージャー、データベースを利用したプレイヤーデータ、非同期フラッシュ、UI 更新タスクreferences/maps-heroes-and-feature-modules.md:マップローテーション、ヒーローやクラスのシステム、モジュール式の機能拡張references/minigame-instance-flow.md:アリーナインスタンス、カウントダウン、戦利品の更新、ウェーブシステム、可視性の分離、エンティティとゲームの対応付けreferences/persistent-progression-and-events.md:プロフィール、パーク、バフ、クエスト、経済システム、カスタムドメインイベント、拡張レジストリを備えた長期運用型 PvP サーバーreferences/build-test-and-runtime-validation.md:Maven または Gradle によるパッケージ化、依存関係のシェーディング、生成リソース、ソフト依存関係、設定検証コマンド、初回サーバーテストの計画
対象範囲
- 対象:Paper、Spigot、Bukkit のプラグイン開発
- 対象:
plugin.yml、コマンド、タブ補完、リスナー、スケジューラー、設定、権限、Adventure のテキスト、プレイヤーの状態、ミニゲームのフロー、アリーナインスタンス、マップの複製、戦利品、ウェーブ、永続プロフィール、パーク、バフ、クエスト、経済システム、PvP/PvE のゲームループ - 対象:Java ベースのサーバープラグインアーキテクチャ、デバッグ、リファクタリング、機能の実装
- 原則として対象外:Fabric MOD、Forge MOD、クライアント MOD、Bedrock アドオン
ユーザーが「Minecraft プラグイン」と述べていても技術スタックが不明な場合は、まずプロジェクトが Paper/Spigot/Bukkit 向けなのか、MOD 開発用の技術スタックなのかを確認してください。
デフォルトの作業スタイル
このスキルが呼び出されたら:
- サーバー API と対象バージョンを特定します。
- ビルドシステムと Java のバージョンを特定します。
plugin.yml、メインプラグインクラス、コマンドまたはリスナーの登録を調べます。- コードを編集する前に、ゲームプレイの流れを把握します:
- プレイヤーのライフサイクル
- ゲームフェーズ
- タイマーとスケジュールされたタスク
- チーム、アリーナ、またはマッチの状態
- 設定と永続化
- 登録、設定、実行時の動作の整合性を保ちながら、最小限で一貫性のある変更を行います。
プラグインがゲームプレイ中心、または状態を多く扱う場合は、編集前にreferences/project-patterns.mdとreferences/state-sessions-and-phases.mdを読んでください。
アリーナの分離、マップインスタンス、チェストやリソースの補充、ウェーブのスポーン、ルート投票、観戦者の表示、ゲーム固有のチャットに関わる場合は、references/minigame-instance-flow.mdも読んでください。
永続的なプレイヤーの進行状況、プロフィールの保存、経済報酬、パーク、バフ、クエスト、カスタム戦闘イベント、または長時間稼働する共有 PvP サーバーに関わる場合は、references/persistent-progression-and-events.mdも読んでください。
ビルドファイル、plugin.yml のメタデータ、シェードされた依存関係、生成されたリソースの出力、テストサーバーへのデプロイ、オプションのプラグイン連携、またはリリース検証に関わる場合は、references/build-test-and-runtime-validation.mdも読んでください。
プロジェクト調査チェックリスト
該当するものがある場合は、まず次を確認します:
plugin.ymlpom.xml、build.gradle、またはbuild.gradle.ktsJavaPluginを継承するプラグインのメインクラス- コマンド実行クラスとタブ補完クラス
- リスナークラス
config.yml、メッセージ、キット、アリーナ、またはカスタム YAML ファイル用の設定初期化コードtarget/classes、build/resources、コピーされたプラグイン JAR など、生成されたリソースの出力先- Bukkit スケジューラー API を介したスケジューラーの使用箇所
- プレイヤーデータ、チーム状態、アリーナ状態、またはマッチ状態を保持するコンテナー
基本ルール
リポジトリ内の具体的なサーバー API を優先する
- プロジェクトがすでに Paper API を対象としている場合、互換性が明示的に必要でない限り、汎用的な Bukkit にダウングレードせず、Paper 優先の API を使い続けます。
- すべてのバージョンで API が利用できるとは限りません。まず既存の依存関係と周辺のコードスタイルを確認します。
登録の整合性を保つ
コマンド、権限、またはリスナーを追加する場合は、同じ変更内で関連する登録箇所も更新します:
plugin.ymlonEnableでのプラグイン起動時の登録- コード内の権限チェック
- 関連する設定キーやメッセージキー
メインスレッドの境界を守る
- API で明示的に許可されていない限り、非同期タスクからワールドの状態、エンティティ、インベントリ、スコアボード、またはほとんどの Bukkit API オブジェクトに触れてはいけません。
- 外部 I/O、負荷の高い計算、またはデータベース処理には非同期タスクを使い、ゲームプレイの変更を適用する前にメインスレッドへ戻します。
ゲームプレイは散在するブール値ではなく、状態としてモデル化する
ゲームプレイプラグインでは、重複するフラグよりも明示的な状態オブジェクトを優先します:
- マッチまたはゲームのフェーズ
- プレイヤーの役割またはクラス
- クールダウンの状態
- チームへの所属
- アリーナの割り当て
- 生存、脱落、観戦、または待機中の状態
マッチ中心のミニゲームや永続的な乱闘ゲームプレイに影響する機能では、症状を修正する前に、隠れた状態遷移がないか確認します。
複数のアリーナに対応するプラグインでは、ゲームごとの表示、チャットの送信先、スコアボード、戦利品、エンティティの所有権を分離します。あるアリーナから別のアリーナを誤って認識したり、変更したりできないようにします。
設定駆動の値を優先する
機能にダメージ、クールダウン、報酬、継続時間、メッセージ、マップ設定、または切り替え設定が含まれる場合:
- ハードコードするのではなく、設定から取得する値を優先します
- 妥当なデフォルト値を用意します
- キー名は安定させ、読みやすくします
- 値が欠落している場合は検証またはサニタイズします
リロード時の動作に注意する
- コードが十分に対応していない限り、安全なホットリロードを保証しないでください。
- 設定のリロード時に、インメモリキャッシュ、スケジュール済みタスク、ゲームプレイの状態が一貫して処理されるようにしてください。
実装パターン
コマンド
新しいコマンドを追加する場合:
plugin.ymlにコマンドを追加します- 必要に応じて実行処理とタブ補完を実装します
Playerにキャストする前に、送信者の型を検証します- パース処理、権限チェック、ゲームプレイのロジックを分離します
- 入力が無効な場合は、プレイヤーにわかりやすいフィードバックを送信します
最小限の登録形式:
commands:
arena:
description: Join or leave an arena
usage: /arena <join|leave>
@Override
public void onEnable() {
ArenaCommand command = new ArenaCommand(gameService);
PluginCommand arena = getCommand("arena");
if (arena != null) {
arena.setExecutor(command);
arena.setTabCompleter(command);
}
}
リスナー
イベントリスナーでは:
- 早い段階で条件を確認し、早期に return します
- 現在のプレイヤー、アリーナ、ゲームフェーズがイベントを処理すべきかどうかを確認します
- 移動、ダメージ、連続したインタラクトなど、頻繁に発生するイベントで高コストな処理を避けます
- 実用的な場合は、繰り返し行うチェックを一元化します
スケジュール済みタスク
タイマー、ラウンド、カウントダウン、クールダウン、定期チェックでは:
- キャンセルが必要な場合は、タスクハンドルを保持します
- プラグインの無効化時、およびマッチやアリーナの終了時にタスクをキャンセルします
- 明示的な意図がない限り、同じゲームプレイ上の処理に複数のタスクを重ねて実行しないでください
- 連携が緩やかな多数の繰り返しタスクより、権威あるゲームループを1つ使用してください
- ゲームが想定された状態を離れたときに、カウントダウンや補充タスクが自らキャンセルされるようにしてください
メインスレッドへの処理移譲形式:
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
PlayerData data = repository.load(playerId);
Bukkit.getScheduler().runTask(plugin, () -> {
Player player = Bukkit.getPlayer(playerId);
if (player != null && player.isOnline()) {
scoreboard.update(player, data);
}
});
});
プレイヤーとマッチの状態
プレイヤー単位またはマッチ単位の状態では:
- 所有者を明確に定義します
- 退出、キック、死亡、マッチ終了、プラグインの無効化時にクリーンアップします
Playerをキーとする古いマップによるメモリリークを避けます- 生きているプレイヤーオブジェクトが厳密に必要な場合を除き、永続的な追跡には
UUIDを使用します
テキストとメッセージ
プロジェクトで Adventure または MiniMessage を使用している場合:
- 既存の書式設定方法に従います
- 理由なくレガシーなカラーコードと Adventure のスタイルを混在させないでください
- ゲームプレイに関わるメッセージでは、メッセージテンプレートを設定可能にします
リスクの高い領域
次の箇所を編集する際は、特に注意してください:
- ダメージ処理とカスタム戦闘ロジック
- 死亡、リスポーン、スペクテイター、脱落の処理フロー
- アリーナへの参加と退出の処理フロー
- スコアボードやボスバーの更新
- インベントリの変更とキットの配布
- 非同期のデータベースまたはファイルアクセス
- 経済、クエスト、パーク、プロフィールの変更
- カスタムイベントの発行または拡張機能レジストリ
- バージョンに依存する API 呼び出し
onDisableでのシャットダウンとクリーンアップ- アリーナ間の表示、チャット、ブロードキャストの分離
- マップのコピー、アンロード、フォルダー削除のロジック
- Mob、NPC、飛翔体、一時エンティティの所有権
- チェストやリソースの補充システム
出力に関する要件
プラグインコードを実装または修正する場合:
- ユーザーが設計のみを求めている場合を除き、疑似コードではなく実行可能な Java コードを作成します
plugin.yml、設定ファイル、ビルドファイル、リソースに必要な更新があれば明記します- バージョンに関する前提を明示します
- スレッドセーフティや API 互換性のリスクがある場合は指摘します
- プロジェクトの既存の規約とフォルダー構成を維持します
変更がプラグインの起動、非同期データ、マッチの進行、クラスシステム、またはローテーションするマップに関わる場合は、編集前に該当するリファレンスファイルを確認してください。
検証チェックリスト
作業を終える前に、タスクの範囲で可能な限り次の項目を確認してください:
- コマンド、リスナー、または機能が正しく登録されている
plugin.ymlが実装された動作と一致している- インポートと API 型が対象のサーバースタックに適合している
- スケジューラーの使用が安全である
- コードで参照する設定キーが存在するか、デフォルト値が設定されている
- マッチ終了、プレイヤーの退出、プラグインの無効化に対する状態のクリーンアップ処理がある
- アリーナごとにチャット、表示、スコアボード、ブロードキャストが分離されている
- 一時ワールド、Mob、タスク、生成されたリソースがクリーンアップされる
- 明らかな null、キャスト、ライフサイクル上の危険性がない
よくある落とし穴
- 確認せずに
CommandSenderをPlayerにキャストする - 非同期タスクから Bukkit の状態を更新する
- リスナーの登録や
plugin.ymlでのコマンド宣言を忘れる UUIDのほうが安全なのに、Playerオブジェクトを長期間保持するマップのキーにする- ラウンド、アリーナ、プラグインの終了後も、繰り返しタスクを稼働させたままにする
- 設定ファイルに置くべきゲームプレイの定数をハードコードする
- Spigot 対象のプラグインで、Paper 専用 API を使えると想定する
- 状態を持つプラグインはリロードで壊れることが多いのに、リロードにコストがないかのように扱う
- 無関係なゲームインスタンスに対して、ブロードキャスト、プレイヤーの表示、スコアボードの変更を行う
- チャンクが利用可能になる前に、チェストやコンテナのブロックを読み込んだり変更したりする
- スポーンしたモブや一時的なエンティティを、所有するゲームから登録解除し忘れる
src/main/resourcesのソースファイルではなく、target/classesやbuild/resourcesの生成ファイルを編集する
推奨する回答の構成
重要な依頼では、次のように作業を構成してください。
- 現在のプラグインの状況と前提
- ゲームプレイまたはライフサイクルへの影響
- コードの変更
- 必要な登録または設定の更新
- 検証と残るリスク
小さな依頼では、簡潔に回答しつつ、必要な plugin.yml、設定、ライフサイクルの更新についても触れてください。