# kommand-lib マイグレーションガイド このガイドでは、旧バージョンの kommand-lib から最新の Brigadier ネイティブ対応バージョンへの移行方法を説明します。 --- ## 📋 目次 1. [変更の概要](#変更の概要) 2. [破壊的変更](#破壊的変更) 3. [マイグレーション手順](#マイグレーション手順) 4. [コード例の比較](#コード例の比較) 5. [トラブルシューティング](#トラブルシューティング) --- ## 変更の概要 ### 🎯 主な変更点 1. **Brigadier ネイティブ対応** - Paper 1.21 の Lifecycle API を使用したコマンド登録 - クライアント側での構文ヒントと検証 - より正確な型システム 2. **引数の型変更** - `coordinates()` の返り値が `Coordinates3` から `io.papermc.paper.math.Position` に変更 - Player/Entity セレクターの内部処理が改善 3. **自動登録** - `kommand()` 関数の呼び出しで自動的にコマンドが登録されるように変更 --- ## 破壊的変更 ### 🔴 1. `coordinates()` 引数の型変更 #### 旧バージョン (動作しません) ```kotlin coordinates("point") { executes { val coords = argument("point") val target = coords.resolve(player.location) // Coordinates3 型は存在しません } } ``` #### 新バージョン (正しい方法) ```kotlin coordinates("point") { executes { val position = argument("point") val location = position.toLocation(player.world) // Position 型を使用します } } ``` **理由**: Paper の Brigadier API は `io.papermc.paper.math.Position` を返します。これは Paper の公式 API に準拠しています。 --- ### 🟡 2. Player/Entity セレクターの内部処理 **ユーザーコードに変更は不要です**が、内部的に以下の変更が行われました: #### 内部処理の改善 ```kotlin // 旧: 直接キャスト (実行時エラーの原因) val player = context.getArgument("player", Player::class.java) // 新: Resolver を使用して解決 (正しい方法) val resolver = context.getArgument("player", PlayerSelectorArgumentResolver::class.java) val player = resolver.resolve(source).firstOrNull() ``` **影響**: Player/Entity 引数がより安定して動作するようになりました。 --- ## マイグレーション手順 ### ステップ 1: 依存関係の確認 `build.gradle.kts` で Paper API のバージョンを確認してください: ```kotlin dependencies { compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") // 1.21 以降が必要です } ``` ### ステップ 2: import 文の追加 `coordinates()` を使用している場合、import を追加してください: ```kotlin import io.papermc.paper.math.Position ``` ### ステップ 3: コードの更新 以下のパターンを検索して置換してください: #### パターン 1: coordinates の型指定 **検索**: ```kotlin argument(" ``` **置換**: ```kotlin argument(" ``` または、import を追加して: ```kotlin argument(" ``` #### パターン 2: coordinates の解決方法 **検索**: ```kotlin val coords = argument("pos") val location = coords.resolve(baseLocation) ``` **置換**: ```kotlin val position = argument("pos") val location = position.toLocation(world) ``` ### ステップ 4: ビルドとテスト ```bash ./gradlew build ``` エラーがないことを確認してから、サーバーでテストしてください。 --- ## コード例の比較 ### 例 1: スポーン地点の設定 #### ❌ 旧バージョン ```kotlin literal("setspawn") { coordinates("point") { executes { val base = (sender as? Player)?.location ?: return@executes val coords = argument("point") val target = coords.resolve(base) plugin.server.worlds.first().setSpawnLocation(target) sender.sendMessage("Spawn set to ${target.x}, ${target.y}, ${target.z}") } } } ``` #### ✅ 新バージョン ```kotlin literal("setspawn") { coordinates("point") { executes { val player = sender as? Player ?: return@executes val position = argument("point") val location = position.toLocation(player.world) player.world.setSpawnLocation(location) sender.sendMessage("Spawn set to ${location.x}, ${location.y}, ${location.z}") } } } ``` **変更点**: - `Coordinates3` → `Position` - `coords.resolve(base)` → `position.toLocation(world)` - より明確な変数名 --- ### 例 2: テレポートコマンド #### ❌ 旧バージョン ```kotlin literal("tp") { coordinates("destination") { executes { val player = sender as? Player ?: return@executes val coords = argument("destination") val target = coords.resolve(player.location) player.teleport(target) } } } ``` #### ✅ 新バージョン ```kotlin literal("tp") { coordinates("destination") { executes { val player = sender as? Player ?: return@executes val position = argument("destination") val location = position.toLocation(player.world) player.teleport(location) } } } ``` --- ### 例 3: 範囲指定コマンド #### ❌ 旧バージョン ```kotlin literal("fill") { coordinates("pos1") { coordinates("pos2") { executes { val player = sender as? Player ?: return@executes val base = player.location val pos1 = argument("pos1").resolve(base) val pos2 = argument("pos2").resolve(base) // 処理... } } } } ``` #### ✅ 新バージョン ```kotlin literal("fill") { coordinates("pos1") { coordinates("pos2") { executes { val player = sender as? Player ?: return@executes val world = player.world val pos1 = argument("pos1").toLocation(world) val pos2 = argument("pos2").toLocation(world) // 処理... } } } } ``` --- ## Position API リファレンス ### Position のメソッド ```kotlin interface Position { fun x(): Double fun y(): Double fun z(): Double fun blockX(): Int fun blockY(): Int fun blockZ(): Int fun toLocation(world: World): Location } ``` ### 使用例 ```kotlin val position = argument("pos") // 座標の取得 val x = position.x() val y = position.y() val z = position.z() // ブロック座標の取得 val blockX = position.blockX() val blockY = position.blockY() val blockZ = position.blockZ() // Location への変換 val location = position.toLocation(player.world) ``` --- ## トラブルシューティング ### 問題 1: `Coordinates3` が見つからない **エラー**: ``` Unresolved reference: Coordinates3 ``` **解決方法**: `Coordinates3` は存在しません。`io.papermc.paper.math.Position` を使用してください。 ```kotlin // ❌ 間違い argument("pos") // ✅ 正しい argument("pos") ``` --- ### 問題 2: `resolve()` メソッドが見つからない **エラー**: ``` Unresolved reference: resolve ``` **解決方法**: `Position` には `resolve()` メソッドはありません。`toLocation(world)` を使用してください。 ```kotlin // ❌ 間違い val location = position.resolve(baseLocation) // ✅ 正しい val location = position.toLocation(world) ``` --- ### 問題 3: Player セレクターが動作しない **症状**: Player 引数を使用するとエラーが発生する **解決方法**: 最新バージョンに更新してください。内部的に `ArgumentResolver` が自動的に処理します。 ```kotlin // これは自動的に動作します val player = argument("target") val players = argument>("targets") ``` --- ### 問題 4: コマンドが登録されない **症状**: `/help` にコマンドが表示されない **解決方法**: 最新バージョンでは `kommand()` 関数の呼び出しで自動的に登録されます。 ```kotlin class MyPlugin : JavaPlugin() { private lateinit var commands: KommandLib override fun onEnable() { // これだけで自動的に登録されます commands = kommand(this) { command("mycommand") { // ... } } } } ``` --- ## よくある質問 (FAQ) ### Q1: 相対座標 (`~`) は引き続き使えますか? **A**: はい、引き続き使えます。`Position` は相対座標を完全にサポートしています。 ```kotlin // "~ ~1 ~-2" のような入力が可能 val position = argument("pos") ``` --- ### Q2: 旧バージョンとの互換性はありますか? **A**: `coordinates()` 引数の型が変更されているため、**互換性はありません**。マイグレーションが必要です。 ただし、`player()`, `players()`, `selector()` などの他の引数は互換性があります。 --- ### Q3: マイグレーションにどのくらい時間がかかりますか? **A**: プロジェクトの規模によりますが、通常は以下の通りです: - **小規模** (1-5 コマンド): 5-10 分 - **中規模** (5-20 コマンド): 15-30 分 - **大規模** (20+ コマンド): 30-60 分 主な作業は検索と置換なので、比較的短時間で完了します。 --- ### Q4: 段階的な移行は可能ですか? **A**: いいえ、`coordinates()` を使用している場合は一度にすべて移行する必要があります。 ただし、`coordinates()` を使用していないコマンドは変更不要です。 --- ## サポート 問題が発生した場合は、以下のドキュメントを参照してください: - [README.md](./README.md) - 基本的な使い方 - [BRIGADIER_REVIEW.md](./BRIGADIER_REVIEW.md) - 詳細なレビュー - [Paper API Documentation](https://docs.papermc.io/paper/dev/command-api/arguments/location) - Position API の詳細 --- ## まとめ ### ✅ マイグレーションチェックリスト - [ ] Paper API 1.21 以降を使用していることを確認 - [ ] `Coordinates3` を `Position` に置換 - [ ] `coords.resolve()` を `position.toLocation()` に置換 - [ ] 必要な import を追加 - [ ] ビルドが成功することを確認 - [ ] サーバーでテストして動作を確認 ### 🎉 完了! マイグレーションが完了すると、以下のメリットが得られます: - ✅ クライアント側での構文ヒント - ✅ より正確な型チェック - ✅ Paper の公式 API に準拠 - ✅ より安定した動作 ご不明な点がございましたら、お気軽にお問い合わせください。