73 lines
4.5 KiB
Markdown
73 lines
4.5 KiB
Markdown
# GhostDisplays
|
||
|
||
Paper 1.21.10 向けの不可視ディスプレイ制御ライブラリです。TextDisplay / BlockDisplay / ItemDisplay をプレイヤー単位で表示・クリック検知できるようにし、ゴースト化した UI やガイドラインをサーバー側で柔軟に提供できます。
|
||
|
||
## 提供機能
|
||
|
||
- `DisplayService` による Text/Block/Item Display の生成 API
|
||
- `DisplayController` を介したパケットベースの表示・非表示制御(参照カウント管理)
|
||
- `AudiencePredicate`/`AudiencePredicates` による可視対象の自動同期(ログイン・ワールド移動・リスポーンで再評価)
|
||
- FakeInteraction エンティティを用いたクリック判定サポートと、優先度付きクリックハンドラー
|
||
- まとめて `destroyAll()` できるリソース管理
|
||
|
||
## スタンドアロンでの使い方
|
||
|
||
プラグインを `plugins/` に配置して起動すると `/ghostdisplay` コマンドが利用できます。デフォルトで OP のみ実行可能ですが、`ghostdisplays.command.*` を付与すると通常権限でも操作できます。
|
||
|
||
| コマンド | 説明 |
|
||
| --- | --- |
|
||
| `/ghostdisplay create text <id>` | プレイヤー視点の約 1.5 ブロック先に TextDisplay を生成し、即座にチャット編集モードへ。次に送信したメッセージ(または `cancel`)が内容になります。 |
|
||
| `/ghostdisplay create block <id> <blockstate>` | BlockDisplay を生成します。`oak_planks[facing=north]` のような `BlockData` 文字列を指定してください。 |
|
||
| `/ghostdisplay create item <id> <material>` | ItemDisplay を生成します。`minecraft:stick` などのアイテム ID を受け付けます。 |
|
||
| `/ghostdisplay text set <id> <content>` | TextDisplay のテキストを即時更新します。`_` はスペースに、`\n` は改行に変換されます。 |
|
||
| `/ghostdisplay viewer add|remove <id> <player/@a>` | 任意のプレイヤーまたはセレクターを表示対象に追加/削除します。`/ghostdisplay viewer clear <id>` で全員解除。 |
|
||
| `/ghostdisplay audience permission add <id> <permission>` | 指定パーミッションを持つプレイヤーに自動表示 (`remove` で解除)。 |
|
||
| `/ghostdisplay audience near set <id> <radius>` | Display 周囲の半径プレイヤーへ自動表示 (`audience clear` で全自動表示を解除)。 |
|
||
| `/ghostdisplay list` / `/ghostdisplay info <id>` | 登録済み Display の一覧、情報(座標 / Viewers / Audiences / 内容)を表示。 |
|
||
| `/ghostdisplay delete <id>` | Display を完全に削除します。 |
|
||
|
||
## 技術的ポイント
|
||
|
||
- **NMS パケットベースの FakeEntity 方式** — サーバー上に実エンティティを生成せず、クライアントへのパケット送信のみで表示を実現。エンティティティック・コリジョン・永続化のオーバーヘッドがゼロ
|
||
- パケット送信はスレッドセーフなため、Folia のリージョンスケジューリングに依存しないシンプルな設計
|
||
- クリック検知は Netty パイプラインで `ServerboundInteractPacket` を傍受し、FakeInteraction の entityId にマッチしたらハンドラーを発火
|
||
- Predicate ごとにアクティブなプレイヤー集合を持つため、複数条件での重複表示にも対応
|
||
- `paperweight-userdev` による NMS アクセス(1.21.11 対応)
|
||
|
||
## API 利用例
|
||
|
||
```kotlin
|
||
val service: DisplayService = GhostDisplaysPlugin.service()
|
||
|
||
// TextDisplay を生成
|
||
val controller = service.createTextDisplay(location) {
|
||
text = Component.text("Hello")
|
||
billboard = Display.Billboard.CENTER
|
||
viewRange = 0.5f
|
||
}
|
||
controller.show(player)
|
||
|
||
// テキスト更新
|
||
controller.updateText { it.text = Component.text("Updated") }
|
||
|
||
// 共通プロパティ更新
|
||
controller.updateDisplay { it.billboard = Display.Billboard.FIXED }
|
||
|
||
// テレポート
|
||
controller.teleport(newLocation)
|
||
|
||
// Audience ルール
|
||
controller.addAudienceRule(AudiencePredicates.near(location, 30.0), AudienceAction.ADD)
|
||
|
||
// クリックハンドラー
|
||
controller.onClick { ctx -> ctx.player.sendMessage("Clicked!") }
|
||
|
||
// 破棄
|
||
controller.destroy()
|
||
```
|
||
|
||
## 同梱ライブラリ
|
||
|
||
- コマンド定義は `kommand-lib`(Kotlin DSL)を使用し、`permits-lib` と連携して `ghostdisplays.command.*` のパーミッションツリーを自動生成しています。
|
||
- どちらも本リポジトリの `kommand-lib/` 以下にサブモジュールとして含まれており、`./gradlew build` 時に一緒にコンパイルされます。
|