sapdon 3.2.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -121
- package/doc/dev/architecture.md +418 -0
- package/doc/dev/cli.md +467 -0
- package/doc/dev/core.md +751 -0
- package/doc/dev/lr-paradigm.md +85 -0
- package/doc/dev/oc.md +582 -0
- package/doc/dev/workflow.md +257 -0
- package/doc/hello_sapdon/hello_sapdon.md +3 -3
- package/doc/user/api/biome.md +558 -0
- package/doc/user/api/block.md +1530 -0
- package/doc/user/api/entity.md +685 -0
- package/doc/user/api/extra.md +231 -0
- package/doc/user/api/item.md +1125 -0
- package/doc/user/api/neo-guidebook.md +409 -0
- package/doc/user/api/recipe.md +427 -0
- package/doc/user/api/sapdon-ui.md +185 -0
- package/doc/user/api/texture.md +181 -0
- package/doc/user/config/build-config.md +83 -0
- package/doc/user/config/mod-info.md +33 -0
- package/doc/user/faq.md +160 -0
- package/doc/user/quick-start.md +122 -0
- package/doc/user/tutorials/block.md +474 -0
- package/doc/user/tutorials/entity.md +356 -0
- package/doc/user/tutorials/item.md +449 -0
- package/doc/user/tutorials/neo-guidebook-experience.md +381 -0
- package/doc/user/tutorials/neo-guidebook.md +640 -0
- package/doc/user/tutorials/recipe.md +278 -0
- package/doc/user/tutorials/sapdon-ui.md +207 -0
- package/package.json +8 -3
- package/prod/cli/index.js +1 -1
- package/prod/cli/start.js +1 -1458
- package/prod/core/index.d.ts +4564 -2166
- package/prod/core/index.js +1 -59015
- package/prod/core/package.json +7 -0
- package/prod/oc/index.d.ts +350 -108
- package/prod/oc/index.js +1 -1
- package/prod/oc/package.json +7 -0
- package/prod/utils/index.d.ts +20 -9
- package/prod/utils/index.js +1 -1
- package/prod/utils/package.json +7 -0
- package/doc/BlockAPI.md +0 -145
- package/doc/api.md +0 -128
- package/doc/oc/index.md +0 -0
- package/doc/sapdon-ts.md +0 -64
- package/src/templates/js_sapdon/build.config +0 -23
- package/src/templates/js_sapdon/main.mjs +0 -4
- package/src/templates/js_sapdon/mod.info +0 -7
- package/src/templates/js_sapdon/pack_icon.png +0 -0
- package/src/templates/js_sapdon/package.json +0 -20
- package/src/templates/js_sapdon/res/animations/animation_item.animation.json +0 -34
- package/src/templates/js_sapdon/res/animations/large_item.animation.json +0 -27
- package/src/templates/js_sapdon/res/models/blocks/crop.geo.json +0 -48
- package/src/templates/js_sapdon/res/models/entity/animation/animation_item.geo.json +0 -26
- package/src/templates/js_sapdon/res/models/entity/animation/large_item.geo.json +0 -28
- package/src/templates/js_sapdon/res/textures/blocks/none.png +0 -0
- package/src/templates/js_sapdon/res/textures/blocks/test_log_oak.png +0 -0
- package/src/templates/js_sapdon/res/textures/blocks/test_log_top.png +0 -0
- package/src/templates/js_sapdon/res/textures/items/masterball.png +0 -0
- package/src/templates/js_sapdon/scripts/custom_components/cropComponent.js +0 -50
- package/src/templates/js_sapdon/scripts/custom_components/items/gui_book.js +0 -37
- package/src/templates/js_sapdon/scripts/custom_components/registry.js +0 -25
- package/src/templates/js_sapdon/scripts/index.js +0 -0
- package/src/templates/ts_sapdon/build.config +0 -23
- package/src/templates/ts_sapdon/main.ts +0 -11
- package/src/templates/ts_sapdon/mod.info +0 -7
- package/src/templates/ts_sapdon/pack_icon.png +0 -0
- package/src/templates/ts_sapdon/package.json +0 -20
- package/src/templates/ts_sapdon/res/models/blocks/crop.geo.json +0 -48
- package/src/templates/ts_sapdon/res/textures/blocks/test_log_oak.png +0 -0
- package/src/templates/ts_sapdon/res/textures/blocks/test_log_top.png +0 -0
- package/src/templates/ts_sapdon/res/textures/items/masterball.png +0 -0
- package/src/templates/ts_sapdon/scripts/components/cropComponent.ts +0 -44
- package/src/templates/ts_sapdon/scripts/components/items/guiBook.ts +0 -36
- package/src/templates/ts_sapdon/scripts/components/registry.ts +0 -24
- package/src/templates/ts_sapdon/scripts/index.ts +0 -7
- package/src/templates/ts_sapdon/tsconfig.json +0 -117
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# NeoGuidebook API 参考
|
|
2
|
+
|
|
3
|
+
NeoGuidebook 是基于 Minecraft Bedrock JSON UI 体系的指南书生成框架。使用链式 API 声明式构建页面,构建时自动序列化为 JSON UI,运行时通过 ActionFormData 触发显示。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
1. [概览](#1-概览)
|
|
10
|
+
2. [NeoGuidebook 类](#2-neoguidebook-类)
|
|
11
|
+
3. [NeoGuidebookPage 类](#3-neoguidebookpage-类)
|
|
12
|
+
4. [NeoGuidebookBridge 类](#4-neoguidebookbridge-类)
|
|
13
|
+
5. [ItemComponent 辅助](#5-itemcomponent-辅助)
|
|
14
|
+
6. [page_ids.json 生成](#6-page_idsjson-生成)
|
|
15
|
+
7. [运行时注册](#7-运行时注册)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. 概览
|
|
20
|
+
|
|
21
|
+
### 工作流程
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
构建时 (main.ts) 运行时 (index.ts)
|
|
25
|
+
───────────────── ─────────────────
|
|
26
|
+
ItemAPI.createItem() system.beforeEvents.startup
|
|
27
|
+
+ setCustomComponentV2() → registerCustomComponent()
|
|
28
|
+
+ setMaxStackSize() → onUse(event, params)
|
|
29
|
+
+ setDisplayName() → ActionFormData
|
|
30
|
+
+ setInteractButton() .title("sapdon_ui:book_name")
|
|
31
|
+
.body("page_id")
|
|
32
|
+
NeoGuidebook("ns:name") → 按钮 .button("prev_button")
|
|
33
|
+
+ addDoublePageStack(id, L, R) .show(player)
|
|
34
|
+
+ addSinglePageStack(id, P)
|
|
35
|
+
+ addCustomButton(config) NeoGuidebookBridge
|
|
36
|
+
→ 上一页/下一页/首页/章节跳转
|
|
37
|
+
registry.submit()
|
|
38
|
+
→ neo_guidebook.json page_ids.json
|
|
39
|
+
→ server_form.json 供 Bridge 获取页面列表
|
|
40
|
+
→ page_ids.json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 脚本 ↔ JSON UI 绑定
|
|
44
|
+
|
|
45
|
+
| ActionForm API | JSON UI 变量 | 说明 |
|
|
46
|
+
|----------------|-------------|------|
|
|
47
|
+
| `.title("sapdon_ui:name")` | `#title_text` | `sapdon_ui:` 前缀路由(SapdonServerUI),精确匹配 `$panel_id` |
|
|
48
|
+
| `.body("page_id")` | `#form_text` | 切换可见页面(匹配页面的 `$binding_text`) |
|
|
49
|
+
| `.button("text")` | `#form_button_text` | 匹配按钮的 `$binding_button_text`,控制哪个按钮 visible |
|
|
50
|
+
|
|
51
|
+
> NeoGuidebook 已迁移到新接口:注册走 `SapdonServerUI.registerPage`(`panelId = sapdon_ui:<name>`),书拆为 `内容面板 + 按键面板`,导航/章节按钮使用 `SapdonTexturedButton`(模板 `server_form.sapdon_textured_button`),不再依赖旧 `ServerUISystem`/`sapdon_form_button_factory`。
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. NeoGuidebook 类
|
|
56
|
+
|
|
57
|
+
用于创建指南书 UI 系统。
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { NeoGuidebook } from '@sapdon/core'
|
|
61
|
+
|
|
62
|
+
const book = new NeoGuidebook(identifier, path, size?, options?)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 构造参数
|
|
66
|
+
|
|
67
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
68
|
+
|------|------|------|--------|------|
|
|
69
|
+
| `identifier` | `string` | 是 | — | 格式 `"命名空间:名称"`,如 `"my_mod:guidebook"` |
|
|
70
|
+
| `path` | `string` | 是 | — | UI 文件路径,通常 `"ui/"` |
|
|
71
|
+
| `size` | `[number, number]` | 否 | `[320, 207]` | 面板像素尺寸 |
|
|
72
|
+
| `options` | `object` | 否 | `{}` | 可选配置(见下文) |
|
|
73
|
+
|
|
74
|
+
### options 配置项
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
{
|
|
78
|
+
debug?: boolean // 是否输出调试信息
|
|
79
|
+
buttons?: {
|
|
80
|
+
prev?: { visible: boolean } // 上一页按钮
|
|
81
|
+
next?: { visible: boolean } // 下一页按钮
|
|
82
|
+
home?: { visible: boolean } // 首页按钮
|
|
83
|
+
close?: { visible: boolean } // 关闭按钮
|
|
84
|
+
}
|
|
85
|
+
textures?: {
|
|
86
|
+
prevDefault?: string // 上一页默认纹理
|
|
87
|
+
prevHover?: string // 上一页悬停纹理
|
|
88
|
+
prevPressed?: string // 上一页按压纹理
|
|
89
|
+
nextDefault?: string // 下一页默认纹理
|
|
90
|
+
nextHover?: string // 下一页悬停纹理
|
|
91
|
+
nextPressed?: string // 下一页按压纹理
|
|
92
|
+
homeDefault?: string // 首页默认纹理
|
|
93
|
+
homeHover?: string // 首页悬停纹理
|
|
94
|
+
homePressed?: string // 首页按压纹理
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 方法
|
|
100
|
+
|
|
101
|
+
#### addDoublePageStack(page_id, left_page, right_page)
|
|
102
|
+
|
|
103
|
+
注册一个双页跨页(左右两页同时显示)。
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
book.addDoublePageStack(
|
|
107
|
+
'page_index0', // page_id: string — 唯一标识,用于 body() 跳转
|
|
108
|
+
leftPanel, // left_page: Panel — NeoGuidebookPage.getPanel()
|
|
109
|
+
rightPanel, // right_page: Panel
|
|
110
|
+
size?: [string, string] // 可选,左右比例,默认 ["50%","50%"]
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### addSinglePageStack(page_id, page)
|
|
115
|
+
|
|
116
|
+
注册一个单页(占满整个表单宽度)。
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
book.addSinglePageStack(
|
|
120
|
+
'page_index7', // page_id: string
|
|
121
|
+
pagePanel, // page: Panel
|
|
122
|
+
size?: [string, string] // 可选尺寸
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### addCustomButton(config)
|
|
127
|
+
|
|
128
|
+
添加自定义按钮。
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
book.addCustomButton({
|
|
132
|
+
id: 'my_button', // 按钮 ID
|
|
133
|
+
defaultTexture: 'textures/ui/...',
|
|
134
|
+
hoverTexture?: 'textures/ui/...',
|
|
135
|
+
pressedTexture?: 'textures/ui/...',
|
|
136
|
+
anchorFrom?: 'bottom_left', // 锚点
|
|
137
|
+
anchorTo?: 'bottom_left',
|
|
138
|
+
offset?: [number, number],
|
|
139
|
+
size?: [number | string, number | string]
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### getPageIds()
|
|
144
|
+
|
|
145
|
+
获取所有已注册页面的 ID 数组。
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const ids: string[] = book.getPageIds()
|
|
149
|
+
// → ["page_index0", "page_index1", ...]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### getPageCount()
|
|
153
|
+
|
|
154
|
+
获取页面总数。
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const count: number = book.getPageCount()
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 3. NeoGuidebookPage 类
|
|
163
|
+
|
|
164
|
+
用于构建单个页面的内容。
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { NeoGuidebookPage } from '@sapdon/core'
|
|
168
|
+
|
|
169
|
+
const page = new NeoGuidebookPage(id, size?)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 构造参数
|
|
173
|
+
|
|
174
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
175
|
+
|------|------|------|--------|------|
|
|
176
|
+
| `id` | `string` | 是 | — | 页面唯一 ID |
|
|
177
|
+
| `size` | `[string, string]` | 否 | `["100%","100%"]` | 页面尺寸,百分比格式 |
|
|
178
|
+
|
|
179
|
+
### 布局方法
|
|
180
|
+
|
|
181
|
+
所有方法返回 `this`,支持链式调用。
|
|
182
|
+
|
|
183
|
+
#### addBookText(text, size?)
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
page.addBookText(
|
|
187
|
+
'这是正文内容', // text: string
|
|
188
|
+
['100%', '70%'] // size?: [string, string]
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### addCategoryTitle(title, size?)
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
page.addCategoryTitle(
|
|
196
|
+
'架构概述', // title: string
|
|
197
|
+
['100%', '15%'] // size?: [string, string]
|
|
198
|
+
)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### addBookTitleBar(text, size?)
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
page.addBookTitleBar(
|
|
205
|
+
'欢迎使用手册', // text: string
|
|
206
|
+
['100%', '15%'] // size?: [string, string]
|
|
207
|
+
)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### addEmptySpace(size?)
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
page.addEmptySpace(['100%', '5%'])
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### addDivider(size?)
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
page.addDivider(['100%', '3%'])
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### addRecipeGrid(row, col, items, size?)
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
page.addRecipeGrid(
|
|
226
|
+
2, // row: number
|
|
227
|
+
3, // col: number
|
|
228
|
+
['textures/items/iron_ingot', ...], // items: string[]
|
|
229
|
+
['100%', '30%'] // size?: [string, string]
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### addBookCategory(title, row, col, buttons, size?)
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
page.addBookCategory(
|
|
237
|
+
'物品分类', // title: string
|
|
238
|
+
2, // row: number
|
|
239
|
+
3, // col: number
|
|
240
|
+
[{ id: 'tools', texture: '...' }], // buttons
|
|
241
|
+
['100%', '60%'] // size?: [string, string]
|
|
242
|
+
)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
#### addChapter(name, texture)
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
page.addChapter('架构概述', 'textures/items/map')
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### addChapters(chapters)
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
page.addChapters([
|
|
255
|
+
{ chapter_name: '架构概述', chapter_texture: 'textures/items/map' },
|
|
256
|
+
{ chapter_name: '核心类', chapter_texture: 'textures/items/iron_ingot' },
|
|
257
|
+
])
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### addControl(control)
|
|
261
|
+
|
|
262
|
+
添加任意自定义 UI 控件(透传内部 StackPanel,可放任何 `UIElement` 或原生 JSON 控件对象)。
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
page.addControl(
|
|
266
|
+
new Label('my_label', undefined)
|
|
267
|
+
.setText(new Text().setText('自定义文字').setColor([0, 0, 0]))
|
|
268
|
+
)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### addStack(size, control, debug?)
|
|
272
|
+
|
|
273
|
+
添加自定义控件并指定占位尺寸(透传 `StackPanel.addStack`)。
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
page.addStack(
|
|
277
|
+
['100%', '20%'],
|
|
278
|
+
new Image('my_img', undefined).setSprite(new Sprite().setTexture('textures/items/iron_ingot'))
|
|
279
|
+
)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### buildChapterList(prefix?)
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
page.buildChapterList() // 默认前缀 "item",生成 item_N_button
|
|
286
|
+
page.buildChapterList("sub") // 多级目录:生成 sub_N_button,避免按钮 id 全局冲突
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`prefix` 决定目录按钮的绑定键名:`${prefix}_${index}_button`。单本书只有一个目录页时用默认值;要加子目录/二级目录,不同级别传不同前缀。
|
|
290
|
+
|
|
291
|
+
#### getPanel()
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
const panel = page.getPanel()
|
|
295
|
+
book.addDoublePageStack('page_0', panel, rightPanel)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### clear()
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
page.clear()
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 4. NeoGuidebookBridge 类
|
|
307
|
+
|
|
308
|
+
运行时导航管理器,封装了 ActionFormData 的显示和页面切换逻辑。
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { NeoGuidebookBridge } from '<path>/page_bridge'
|
|
312
|
+
|
|
313
|
+
const bridge = new NeoGuidebookBridge(uiName, pageIds, options?)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### 构造参数
|
|
317
|
+
|
|
318
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
319
|
+
|------|------|------|------|
|
|
320
|
+
| `uiName` | `string` | 是 | 书名字,必须与 `title()` 一致 |
|
|
321
|
+
| `pageIds` | `string[]` | 是 | 页面 ID 列表,来自 `getPageIds()` |
|
|
322
|
+
| `options` | `object` | 否 | `{ debug: boolean }` |
|
|
323
|
+
|
|
324
|
+
### 方法
|
|
325
|
+
|
|
326
|
+
#### show(player, startIndex)
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
bridge.show(player, 0) // player: Player, startIndex: number
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### onPage(pageId, callbacks)
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
bridge.onPage('page_index0', {
|
|
336
|
+
onEnter: (pageId: string, index: number) => { /* 进入页面时调用 */ },
|
|
337
|
+
onLeave: (pageId: string, index: number) => { /* 离开页面时调用 */ },
|
|
338
|
+
})
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 内置按钮映射
|
|
342
|
+
|
|
343
|
+
| ActionForm 按钮文字 | 对应 JSON UI 控件 | 行为 |
|
|
344
|
+
|-------------------|------------------|------|
|
|
345
|
+
| `"prev_button"` | 上一页按钮 | `currentIndex--` |
|
|
346
|
+
| `"next_button"` | 下一页按钮 | `currentIndex++` |
|
|
347
|
+
| `"home_button"` | 首页按钮 | `currentIndex = 0` |
|
|
348
|
+
| `"item_X_button"` | 章节选择按钮 | `currentIndex = X+1` |
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## 5. ItemComponent 辅助
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { ItemComponent } from '@sapdon/core'
|
|
356
|
+
|
|
357
|
+
// 设置自定义物品组件(指南书的核心)
|
|
358
|
+
ItemComponent.setCustomComponentV2('sapdon:neo_guibook', {})
|
|
359
|
+
|
|
360
|
+
// 其他物品组件
|
|
361
|
+
ItemComponent.setMaxStackSize(1)
|
|
362
|
+
ItemComponent.setDisplayName('我的手册')
|
|
363
|
+
ItemComponent.setInteractButton('打开')
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### setCustomComponentV2(componentName, options)
|
|
367
|
+
|
|
368
|
+
参数 `componentName` 必须与运行时 `registerCustomComponent()` 注册的名字一致。这个值也会出现在物品 JSON 的 `components` 中。
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 6. page_ids.json 生成
|
|
373
|
+
|
|
374
|
+
`main.ts` 中调用 `getPageIds()` 后将结果写入文件,供运行时脚本使用:
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
const pageIds: string[] = neo_guidebook.getPageIds()
|
|
378
|
+
fs.writeFileSync(
|
|
379
|
+
path.join(process.cwd(), 'scripts', 'page_ids.json'),
|
|
380
|
+
JSON.stringify(pageIds, null, 2)
|
|
381
|
+
)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
生成的 `page_ids.json` 示例:
|
|
385
|
+
|
|
386
|
+
```json
|
|
387
|
+
["page_index0", "page_index1", "page_index2", "page_index3"]
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## 7. 运行时注册
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// registry.ts — v2 API
|
|
396
|
+
import { system, world } from "@minecraft/server"
|
|
397
|
+
import { GuiBookItemComponent } from "./items/gui_book"
|
|
398
|
+
|
|
399
|
+
let registered = false
|
|
400
|
+
|
|
401
|
+
system.beforeEvents.startup.subscribe((initEvent: StartupEvent) => {
|
|
402
|
+
if (registered) return
|
|
403
|
+
registered = true
|
|
404
|
+
initEvent.itemComponentRegistry.registerCustomComponent(
|
|
405
|
+
"sapdon:neo_guibook",
|
|
406
|
+
GuiBookItemComponent
|
|
407
|
+
)
|
|
408
|
+
})
|
|
409
|
+
```
|