sapdon 3.2.2 → 3.3.3

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 (68) hide show
  1. package/README.md +245 -121
  2. package/doc/dev/architecture.md +415 -0
  3. package/doc/dev/cli.md +467 -0
  4. package/doc/dev/core.md +717 -0
  5. package/doc/dev/oc.md +582 -0
  6. package/doc/user/api/biome.md +558 -0
  7. package/doc/user/api/block.md +945 -0
  8. package/doc/user/api/entity.md +685 -0
  9. package/doc/user/api/extra.md +231 -0
  10. package/doc/user/api/item.md +896 -0
  11. package/doc/user/api/recipe.md +427 -0
  12. package/doc/user/api/texture.md +181 -0
  13. package/doc/user/config/build-config.md +84 -0
  14. package/doc/user/config/mod-info.md +33 -0
  15. package/doc/user/faq.md +160 -0
  16. package/doc/user/quick-start.md +108 -0
  17. package/doc/user/tutorials/block.md +463 -0
  18. package/doc/user/tutorials/entity.md +356 -0
  19. package/doc/user/tutorials/item.md +449 -0
  20. package/doc/user/tutorials/recipe.md +278 -0
  21. package/package.json +4 -3
  22. package/prod/cli/index.js +1 -1
  23. package/prod/cli/start.js +1 -1458
  24. package/prod/core/index.d.ts +3290 -2150
  25. package/prod/core/index.js +1 -59015
  26. package/prod/core/package.json +7 -0
  27. package/prod/oc/index.d.ts +348 -108
  28. package/prod/oc/index.js +1 -1
  29. package/prod/oc/package.json +7 -0
  30. package/prod/utils/index.d.ts +20 -2
  31. package/prod/utils/index.js +1 -1
  32. package/prod/utils/package.json +7 -0
  33. package/doc/BlockAPI.md +0 -145
  34. package/doc/api.md +0 -128
  35. package/doc/oc/index.md +0 -0
  36. package/doc/sapdon-ts.md +0 -64
  37. package/src/templates/js_sapdon/build.config +0 -23
  38. package/src/templates/js_sapdon/main.mjs +0 -4
  39. package/src/templates/js_sapdon/mod.info +0 -7
  40. package/src/templates/js_sapdon/pack_icon.png +0 -0
  41. package/src/templates/js_sapdon/package.json +0 -20
  42. package/src/templates/js_sapdon/res/animations/animation_item.animation.json +0 -34
  43. package/src/templates/js_sapdon/res/animations/large_item.animation.json +0 -27
  44. package/src/templates/js_sapdon/res/models/blocks/crop.geo.json +0 -48
  45. package/src/templates/js_sapdon/res/models/entity/animation/animation_item.geo.json +0 -26
  46. package/src/templates/js_sapdon/res/models/entity/animation/large_item.geo.json +0 -28
  47. package/src/templates/js_sapdon/res/textures/blocks/none.png +0 -0
  48. package/src/templates/js_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  49. package/src/templates/js_sapdon/res/textures/blocks/test_log_top.png +0 -0
  50. package/src/templates/js_sapdon/res/textures/items/masterball.png +0 -0
  51. package/src/templates/js_sapdon/scripts/custom_components/cropComponent.js +0 -50
  52. package/src/templates/js_sapdon/scripts/custom_components/items/gui_book.js +0 -37
  53. package/src/templates/js_sapdon/scripts/custom_components/registry.js +0 -25
  54. package/src/templates/js_sapdon/scripts/index.js +0 -0
  55. package/src/templates/ts_sapdon/build.config +0 -23
  56. package/src/templates/ts_sapdon/main.ts +0 -11
  57. package/src/templates/ts_sapdon/mod.info +0 -7
  58. package/src/templates/ts_sapdon/pack_icon.png +0 -0
  59. package/src/templates/ts_sapdon/package.json +0 -20
  60. package/src/templates/ts_sapdon/res/models/blocks/crop.geo.json +0 -48
  61. package/src/templates/ts_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  62. package/src/templates/ts_sapdon/res/textures/blocks/test_log_top.png +0 -0
  63. package/src/templates/ts_sapdon/res/textures/items/masterball.png +0 -0
  64. package/src/templates/ts_sapdon/scripts/components/cropComponent.ts +0 -44
  65. package/src/templates/ts_sapdon/scripts/components/items/guiBook.ts +0 -36
  66. package/src/templates/ts_sapdon/scripts/components/registry.ts +0 -24
  67. package/src/templates/ts_sapdon/scripts/index.ts +0 -7
  68. package/src/templates/ts_sapdon/tsconfig.json +0 -117
@@ -0,0 +1,278 @@
1
+ # 配方创建教程
2
+
3
+ 本文档介绍如何使用 sapdon 框架创建各类 Minecraft 配方。
4
+
5
+ > 开始前请确保已完成[快速入门](../quick-start.md)中的环境搭建。
6
+
7
+ ## 导入
8
+
9
+ 所有配方 API 均从 `@sapdon/core` 导入:
10
+
11
+ ```typescript
12
+ import { RecipeAPI, registry } from '@sapdon/core'
13
+ ```
14
+
15
+ 完成后调用 `registry.submit()` 提交所有注册数据。
16
+
17
+ ---
18
+
19
+ ## 1. 有序配方 — 简写
20
+
21
+ `RecipeAPI.registerSimpleShaped()` 通过 pattern(图案)、key(键映射)和 output(输出)快速创建有序配方。
22
+
23
+ ```typescript
24
+ import { RecipeAPI, registry } from '@sapdon/core'
25
+
26
+ RecipeAPI.registerSimpleShaped(
27
+ 'sapdon:diamond_sword',
28
+ 'minecraft:diamond_sword',
29
+ [' X ', ' X ', ' Y '],
30
+ {
31
+ X: { item: 'minecraft:diamond' },
32
+ Y: { item: 'minecraft:stick' }
33
+ }
34
+ ).tags(['crafting_table'])
35
+
36
+ registry.submit()
37
+ ```
38
+
39
+ **参数说明**
40
+
41
+ | 参数 | 类型 | 说明 |
42
+ |------|------|------|
43
+ | `identifier` | `string` | 配方唯一标识符,格式 `命名空间:名称` |
44
+ | `output` | `string` | 输出物品 ID |
45
+ | `pattern` | `string[]` | 3 行图案,每行 3 字符 |
46
+ | `key` | `object` | 字符到物品的映射 |
47
+
48
+ 方法自动设置 `crafting_table` 标签。`.tags()` 链式调用可覆盖或追加标签。
49
+
50
+ ---
51
+
52
+ ## 2. 有序配方 — 链式
53
+
54
+ `RecipeAPI.registerShaped()` 返回 `AddonRecipeShaped` 实例,支持完整的链式调用。
55
+
56
+ ```typescript
57
+ import { RecipeAPI, registry } from '@sapdon/core'
58
+
59
+ RecipeAPI.registerShaped('sapdon:custom_helmet')
60
+ .key({
61
+ X: { item: 'minecraft:iron_ingot' }
62
+ })
63
+ .pattern(['XXX', 'X X', ' '])
64
+ .output('sapdon:custom_helmet')
65
+ .tags(['crafting_table'])
66
+
67
+ registry.submit()
68
+ ```
69
+
70
+ **可用链式方法**
71
+
72
+ | 方法 | 说明 |
73
+ |------|------|
74
+ | `.key(map)` | 设置字符到物品的键映射 |
75
+ | `.pattern(rows)` | 设置 3 行图案数组 |
76
+ | `.output(item)` | 设置输出物品,支持 `string` 或 `{ item, count }` 对象 |
77
+ | `.priority(num)` | 设置优先级(数值越小优先级越高) |
78
+ | `.assumeSymmetry()` | 启用对称假设 |
79
+ | `.tags(tags[])` | 设置配方标签数组 |
80
+
81
+ ```typescript
82
+ // 带数量和优先级的完整示例
83
+ RecipeAPI.registerShaped('sapdon:custom_block')
84
+ .key({
85
+ A: { item: 'minecraft:diamond' },
86
+ B: { item: 'minecraft:iron_ingot' }
87
+ })
88
+ .pattern(['AAA', 'ABA', 'AAA'])
89
+ .output({ item: 'sapdon:custom_block', count: 4 })
90
+ .priority(0)
91
+ .tags(['crafting_table'])
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 3. 无序配方 — 简写
97
+
98
+ `RecipeAPI.registerSimpleShapeless()` 通过 ingredients 数组快速创建无序配方。
99
+
100
+ ```typescript
101
+ import { RecipeAPI, registry } from '@sapdon/core'
102
+
103
+ RecipeAPI.registerSimpleShapeless(
104
+ 'sapdon:custom_ingot',
105
+ 'sapdon:custom_ingot',
106
+ [
107
+ { item: 'minecraft:iron_ingot' },
108
+ { item: 'minecraft:gold_ingot' }
109
+ ]
110
+ ).tags(['crafting_table'])
111
+
112
+ registry.submit()
113
+ ```
114
+
115
+ **参数说明**
116
+
117
+ | 参数 | 类型 | 说明 |
118
+ |------|------|------|
119
+ | `identifier` | `string` | 配方唯一标识符 |
120
+ | `output` | `string` | 输出物品 ID |
121
+ | `ingredients` | `object[]` | 原料数组,无需顺序 |
122
+
123
+ 原料支持标签引用实现宽匹配:
124
+
125
+ ```typescript
126
+ RecipeAPI.registerSimpleShapeless(
127
+ 'sapdon:leather_helmet',
128
+ 'minecraft:leather_helmet',
129
+ [
130
+ { item: 'minecraft:leather' },
131
+ { item: 'minecraft:leather' },
132
+ { item: 'minecraft:leather' },
133
+ { item: 'minecraft:leather' },
134
+ { item: 'minecraft:leather' }
135
+ ]
136
+ ).tags(['crafting_table'])
137
+ ```
138
+
139
+ ---
140
+
141
+ ## 4. 无序配方 — 链式
142
+
143
+ `RecipeAPI.registerShapeless()` 返回 `AddonRecipeShapeless` 实例,支持链式调用。
144
+
145
+ ```typescript
146
+ import { RecipeAPI, registry } from '@sapdon/core'
147
+
148
+ RecipeAPI.registerShapeless('sapdon:mixed_ingot')
149
+ .ingredients([
150
+ { item: 'minecraft:iron_ingot' },
151
+ { item: 'minecraft:gold_ingot' },
152
+ { item: 'minecraft:diamond' }
153
+ ])
154
+ .output({ item: 'sapdon:mixed_ingot', count: 3 })
155
+ .tags(['crafting_table'])
156
+
157
+ registry.submit()
158
+ ```
159
+
160
+ **可用链式方法**
161
+
162
+ | 方法 | 说明 |
163
+ |------|------|
164
+ | `.ingredients(items[])` | 设置原料数组 |
165
+ | `.output(item)` | 设置输出物品 |
166
+ | `.priority(num)` | 设置优先级 |
167
+ | `.tags(tags[])` | 设置配方标签数组 |
168
+
169
+ 使用物品标签作为原料:
170
+
171
+ ```typescript
172
+ RecipeAPI.registerShapeless('sapdon:wooden_rod')
173
+ .ingredients([
174
+ { tag: 'minecraft:planks' },
175
+ { tag: 'minecraft:planks' }
176
+ ])
177
+ .output('sapdon:wooden_rod')
178
+ .tags(['crafting_table'])
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 5. 熔炉配方 — 简写
184
+
185
+ `RecipeAPI.registerSimpleFurnace()` 快速创建熔炉配方。
186
+
187
+ ```typescript
188
+ import { RecipeAPI, registry } from '@sapdon/core'
189
+
190
+ RecipeAPI.registerSimpleFurnace(
191
+ 'sapdon:cooked_ruby',
192
+ 'sapdon:ruby',
193
+ 'sapdon:raw_ruby'
194
+ ).tags(['furnace'])
195
+
196
+ registry.submit()
197
+ ```
198
+
199
+ **参数说明**
200
+
201
+ | 参数 | 类型 | 说明 |
202
+ |------|------|------|
203
+ | `identifier` | `string` | 配方唯一标识符 |
204
+ | `output` | `string` | 烧炼输出物品 ID |
205
+ | `input` | `string` | 烧炼输入物品 ID |
206
+
207
+ 方法自动设置 `furnace` 标签。
208
+
209
+ ---
210
+
211
+ ## 6. 熔炉配方 — 链式
212
+
213
+ `RecipeAPI.registerFurnace()` 返回 `AddonRecipeFurnace` 实例,支持链式调用。
214
+
215
+ ```typescript
216
+ import { RecipeAPI, registry } from '@sapdon/core'
217
+
218
+ RecipeAPI.registerFurnace('sapdon:smelt_ruby')
219
+ .input('sapdon:raw_ruby')
220
+ .output('sapdon:ruby')
221
+ .tags(['furnace'])
222
+
223
+ registry.submit()
224
+ ```
225
+
226
+ **可用链式方法**
227
+
228
+ | 方法 | 说明 |
229
+ |------|------|
230
+ | `.input(item, data?, count?)` | 设置输入物品,可选 data 和 count |
231
+ | `.output(item)` | 设置输出物品 |
232
+ | `.tags(tags[])` | 设置配方标签数组 |
233
+
234
+ ```typescript
235
+ // 带 data 值的熔炉配方
236
+ RecipeAPI.registerFurnace('sapdon:smelt_ore')
237
+ .input('minecraft:iron_ore', 0, 1)
238
+ .output('minecraft:iron_ingot')
239
+ .tags(['furnace', 'blast_furnace'])
240
+ ```
241
+
242
+ ---
243
+
244
+ ## 7. 配方标签
245
+
246
+ 配方标签决定配方可在哪些方块中使用。通过 `.tags()` 方法设置:
247
+
248
+ ```typescript
249
+ RecipeAPI.registerShaped('sapdon:example')
250
+ .pattern(['A', 'A', 'A'])
251
+ .key({ A: { item: 'minecraft:iron_ingot' } })
252
+ .output('sapdon:example')
253
+ .tags(['crafting_table'])
254
+ ```
255
+
256
+ ### 可用标签值
257
+
258
+ | 标签 | 适用方块 | 说明 |
259
+ |------|----------|------|
260
+ | `furnace` | 熔炉 | 标准熔炉烧炼配方 |
261
+ | `smoker` | 烟熏炉 | 食物烧炼配方 |
262
+ | `campfire` | 篝火 | 篝火烹饪配方 |
263
+ | `soul_campfire` | 灵魂篝火 | 灵魂篝火烹饪配方 |
264
+ | `crafting_table` | 工作台 | 工作台合成配方 |
265
+
266
+ 可通过 `RecipeTags` 常量引用:
267
+
268
+ ```typescript
269
+ import { RecipeAPI, registry, RecipeTags } from '@sapdon/core'
270
+
271
+ RecipeAPI.registerSimpleFurnace(
272
+ 'sapdon:cooked_beef',
273
+ 'minecraft:cooked_beef',
274
+ 'minecraft:beef'
275
+ ).tags([RecipeTags.Furnace, RecipeTags.smoker])
276
+ ```
277
+
278
+ > 注:`RecipeTags.smoker` 首字母小写,其余常量均为大写首字母。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapdon",
3
- "version": "3.2.2",
3
+ "version": "3.3.3",
4
4
  "scripts": {
5
5
  "build": "node scripts/build.cjs",
6
6
  "pub": "npm run build && npm publish"
@@ -20,6 +20,7 @@
20
20
  "devDependencies": {
21
21
  "@minecraft/server": "^2.0.0-beta.1.21.80-preview.20",
22
22
  "@minecraft/server-ui": "^1.3.0",
23
+ "@types/d3-array": "^3.2.1",
23
24
  "@types/lodash": "^4.17.16",
24
25
  "@types/node": "^22.14.0",
25
26
  "tsc-alias": "^1.8.13"
@@ -32,6 +33,7 @@
32
33
  "@rollup/plugin-typescript": "^12.1.2",
33
34
  "chalk": "^5.4.1",
34
35
  "commander": "^13.0.0",
36
+ "d3-array": "^3.2.4",
35
37
  "download-git-repo": "^3.0.2",
36
38
  "inquirer": "^12.3.1",
37
39
  "lodash": "^4.17.21",
@@ -46,7 +48,6 @@
46
48
  },
47
49
  "files": [
48
50
  "prod/**/*",
49
- "doc/**/*",
50
- "src/templates/**/*"
51
+ "doc/**/*"
51
52
  ]
52
53
  }
package/prod/cli/index.js CHANGED
@@ -1 +1 @@
1
- import e from"http";Symbol.metadata||(Symbol.metadata=Symbol("[[metadata]]"));const t=Symbol("isRawJSON");const r=["boolean","number"],n=["string","undefined"];function o(e,o){const i=typeof o;if(null===i)return null;if(n.includes(i))return o;if(r.includes(i))return JSON.rawJSON(o);if("object"===i)return JSON.isRawJSON(o)?o:function(e){return!0===e?.[t]}(o)?JSON.rawJSON(o.rawJSON):o;if("bigint"===i)return JSON.rawJSON(o.toString());throw new Error("Unexpected value")}const i={encode:e=>JSON.stringify(e,o),decode:JSON.parse};function s(e,t=i){return t.encode(e)}const a={port:49037},{port:c}=a;const{port:l}=a;const d=new class{cliServerHandlers=new Map;listening=!1;isListening(){return this.listening}bootstrap(){this.listening=!0;const t=e.createServer((async(e,t)=>{const r=this.cliServerHandlers.get((e.url??"/").slice(1));if(r){try{const{promise:t,resolve:n,reject:o}=Promise.withResolvers();let s=Buffer.alloc(0);e.on("data",(e=>s=Buffer.concat([s,e]))),e.on("end",(()=>{try{n(function(e,t=i){return t.decode(e)}(s))}catch(e){o(e)}})),await r(...await t)}catch(e){return console.error(e),t.writeHead(500),void t.end()}t.writeHead(200),t.end()}else t.writeHead(404),t.end()})).listen(l,(()=>console.log(`Dev Server listening on port ${l}`)));return t.on("error",(()=>this.listening=!1)),t}handle(e,t){this.cliServerHandlers.set(e,t)}getHandler(e){return this.cliServerHandlers.get(e)}interceptHandler(e,t){const r=t(this.getHandler(e)??Function.prototype);return this.cliServerHandlers.set(e,r),r}},u={call:async(e,...t)=>await async function(e,...t){try{await fetch(`http://localhost:${c}/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:s(t)})}catch(e){console.error(e),console.error("尝试在构建脚本中使用 server.startDevServer() 启动开发服务器")}}(e,...t)};export{u as client,d as devServer};
1
+ import e from"http";Symbol.metadata||(Symbol.metadata=Symbol("[[metadata]]"));const t=Symbol("isRawJSON");const r=["boolean","number"],n=["string","undefined"];function o(e,o){const i=typeof o;if(null===i)return null;if(n.includes(i))return o;if(r.includes(i))return JSON.rawJSON(o);if("object"===i)return JSON.isRawJSON(o)?o:function(e){return!0===e?.[t]}(o)?JSON.rawJSON(o.rawJSON):o;if("bigint"===i)return JSON.rawJSON(o.toString());throw new Error("Unexpected value")}const i={encode:e=>JSON.stringify(e,o),decode:JSON.parse};function s(e,t=i){return t.encode(e)}const a={port:49037},{port:c}=a;const{port:l}=a;const d=new class{cliServerHandlers=new Map;listening=!1;isListening(){return this.listening}bootstrap(){this.listening=!0;const t=e.createServer(async(e,t)=>{const r=this.cliServerHandlers.get((e.url??"/").slice(1));if(r){try{const{promise:t,resolve:n,reject:o}=Promise.withResolvers();let s=Buffer.alloc(0);e.on("data",e=>s=Buffer.concat([s,e])),e.on("end",()=>{try{n(function(e,t=i){return t.decode(e)}(s))}catch(e){o(e)}}),await r(...await t)}catch(e){return console.error(e),t.writeHead(500),void t.end()}t.writeHead(200),t.end()}else t.writeHead(404),t.end()}).listen(l,()=>console.log(`Dev Server listening on port ${l}`));return t.on("error",()=>this.listening=!1),t}handle(e,t){this.cliServerHandlers.set(e,t)}getHandler(e){return this.cliServerHandlers.get(e)}interceptHandler(e,t){const r=t(this.getHandler(e)??Function.prototype);return this.cliServerHandlers.set(e,r),r}},u={call:async(e,...t)=>await async function(e,...t){try{await fetch(`http://localhost:${c}/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:s(t)})}catch(e){console.error(e),console.error("尝试在构建脚本中使用 server.startDevServer() 启动开发服务器")}}(e,...t)};export{u as client,d as devServer};