Skip to content

Commit c64a2ec

Browse files
committed
feat(menu): 新增 dialogs 菜单功能支持
- 新增 dialogs 菜单渲染链路与配置解析 - 支持 dialogs 示例菜单、回退逻辑与高自定义布局骨架
1 parent 265ee9a commit c64a2ec

52 files changed

Lines changed: 1493 additions & 38 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
build
44
.serena
55
AGENTS.md
6+
.narrafork
7+
.claude
8+
docs
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
data class DialogActionPayload(
4+
val id: String,
5+
val label: String,
6+
val width: Int? = null,
7+
val closesDialog: Boolean = true,
8+
val nextPage: Int? = null
9+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
import org.bukkit.inventory.ItemStack
4+
5+
data class DialogElementPayload(
6+
val id: String,
7+
val type: String,
8+
val label: String? = null,
9+
val text: List<String> = emptyList(),
10+
val width: Int? = null,
11+
val item: ItemStack? = null,
12+
val placeholder: String? = null,
13+
val options: List<DialogOptionPayload> = emptyList(),
14+
val value: String? = null,
15+
val boolValue: Boolean? = null,
16+
val maxLength: Int? = null,
17+
val min: Double? = null,
18+
val max: Double? = null,
19+
val step: Double? = null
20+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
import org.bukkit.entity.Player
4+
5+
abstract class DialogNms {
6+
7+
abstract fun supportsDialogs(): Boolean
8+
9+
abstract fun open(player: Player, payload: DialogPayload)
10+
11+
abstract fun close(player: Player)
12+
13+
abstract fun parseResponse(packet: Any): DialogResponseData?
14+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
import org.bukkit.entity.Player
4+
import taboolib.module.nms.MinecraftVersion
5+
6+
class DialogNmsImpl : DialogNms() {
7+
8+
private val requiredClasses = listOf(
9+
"net.minecraft.network.protocol.Packet",
10+
"net.minecraft.server.level.ServerPlayer"
11+
)
12+
13+
override fun supportsDialogs(): Boolean {
14+
if (MinecraftVersion.majorLegacy < 12106) {
15+
return false
16+
}
17+
if (!requiredClasses.all { className -> runCatching { Class.forName(className) }.isSuccess }) {
18+
return false
19+
}
20+
// 当前阶段仅落骨架,不在这里伪装成“已支持”。
21+
// 真正的 1.21.6+ dialogs 发包/回包映射实现到位后,再切换为 true。
22+
return false
23+
}
24+
25+
override fun open(player: Player, payload: DialogPayload) {
26+
throw UnsupportedOperationException("Dialogs NMS bridge is not available for the current runtime.")
27+
}
28+
29+
override fun close(player: Player) {
30+
// Dialogs 暂无通用 close packet 映射时,保持空实现,由上层负责清理会话。
31+
}
32+
33+
override fun parseResponse(packet: Any): DialogResponseData? {
34+
return null
35+
}
36+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
data class DialogOptionPayload(
4+
val id: String,
5+
val title: String,
6+
val description: String? = null
7+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
data class DialogPayload(
4+
val menuId: String,
5+
val pageId: String,
6+
val pageIndex: Int,
7+
val screenType: String,
8+
val title: String?,
9+
val externalTitle: String?,
10+
val allowEscClose: Boolean,
11+
val body: List<DialogElementPayload>,
12+
val actions: List<DialogActionPayload>
13+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package trplugins.menu.api.receptacle.dialog
2+
3+
data class DialogResponseData(
4+
val actionId: String?,
5+
val closeAction: Boolean = false,
6+
val values: Map<String, Any?> = emptyMap()
7+
)

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ subprojects {
7272
disableOnSkippedVersion = false
7373
}
7474
version {
75-
taboolib = "6.2.4-86dd2bf"
75+
taboolib = "6.2.4-99fb800"
7676
coroutines = null
7777
}
7878
}

common/src/main/kotlin/trplugins/menu/util/conf/Property.kt

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,41 @@ enum class Property(val default: String, val regex: Regex) {
5353
*/
5454
OPTIONS("Options", "(option|setting)s?"),
5555

56+
/**
57+
* 菜单渲染类型
58+
*/
59+
RENDER_TYPE("Render-Type", "render-?types?"),
60+
61+
/**
62+
* Dialogs 根节点
63+
*/
64+
DIALOG("Dialog", "dialogs?"),
65+
66+
/**
67+
* Dialogs 最低版本
68+
*/
69+
DIALOG_MIN_VERSION("Min-Version", "min-?versions?"),
70+
71+
/**
72+
* Dialogs 回退菜单
73+
*/
74+
DIALOG_FALLBACK_MENU("Fallback-Menu", "fallback-?menus?"),
75+
76+
/**
77+
* Dialogs 是否允许 ESC 关闭
78+
*/
79+
DIALOG_ALLOW_ESC_CLOSE("Allow-Esc-Close", "allow-?esc-?closes?"),
80+
81+
/**
82+
* Dialogs 外部标题
83+
*/
84+
DIALOG_EXTERNAL_TITLE("External-Title", "external-?titles?"),
85+
86+
/**
87+
* Dialogs 页列表
88+
*/
89+
DIALOG_PAGES("Pages", "pages?"),
90+
5691
/**
5792
* 菜单选项 - 是否启用传递参数
5893
*/
@@ -163,6 +198,111 @@ enum class Property(val default: String, val regex: Regex) {
163198
*/
164199
DENY_ACTIONS("deny-actions", "deny(-)?(list|action|click|execute|cmd)?s?"),
165200

201+
/**
202+
* Dialogs 页 ID
203+
*/
204+
DIALOG_PAGE_ID("Id", "ids?"),
205+
206+
/**
207+
* Dialogs 页类型
208+
*/
209+
DIALOG_PAGE_TYPE("Type", "types?"),
210+
211+
/**
212+
* Dialogs 页标题
213+
*/
214+
DIALOG_PAGE_TITLE("Title", "titles?"),
215+
216+
/**
217+
* Dialogs 页正文
218+
*/
219+
DIALOG_PAGE_BODY("Body", "bod(y|ies)"),
220+
221+
/**
222+
* Dialogs 页动作
223+
*/
224+
DIALOG_PAGE_ACTIONS("Actions", "actions?"),
225+
226+
/**
227+
* Dialogs 编译器
228+
*/
229+
DIALOG_COMPILER("Compiler", "compilers?"),
230+
231+
/**
232+
* Dialogs 编译策略
233+
*/
234+
DIALOG_COMPILER_STRATEGY("Strategy", "strateg(y|ies)"),
235+
236+
/**
237+
* Dialogs 不支持策略
238+
*/
239+
DIALOG_COMPILER_UNSUPPORTED_POLICY("Unsupported-Policy", "unsupported-?polic(y|ies)"),
240+
241+
/**
242+
* Dialogs 网格列数
243+
*/
244+
DIALOG_COMPILER_GRID_COLUMNS("Grid-Columns", "grid-?columns?"),
245+
246+
/**
247+
* Dialogs 内容最大宽度
248+
*/
249+
DIALOG_COMPILER_CONTENT_MAX_WIDTH("Content-Max-Width", "content-?max-?width"),
250+
251+
/**
252+
* Dialogs Mixin Assist
253+
*/
254+
DIALOG_COMPILER_MIXIN_ASSIST("Mixin-Assist", "mixin-?assist"),
255+
256+
/**
257+
* Dialogs 布局
258+
*/
259+
DIALOG_LAYOUT("Layout", "layouts?"),
260+
261+
/**
262+
* Dialogs 布局行距
263+
*/
264+
DIALOG_LAYOUT_ROW_GAP("Row-Gap", "row-?gaps?"),
265+
266+
/**
267+
* Dialogs 布局分区
268+
*/
269+
DIALOG_LAYOUT_SECTIONS("Sections", "sections?"),
270+
271+
/**
272+
* Dialogs Widgets
273+
*/
274+
DIALOG_WIDGETS("Widgets", "widgets?"),
275+
276+
/**
277+
* Dialogs Widget 种类
278+
*/
279+
DIALOG_WIDGET_KIND("kind", "kinds?"),
280+
281+
/**
282+
* Dialogs Widget 锚点
283+
*/
284+
DIALOG_WIDGET_ANCHOR("anchor", "anchors?"),
285+
286+
/**
287+
* Dialogs Widget 行号
288+
*/
289+
DIALOG_WIDGET_ROW("row", "rows?"),
290+
291+
/**
292+
* Dialogs Widget 起始列
293+
*/
294+
DIALOG_WIDGET_COL_START("col-start", "col-?starts?"),
295+
296+
/**
297+
* Dialogs Widget 跨列
298+
*/
299+
DIALOG_WIDGET_COL_SPAN("col-span", "col-?spans?"),
300+
301+
/**
302+
* Dialogs Widget 顺序
303+
*/
304+
DIALOG_WIDGET_ORDER("order", "orders?"),
305+
166306
/**
167307
* 菜单图标
168308
*/

0 commit comments

Comments
 (0)