sapdon 3.5.0 → 3.5.2

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.
Files changed (51) hide show
  1. package/README.md +6 -4
  2. package/doc/dev/core.md +2 -2
  3. package/doc/dev/ui-architecture.md +3 -3
  4. package/doc/guidebook.md +10 -2
  5. package/doc/user/faq.md +3 -15
  6. package/doc/user/quick-start.md +7 -4
  7. package/package.json +1 -1
  8. package/prod/cli/start.js +1 -1
  9. package/prod/core/index.d.ts +15 -160
  10. package/prod/core/index.js +1 -1
  11. package/prod/templates/js_sapdon/build.config +24 -0
  12. package/prod/templates/js_sapdon/main.mjs +4 -0
  13. package/prod/templates/js_sapdon/mod.info +7 -0
  14. package/prod/templates/js_sapdon/pack_icon.png +0 -0
  15. package/prod/templates/js_sapdon/package.json +21 -0
  16. package/prod/templates/js_sapdon/res/animations/animation_item.animation.json +34 -0
  17. package/prod/templates/js_sapdon/res/animations/large_item.animation.json +27 -0
  18. package/prod/templates/js_sapdon/res/models/blocks/crop.geo.json +48 -0
  19. package/prod/templates/js_sapdon/res/models/blocks/flipbook_item.geo.json +3160 -0
  20. package/prod/templates/js_sapdon/res/models/entity/animation/animation_item.geo.json +26 -0
  21. package/prod/templates/js_sapdon/res/models/entity/animation/large_item.geo.json +28 -0
  22. package/prod/templates/js_sapdon/res/textures/blocks/none.png +0 -0
  23. package/prod/templates/js_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  24. package/prod/templates/js_sapdon/res/textures/blocks/test_log_top.png +0 -0
  25. package/prod/templates/js_sapdon/res/textures/items/masterball.png +0 -0
  26. package/prod/templates/js_sapdon/scripts/custom_components/cropComponent.js +50 -0
  27. package/prod/templates/js_sapdon/scripts/custom_components/items/gui_book.js +37 -0
  28. package/prod/templates/js_sapdon/scripts/custom_components/registry.js +25 -0
  29. package/prod/templates/js_sapdon/scripts/index.js +1 -0
  30. package/prod/templates/ts_sapdon/build.config +24 -0
  31. package/prod/templates/ts_sapdon/main.ts +15 -0
  32. package/prod/templates/ts_sapdon/mod.info +7 -0
  33. package/prod/templates/ts_sapdon/pack_icon.png +0 -0
  34. package/prod/templates/ts_sapdon/package.json +21 -0
  35. package/prod/templates/ts_sapdon/res/animations/animation_item.animation.json +34 -0
  36. package/prod/templates/ts_sapdon/res/animations/large_item.animation.json +27 -0
  37. package/prod/templates/ts_sapdon/res/models/blocks/crop.geo.json +48 -0
  38. package/prod/templates/ts_sapdon/res/models/blocks/flipbook_item.geo.json +3160 -0
  39. package/prod/templates/ts_sapdon/res/models/entity/animation/animation_item.geo.json +26 -0
  40. package/prod/templates/ts_sapdon/res/models/entity/animation/large_item.geo.json +28 -0
  41. package/prod/templates/ts_sapdon/res/models/entity/dummy.geo.json +24 -0
  42. package/prod/templates/ts_sapdon/res/models/entity/falling_block.geo.json +35 -0
  43. package/prod/templates/ts_sapdon/res/textures/blocks/none.png +0 -0
  44. package/prod/templates/ts_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  45. package/prod/templates/ts_sapdon/res/textures/blocks/test_log_top.png +0 -0
  46. package/prod/templates/ts_sapdon/res/textures/items/masterball.png +0 -0
  47. package/prod/templates/ts_sapdon/scripts/index.ts +14 -0
  48. package/prod/templates/ts_sapdon/tsconfig.json +117 -0
  49. package/doc/user/api/neo-guidebook.md +0 -409
  50. package/doc/user/tutorials/neo-guidebook-experience.md +0 -381
  51. package/doc/user/tutorials/neo-guidebook.md +0 -640
@@ -0,0 +1,26 @@
1
+ {
2
+ "format_version": "1.12.0",
3
+ "minecraft:geometry": [
4
+ {
5
+ "description": {
6
+ "identifier": "geometry.animation_item",
7
+ "texture_width": 32,
8
+ "texture_height": 32,
9
+ "visible_bounds_width": 5,
10
+ "visible_bounds_height": 3.5,
11
+ "visible_bounds_offset": [0, 1.25, 0]
12
+ },
13
+ "bones": [
14
+ {
15
+ "name": "body",
16
+ "pivot": [0, 0, 0]
17
+ },
18
+ {
19
+ "name": "rightitem",
20
+ "parent": "body",
21
+ "pivot": [-0.3, 8, 0]
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "format_version": "1.16.0",
3
+ "minecraft:geometry": [
4
+ {
5
+ "description": {
6
+ "identifier": "geometry.large_item",
7
+ "texture_width": 16,
8
+ "texture_height": 16,
9
+ "visible_bounds_width": 2,
10
+ "visible_bounds_height": 1.5,
11
+ "visible_bounds_offset": [0, 0.25, 0]
12
+ },
13
+ "bones": [
14
+ {
15
+ "name": "rightitem",
16
+ "pivot": [0, 0, 0],
17
+ "texture_meshes": [
18
+ {
19
+ "texture": "default",
20
+ "position": [0, 0, 0],
21
+ "local_pivot": [8, 0, 8]
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "format_version": "1.12.0",
3
+ "minecraft:geometry": [
4
+ {
5
+ "description": {
6
+ "identifier": "geometry.dummy",
7
+ "texture_width": 16,
8
+ "texture_height": 16,
9
+ "visible_bounds_width": 1,
10
+ "visible_bounds_height": 1,
11
+ "visible_bounds_offset": [0, 0, 0]
12
+ },
13
+ "bones": [
14
+ {
15
+ "name": "dummy",
16
+ "pivot": [0, 0, 0],
17
+ "locators": {
18
+ "locator": [0, 0, 0]
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "format_version": "1.12.0",
3
+ "minecraft:geometry": [
4
+ {
5
+ "description": {
6
+ "identifier": "geometry.falling_block",
7
+ "texture_width": 16,
8
+ "texture_height": 16,
9
+ "visible_bounds_width": 3,
10
+ "visible_bounds_height": 3,
11
+ "visible_bounds_offset": [0, 0.5, 0]
12
+ },
13
+ "bones": [
14
+ {
15
+ "name": "bb_main",
16
+ "pivot": [0, 0, 0],
17
+ "cubes": [
18
+ {
19
+ "origin": [-8, 0, -8],
20
+ "size": [16, 16, 16],
21
+ "uv": {
22
+ "north": {"uv": [0, 0], "uv_size": [16, 16]},
23
+ "east": {"uv": [0, 0], "uv_size": [16, 16]},
24
+ "south": {"uv": [0, 0], "uv_size": [16, 16]},
25
+ "west": {"uv": [0, 0], "uv_size": [16, 16]},
26
+ "up": {"uv": [16, 16], "uv_size": [-16, -16]},
27
+ "down": {"uv": [16, 16], "uv_size": [-16, -16]}
28
+ }
29
+ }
30
+ ]
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ }
@@ -0,0 +1,14 @@
1
+ import {
2
+ MinecraftMain,
3
+ MinecraftGameInstance,
4
+ registerBuiltinComponents,
5
+ } from '@sapdon/runtime'
6
+
7
+ import './custom_components/index.js'
8
+
9
+ registerBuiltinComponents()
10
+
11
+ @MinecraftMain
12
+ export class Main extends MinecraftGameInstance {
13
+
14
+ }
@@ -0,0 +1,117 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Visit https://aka.ms/tsconfig to read more about this file */
4
+ /* Projects */
5
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
6
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
7
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
8
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
9
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
10
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
11
+ /* Language and Environment */
12
+ "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
13
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
14
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
15
+ "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
16
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
17
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
18
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
19
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
20
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
21
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
22
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
23
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
24
+ /* Modules */
25
+ "module": "NodeNext", /* Specify what module code is generated. */
26
+ "rootDir": "./", /* Specify the root folder within your source files. */
27
+ "moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */
28
+ "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
29
+ // "paths": {
30
+ // "@core/*": [
31
+ // "sapdon/core/*"
32
+ // ],
33
+ // "@cli/*": [
34
+ // "sapdon/cli/*"
35
+ // ]
36
+ // }, /* Specify a set of entries that re-map imports to additional lookup locations. */
37
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
38
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
39
+ "types": [
40
+ "@minecraft/server",
41
+ "@minecraft/server-ui",
42
+ "node"
43
+ ], /* Specify type package names to be included without being referenced in a source file. */
44
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
45
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
46
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
47
+ // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
48
+ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
49
+ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
50
+ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
51
+ // "noUncheckedSideEffectImports": true, /* Check side effect imports. */
52
+ // "resolveJsonModule": true, /* Enable importing .json files. */
53
+ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
54
+ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
55
+ /* JavaScript Support */
56
+ "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
57
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
58
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
59
+ /* Emit */
60
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
61
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
62
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
63
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
64
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
65
+ // "noEmit": true, /* Disable emitting files from a compilation. */
66
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
67
+ "outDir": "./.tmp", /* Specify an output folder for all emitted files. */
68
+ // "removeComments": true, /* Disable emitting comments. */
69
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
70
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
71
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
72
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
73
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
74
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
75
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
76
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
77
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
78
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
79
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
80
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
81
+ /* Interop Constraints */
82
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
83
+ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
84
+ // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
85
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
86
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
87
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
88
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
89
+ /* Type Checking */
90
+ "strict": true, /* Enable all strict type-checking options. */
91
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
92
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
93
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
94
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
95
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
96
+ // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
97
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
98
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
99
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
100
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
101
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
102
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
103
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
104
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
105
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
106
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
107
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
108
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
109
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
110
+ /* Completeness */
111
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
112
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
113
+ },
114
+ "exclude": [
115
+ "dev"
116
+ ]
117
+ }
@@ -1,409 +0,0 @@
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`/`Guidebook` 已移除。
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
- ```