sapdon 2.0.2 → 2.1.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.
Files changed (283) hide show
  1. package/LICENSE +1 -1
  2. package/doc/BlockAPI.md +145 -0
  3. package/doc/api.md +1 -1
  4. package/doc/hello_sapdon/a9aad643f5609da73404d1f7f35fd5d0.png +0 -0
  5. package/doc/hello_sapdon/sapdon/344/275/277/347/224/250/346/225/231/347/250/213.md +159 -0
  6. package/examples/guidebook/build.config +33 -0
  7. package/examples/guidebook/dev/guidebook_BP/items/sapdon_test_guidebook.json +19 -0
  8. package/examples/{masterball/dev/masterball_BP/masterball_BP_1_20_20 → guidebook/dev/guidebook_BP}/manifest.json +63 -59
  9. package/examples/guidebook/dev/guidebook_BP/scripts/custom_components/cropComponent.js +50 -0
  10. package/examples/guidebook/dev/guidebook_BP/scripts/custom_components/items/gui_book.js +37 -0
  11. package/examples/guidebook/dev/guidebook_BP/scripts/custom_components/registry.js +20 -0
  12. package/examples/guidebook/dev/guidebook_BP/scripts/index.js +3 -0
  13. package/examples/guidebook/dev/guidebook_RP/blocks.json +3 -0
  14. package/examples/guidebook/dev/guidebook_RP/manifest.json +44 -0
  15. package/examples/guidebook/dev/guidebook_RP/models/blocks/crop.geo.json +48 -0
  16. package/examples/{masterball/dev/masterball_RP/masterball_RP_1_20_20.zip → guidebook/dev/guidebook_RP/pack_icon.png} +0 -0
  17. package/examples/guidebook/dev/guidebook_RP/textures/blocks/test_log_oak.png +0 -0
  18. package/examples/guidebook/dev/guidebook_RP/textures/blocks/test_log_top.png +0 -0
  19. package/examples/guidebook/dev/guidebook_RP/textures/flipbook_textures.json +1 -0
  20. package/examples/guidebook/dev/guidebook_RP/textures/item_texture.json +9 -0
  21. package/examples/guidebook/dev/guidebook_RP/textures/items/masterball.png +0 -0
  22. package/examples/guidebook/dev/guidebook_RP/textures/terrain_texture.json +14 -0
  23. package/examples/guidebook/dev/guidebook_RP/ui/_ui_defs.json +6 -0
  24. package/examples/guidebook/dev/guidebook_RP/ui/guidebook.json +581 -0
  25. package/examples/guidebook/dev/guidebook_RP/ui/server_form.json +91 -0
  26. package/examples/guidebook/main.mjs +66 -0
  27. package/examples/guidebook/mod.info +7 -0
  28. package/examples/{masterball/dev/masterball_BP/masterball_BP_1_20_20.zip → guidebook/pack_icon.png} +0 -0
  29. package/examples/guidebook/res/models/blocks/crop.geo.json +48 -0
  30. package/examples/guidebook/res/textures/blocks/test_log_oak.png +0 -0
  31. package/examples/guidebook/res/textures/blocks/test_log_top.png +0 -0
  32. package/examples/guidebook/res/textures/items/masterball.png +0 -0
  33. package/examples/guidebook/scripts/custom_components/cropComponent.js +50 -0
  34. package/examples/guidebook/scripts/custom_components/items/gui_book.js +37 -0
  35. package/examples/guidebook/scripts/custom_components/registry.js +20 -0
  36. package/examples/guidebook/scripts/index.js +3 -0
  37. package/examples/hello_sapdon/build.config +29 -0
  38. package/examples/hello_sapdon/main.mjs +3 -0
  39. package/examples/hello_sapdon/mod.info +7 -0
  40. package/examples/hello_sapdon/pack_icon.png +0 -0
  41. package/examples/hello_sapdon/res/models/blocks/crop.geo.json +48 -0
  42. package/examples/hello_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  43. package/examples/hello_sapdon/res/textures/blocks/test_log_top.png +0 -0
  44. package/examples/hello_sapdon/res/textures/items/masterball.png +0 -0
  45. package/examples/hello_sapdon/scripts/custom_components/cropComponent.js +50 -0
  46. package/examples/hello_sapdon/scripts/custom_components/items/gui_book.js +37 -0
  47. package/examples/hello_sapdon/scripts/custom_components/registry.js +25 -0
  48. package/examples/hello_sapdon/scripts/index.js +0 -0
  49. package/examples/masterball/build.config +1 -0
  50. package/examples/masterball/dev/masterball_1_20_30.mcaddon +0 -0
  51. package/examples/masterball/dev/masterball_BP/entities/sapdon_projectile_masterball.json +56 -55
  52. package/examples/masterball/dev/masterball_BP/manifest.json +59 -59
  53. package/examples/masterball/dev/masterball_BP/pack_icon.png +0 -0
  54. package/examples/masterball/dev/masterball_BP/recipes/masterball.json +25 -0
  55. package/examples/masterball/dev/masterball_BP_1_20_30.mcpack +0 -0
  56. package/examples/masterball/dev/masterball_RP/attachables/sapdon_caught_masterball.json +19 -0
  57. package/examples/masterball/dev/masterball_RP/manifest.json +43 -43
  58. package/examples/masterball/dev/masterball_RP/pack_icon.png +0 -0
  59. package/examples/masterball/dev/masterball_RP/textures/flipbook_textures.json +1 -0
  60. package/examples/masterball/dev/masterball_RP/ui/_ui_defs.json +3 -0
  61. package/examples/masterball/dev/masterball_RP_1_20_30.mcpack +0 -0
  62. package/examples/masterball/main.mjs +18 -1
  63. package/examples/masterball/pack_icon.png +0 -0
  64. package/examples/mob_chest/build.config +29 -0
  65. package/examples/mob_chest/dev/mob_chest_BP/blocks/mob_chest_chest.json +56 -0
  66. package/examples/mob_chest/dev/mob_chest_BP/entities/mob_chest_chest_entity.json +79 -0
  67. package/examples/mob_chest/dev/mob_chest_BP/manifest.json +64 -0
  68. package/examples/mob_chest/dev/mob_chest_BP/pack_icon.png +0 -0
  69. package/examples/mob_chest/dev/mob_chest_BP/scripts/custom_components/block/block_with_entity.js +46 -0
  70. package/examples/mob_chest/dev/mob_chest_BP/scripts/custom_components/block/cropComponent.js +50 -0
  71. package/examples/mob_chest/dev/mob_chest_BP/scripts/custom_components/items/gui_book.js +37 -0
  72. package/examples/mob_chest/dev/mob_chest_BP/scripts/custom_components/registry.js +25 -0
  73. package/examples/mob_chest/dev/mob_chest_BP/scripts/index.js +4 -0
  74. package/examples/mob_chest/dev/mob_chest_RP/animation_controllers/mob_chest.animation_controllers.json +30 -0
  75. package/examples/mob_chest/dev/mob_chest_RP/animations/animation_item.animation.json +34 -0
  76. package/examples/mob_chest/dev/mob_chest_RP/animations/large_item.animation.json +27 -0
  77. package/examples/mob_chest/dev/mob_chest_RP/animations/mob_chest.animation.json +64 -0
  78. package/examples/mob_chest/dev/mob_chest_RP/blocks.json +13 -0
  79. package/examples/mob_chest/dev/mob_chest_RP/entity/mob_chest_chest_entity.json +32 -0
  80. package/examples/mob_chest/dev/mob_chest_RP/manifest.json +44 -0
  81. package/examples/mob_chest/dev/mob_chest_RP/models/blocks/crop.geo.json +48 -0
  82. package/examples/mob_chest/dev/mob_chest_RP/models/blocks/cube.geo.json +35 -0
  83. package/examples/mob_chest/dev/mob_chest_RP/models/blocks/empty.geo.json +35 -0
  84. package/examples/mob_chest/dev/mob_chest_RP/models/entity/mob_chest.geo.json +98 -0
  85. package/examples/mob_chest/dev/mob_chest_RP/pack_icon.png +0 -0
  86. package/examples/mob_chest/dev/mob_chest_RP/textures/blocks/entity/double_normal.png +0 -0
  87. package/examples/mob_chest/dev/mob_chest_RP/textures/blocks/entity/none.png +0 -0
  88. package/examples/mob_chest/dev/mob_chest_RP/textures/blocks/entity/normal.png +0 -0
  89. package/examples/mob_chest/dev/mob_chest_RP/textures/blocks/test_log_oak.png +0 -0
  90. package/examples/mob_chest/dev/mob_chest_RP/textures/blocks/test_log_top.png +0 -0
  91. package/examples/mob_chest/dev/mob_chest_RP/textures/flipbook_textures.json +1 -0
  92. package/examples/mob_chest/dev/mob_chest_RP/textures/item_texture.json +9 -0
  93. package/examples/mob_chest/dev/mob_chest_RP/textures/items/masterball.png +0 -0
  94. package/examples/mob_chest/dev/mob_chest_RP/textures/terrain_texture.json +23 -0
  95. package/examples/mob_chest/dev/mob_chest_RP/ui/_ui_defs.json +3 -0
  96. package/examples/mob_chest/main.mjs +31 -0
  97. package/examples/mob_chest/mod.info +7 -0
  98. package/examples/mob_chest/pack_icon.png +0 -0
  99. package/examples/mob_chest/res/animation_controllers/mob_chest.animation_controllers.json +30 -0
  100. package/examples/mob_chest/res/animations/animation_item.animation.json +34 -0
  101. package/examples/mob_chest/res/animations/large_item.animation.json +27 -0
  102. package/examples/mob_chest/res/animations/mob_chest.animation.json +64 -0
  103. package/examples/mob_chest/res/models/blocks/crop.geo.json +48 -0
  104. package/examples/mob_chest/res/models/blocks/cube.geo.json +35 -0
  105. package/examples/mob_chest/res/models/blocks/empty.geo.json +35 -0
  106. package/examples/mob_chest/res/models/entity/mob_chest.geo.json +98 -0
  107. package/examples/mob_chest/res/textures/blocks/entity/double_normal.png +0 -0
  108. package/examples/mob_chest/res/textures/blocks/entity/none.png +0 -0
  109. package/examples/mob_chest/res/textures/blocks/entity/normal.png +0 -0
  110. package/examples/mob_chest/res/textures/blocks/test_log_oak.png +0 -0
  111. package/examples/mob_chest/res/textures/blocks/test_log_top.png +0 -0
  112. package/examples/mob_chest/res/textures/items/masterball.png +0 -0
  113. package/examples/mob_chest/resource/cube.bbmodel +1 -0
  114. package/examples/mob_chest/resource/flipbook_item.bbmodel +1 -0
  115. package/examples/mob_chest/resource/flipbook_item.geo.bbmodel +1 -0
  116. package/examples/mob_chest/resource/flipbook_item.geo.json +3124 -0
  117. package/examples/mob_chest/resource/mob_chest.bbmodel +1 -0
  118. package/examples/mob_chest/scripts/custom_components/block/block_with_entity.js +46 -0
  119. package/examples/mob_chest/scripts/custom_components/block/cropComponent.js +50 -0
  120. package/examples/mob_chest/scripts/custom_components/items/gui_book.js +37 -0
  121. package/examples/mob_chest/scripts/custom_components/registry.js +25 -0
  122. package/examples/mob_chest/scripts/index.js +4 -0
  123. package/examples/test/build.config +29 -0
  124. package/examples/test/dev/test_BP/blocks/sapdon_ore_cinnabar.json +15 -15
  125. package/examples/test/dev/test_BP/blocks/sapdon_test_block.json +15 -15
  126. package/examples/test/dev/test_BP/blocks/sapdon_test_crop.json +191 -191
  127. package/examples/test/dev/test_BP/blocks/sapdon_wire.json +102 -102
  128. package/examples/test/dev/test_BP/entities/sapdon_test_projectile.json +56 -55
  129. package/examples/test/dev/test_BP/feature_rules/ore_cinnabar_orefeatre_rule.json +52 -52
  130. package/examples/test/dev/test_BP/feature_rules/overworld_underground_titanite_ore_feature.json +52 -52
  131. package/examples/test/dev/test_BP/features/ore_cinnabar_ore_feature.json +16 -16
  132. package/examples/test/dev/test_BP/features/titanite_ore_feature.json +22 -22
  133. package/examples/test/dev/test_BP/items/sapdon_chest.json +22 -22
  134. package/examples/test/dev/test_BP/items/sapdon_test_book.json +19 -0
  135. package/examples/test/dev/test_BP/items/sapdon_test_food.json +25 -25
  136. package/examples/test/dev/test_BP/items/sapdon_test_item.json +30 -30
  137. package/examples/test/dev/test_BP/manifest.json +63 -59
  138. package/examples/test/dev/test_BP/recipes/sapdon_test_furnace.json +12 -12
  139. package/examples/test/dev/test_BP/scripts/custom_components/cropComponent.js +1 -10
  140. package/examples/test/dev/test_BP/scripts/custom_components/items/gui_book.js +37 -0
  141. package/examples/test/dev/test_BP/scripts/custom_components/registry.js +20 -0
  142. package/examples/test/dev/test_BP/scripts/index.js +4 -3
  143. package/examples/test/dev/test_RP/attachables/sapdon_chest.json +24 -24
  144. package/examples/test/dev/test_RP/blocks.json +42 -42
  145. package/examples/test/dev/test_RP/entity/sapdon_test_projectile.json +27 -27
  146. package/examples/test/dev/test_RP/manifest.json +43 -43
  147. package/examples/test/dev/test_RP/models/blocks/arcane_workbench.geo.json +105 -105
  148. package/examples/test/dev/test_RP/models/blocks/jar_normal.geo.json +46 -46
  149. package/examples/test/dev/test_RP/models/blocks/jar_normal_0.geo.json +58 -58
  150. package/examples/test/dev/test_RP/models/blocks/jar_normal_1.geo.json +58 -58
  151. package/examples/test/dev/test_RP/models/blocks/jar_normal_2.geo.json +58 -58
  152. package/examples/test/dev/test_RP/models/blocks/jar_normal_3.geo.json +58 -58
  153. package/examples/test/dev/test_RP/models/blocks/wire.geo.json +153 -153
  154. package/examples/test/dev/test_RP/textures/item_texture.json +788 -788
  155. package/examples/test/dev/test_RP/textures/items/seals/seal_breaker.png.mcmeta +5 -5
  156. package/examples/test/dev/test_RP/textures/items/seals/seal_butcher.png.mcmeta +5 -5
  157. package/examples/test/dev/test_RP/textures/items/seals/seal_empty.png.mcmeta +5 -5
  158. package/examples/test/dev/test_RP/textures/items/seals/seal_empty_advanced.png.mcmeta +5 -5
  159. package/examples/test/dev/test_RP/textures/items/seals/seal_fill.png.mcmeta +5 -5
  160. package/examples/test/dev/test_RP/textures/items/seals/seal_fill_advanced.png.mcmeta +5 -5
  161. package/examples/test/dev/test_RP/textures/items/seals/seal_guard.png.mcmeta +5 -5
  162. package/examples/test/dev/test_RP/textures/items/seals/seal_guard_advanced.png.mcmeta +5 -5
  163. package/examples/test/dev/test_RP/textures/items/seals/seal_harvest.png.mcmeta +5 -5
  164. package/examples/test/dev/test_RP/textures/items/seals/seal_lumber.png.mcmeta +5 -5
  165. package/examples/test/dev/test_RP/textures/items/seals/seal_pickup.png.mcmeta +5 -5
  166. package/examples/test/dev/test_RP/textures/items/seals/seal_pickup_advanced.png.mcmeta +5 -5
  167. package/examples/test/dev/test_RP/textures/items/seals/seal_provider.png.mcmeta +5 -5
  168. package/examples/test/dev/test_RP/textures/items/seals/seal_use.png.mcmeta +5 -5
  169. package/examples/test/dev/test_RP/textures/items/wand/cap_thaumium.png.mcmeta +11 -11
  170. package/examples/test/dev/test_RP/textures/items/wand/cap_void.png.mcmeta +11 -11
  171. package/examples/test/dev/test_RP/textures/items/wand/focus_pech.png.mcmeta +2 -2
  172. package/examples/test/dev/test_RP/textures/items/wand/focus_portablehole.png.mcmeta +2 -2
  173. package/examples/test/dev/test_RP/textures/items/wand/focus_primal.png.mcmeta +2 -2
  174. package/examples/test/dev/test_RP/textures/items/wand/focus_shard.png.mcmeta +2 -2
  175. package/examples/test/dev/test_RP/textures/items/wand/focus_warding.png.mcmeta +2 -2
  176. package/examples/test/dev/test_RP/textures/items/wand/rod_primal_mat.png.mcmeta +44 -44
  177. package/examples/test/dev/test_RP/textures/terrain_texture.json +136 -136
  178. package/examples/test/dev/test_RP/ui/_ui_defs.json +6 -0
  179. package/examples/test/dev/test_RP/ui/guidebook.json +446 -0
  180. package/examples/test/dev/test_RP/ui/server_form.json +91 -0
  181. package/examples/test/main.mjs +46 -1
  182. package/examples/test/res/models/blocks/arcane_workbench.geo.json +105 -105
  183. package/examples/test/res/models/blocks/jar_normal.geo.json +46 -46
  184. package/examples/test/res/models/blocks/jar_normal_0.geo.json +58 -58
  185. package/examples/test/res/models/blocks/jar_normal_1.geo.json +58 -58
  186. package/examples/test/res/models/blocks/jar_normal_2.geo.json +58 -58
  187. package/examples/test/res/models/blocks/jar_normal_3.geo.json +58 -58
  188. package/examples/test/res/models/blocks/wire.geo.json +153 -153
  189. package/examples/test/res/textures/items/seals/seal_breaker.png.mcmeta +5 -5
  190. package/examples/test/res/textures/items/seals/seal_butcher.png.mcmeta +5 -5
  191. package/examples/test/res/textures/items/seals/seal_empty.png.mcmeta +5 -5
  192. package/examples/test/res/textures/items/seals/seal_empty_advanced.png.mcmeta +5 -5
  193. package/examples/test/res/textures/items/seals/seal_fill.png.mcmeta +5 -5
  194. package/examples/test/res/textures/items/seals/seal_fill_advanced.png.mcmeta +5 -5
  195. package/examples/test/res/textures/items/seals/seal_guard.png.mcmeta +5 -5
  196. package/examples/test/res/textures/items/seals/seal_guard_advanced.png.mcmeta +5 -5
  197. package/examples/test/res/textures/items/seals/seal_harvest.png.mcmeta +5 -5
  198. package/examples/test/res/textures/items/seals/seal_lumber.png.mcmeta +5 -5
  199. package/examples/test/res/textures/items/seals/seal_pickup.png.mcmeta +5 -5
  200. package/examples/test/res/textures/items/seals/seal_pickup_advanced.png.mcmeta +5 -5
  201. package/examples/test/res/textures/items/seals/seal_provider.png.mcmeta +5 -5
  202. package/examples/test/res/textures/items/seals/seal_use.png.mcmeta +5 -5
  203. package/examples/test/res/textures/items/wand/cap_thaumium.png.mcmeta +11 -11
  204. package/examples/test/res/textures/items/wand/cap_void.png.mcmeta +11 -11
  205. package/examples/test/res/textures/items/wand/focus_pech.png.mcmeta +2 -2
  206. package/examples/test/res/textures/items/wand/focus_portablehole.png.mcmeta +2 -2
  207. package/examples/test/res/textures/items/wand/focus_primal.png.mcmeta +2 -2
  208. package/examples/test/res/textures/items/wand/focus_shard.png.mcmeta +2 -2
  209. package/examples/test/res/textures/items/wand/focus_warding.png.mcmeta +2 -2
  210. package/examples/test/res/textures/items/wand/rod_primal_mat.png.mcmeta +44 -44
  211. package/examples/test/scripts/custom_components/cropComponent.js +1 -10
  212. package/examples/test/scripts/custom_components/items/gui_book.js +37 -0
  213. package/examples/test/scripts/custom_components/registry.js +20 -0
  214. package/examples/test/scripts/index.js +4 -3
  215. package/log.md +8 -0
  216. package/package.json +4 -1
  217. package/src/cli/build.js +210 -210
  218. package/src/cli/load.js +116 -112
  219. package/src/cli/tools/textureSet.js +114 -114
  220. package/src/cli/utils.js +82 -82
  221. package/src/core/addon/controllers/animation_controller.js +80 -0
  222. package/src/core/addon/entity/entity.js +52 -51
  223. package/src/core/block/GeometryBlock.js +8 -0
  224. package/src/core/block/OreBlock.js +1 -0
  225. package/src/core/block/TileBlock.js +117 -0
  226. package/src/core/block/block.js +106 -106
  227. package/src/core/block/blockComponent.js +557 -557
  228. package/src/core/block/cropBlock.js +1 -1
  229. package/src/core/entity/BasicEntity.js +195 -166
  230. package/src/core/entity/bundles/BasicBundle.js +51 -0
  231. package/src/core/factory/BlockFactory.js +166 -158
  232. package/src/core/factory/EntityFactory.js +82 -82
  233. package/src/core/factory/ItemFactory.js +120 -95
  234. package/src/core/factory/RecipeFactory.js +46 -46
  235. package/src/core/index.js +2 -1
  236. package/src/core/item/Item.js +96 -96
  237. package/src/core/item/ItemComponents.js +251 -235
  238. package/src/core/item/armor.js +117 -89
  239. package/src/core/item/attachable.js +33 -33
  240. package/src/core/item/food.js +61 -61
  241. package/src/core/registry.js +16 -16
  242. package/src/core/ui/Properties/{Grid.js → GridProp.js} +2 -2
  243. package/src/core/ui/Properties/Sound.js +72 -0
  244. package/src/core/ui/elements/Button.js +111 -0
  245. package/src/core/ui/elements/CollectionPanel.js +61 -0
  246. package/src/core/ui/elements/Grid.js +24 -0
  247. package/src/core/ui/elements/Image.js +4 -0
  248. package/src/core/ui/elements/Label.js +10 -2
  249. package/src/core/ui/elements/Panel.js +7 -0
  250. package/src/core/ui/elements/ScrollingPanel.js +68 -0
  251. package/src/core/ui/elements/StackPanel.js +40 -0
  252. package/src/core/ui/elements/UIElement.js +43 -2
  253. package/src/core/ui/registry/UISystemRegistry.js +35 -0
  254. package/src/core/ui/systems/UISystem.js +9 -5
  255. package/src/core/ui/systems/guidebook.js +299 -0
  256. package/src/core/ui/systems/server_form.js +94 -83
  257. package/src/templates/test_sapdon/build.config +28 -28
  258. package/src/templates/test_sapdon/res/animations/animation_item.animation.json +34 -0
  259. package/src/templates/test_sapdon/res/animations/large_item.animation.json +27 -0
  260. package/src/templates/test_sapdon/res/models/entity/animation/animation_item.geo.json +26 -0
  261. package/src/templates/test_sapdon/res/models/entity/animation/large_item.geo.json +28 -0
  262. package/src/templates/test_sapdon/res/textures/blocks/none.png +0 -0
  263. package/src/templates/test_sapdon/scripts/custom_components/cropComponent.js +50 -0
  264. package/src/templates/test_sapdon/scripts/custom_components/items/gui_book.js +37 -0
  265. package/src/templates/test_sapdon/scripts/custom_components/registry.js +25 -0
  266. package/examples/masterball/dev/masterball[1.20.20+].mcaddon.zip +0 -0
  267. package/examples/masterball/dev/masterball_BP/masterball_BP_1_20_20/entities/sapdon_projectile_masterball.json +0 -56
  268. package/examples/masterball/dev/masterball_BP/masterball_BP_1_20_20/items/sapdon_caught_masterball.json +0 -32
  269. package/examples/masterball/dev/masterball_BP/masterball_BP_1_20_20/items/sapdon_uncaught_masterball.json +0 -31
  270. package/examples/masterball/dev/masterball_BP/masterball_BP_1_20_20/scripts/index.js +0 -159
  271. package/examples/test/dev/test_BP/biomes/test_biome.json +0 -48
  272. package/examples/test/dev/test_BP/blocks/sapdon_block.json +0 -111
  273. package/examples/test/dev/test_BP/entities/sapdon_body.json +0 -118
  274. package/examples/test/dev/test_BP/entities/sapdon_test_entity_ctrl1.json +0 -55
  275. package/examples/test/dev/test_BP/entities/sapdon_test_entity_ctrl2.json +0 -61
  276. package/examples/test/dev/test_BP/entities/sapdon_test_entity_header.json +0 -408
  277. package/examples/test/dev/test_RP/entity/sapdon_body.json +0 -44
  278. package/examples/test/dev/test_RP/entity/sapdon_test_entity_ctrl1.json +0 -38
  279. package/examples/test/dev/test_RP/entity/sapdon_test_entity_ctrl2.json +0 -38
  280. package/examples/test/dev/test_RP/entity/sapdon_test_entity_header.json +0 -44
  281. package/src/cli/build.config +0 -4
  282. package/src/core/ui/registry/ServerUISystem.js +0 -19
  283. /package/examples/{masterball/dev/masterball_BP/masterball_BP_1_20_20 → guidebook/dev/guidebook_BP}/pack_icon.png +0 -0
@@ -1,558 +1,558 @@
1
- export class BlockComponent {
2
- static setTick(interval_range,looping){
3
- return new Map().set("minecraft:tick",{
4
- interval_range:interval_range,
5
- looping:looping
6
- })
7
- }
8
- /**
9
- *
10
- * @param {Array} custom_components
11
- * @returns
12
- */
13
- static setCustomComponents(custom_components){
14
- return new Map().set("minecraft:custom_components",[...custom_components])
15
- }
16
- /**
17
- * 创建一个用于 Minecraft 方块的变换对象,并返回一个 Map。
18
- * @param {number[]} [translation=[0, 0, 0]] - 平移向量 [x, y, z]。
19
- * @param {number[]} [scale=[1, 1, 1]] - 缩放向量 [x, y, z]。
20
- * @param {number[]} [scale_pivot=[0, 0, 0]] - 缩放的枢轴点 [x, y, z]。
21
- * @param {number[]} [rotation=[0, 0, 0]] - 旋转向量(角度)[x, y, z]。
22
- * @param {number[]} [rotation_pivot=[0, 0, 0]] - 旋转的枢轴点 [x, y, z]。
23
- * @returns {Map} - 一个包含变换数据的 Map 对象。
24
- * @throws {Error} - 如果任何参数无效,则抛出错误。
25
- */
26
- static setTransformation(
27
- translation = [0, 0, 0],
28
- scale = [1, 1, 1],
29
- scale_pivot = [0, 0, 0],
30
- rotation = [0, 0, 0],
31
- rotation_pivot = [0, 0, 0]
32
- ) {
33
- // 验证输入参数是否为有效的 3D 向量
34
- const validateVector = (vector, name) => {
35
- if (
36
- !Array.isArray(vector) ||
37
- vector.length !== 3 ||
38
- !vector.every((value) => typeof value === "number" && !isNaN(value))
39
- ) {
40
- throw new Error(`${name} 必须是一个包含 3 个有效数字的数组`);
41
- }
42
- };
43
-
44
- // 验证所有输入参数
45
- validateVector(translation, "translation");
46
- validateVector(scale, "scale");
47
- validateVector(scale_pivot, "scale_pivot");
48
- validateVector(rotation, "rotation");
49
- validateVector(rotation_pivot, "rotation_pivot");
50
-
51
- // 创建变换对象
52
- const transformation = {
53
- translation,
54
- scale,
55
- scale_pivot,
56
- rotation,
57
- rotation_pivot,
58
- };
59
-
60
- // 将变换对象存入 Map
61
- const transformationMap = new Map();
62
- transformationMap.set("minecraft:transformation", transformation);
63
-
64
- return transformationMap;
65
- }
66
- /**
67
- * 设置方块的呼吸行为。
68
- * @param {String} value - 呼吸行为,可选值为 "solid" 或 "air"。
69
- * @returns {Map} - 新的组件集合。
70
- */
71
- static setBreathability(value) {
72
- if (value !== "solid" && value !== "air") {
73
- throw new Error('breathability must be either "solid" or "air"');
74
- }
75
- return new Map().set("minecraft:breathability", value);
76
- }
77
-
78
- /**
79
- * 启用或禁用方块的碰撞箱。
80
- * @param {Boolean} enabled - 是否启用碰撞箱。
81
- * @returns {Map} - 新的组件集合。
82
- */
83
- static setCollisionBoxEnabled(enabled) {
84
- if (typeof enabled !== "boolean") {
85
- throw new Error('enabled must be a boolean');
86
- }
87
- return new Map().set("minecraft:collision_box", enabled);
88
- }
89
-
90
- /**
91
- * 设置自定义的碰撞箱。
92
- * @param {Array} origin - 碰撞箱的起点坐标 [x, y, z]。
93
- * @param {Array} size - 碰撞箱的大小 [width, height, depth]。
94
- * @returns {Map} - 新的组件集合。
95
- */
96
- static setCollisionBoxCustom(origin, size) {
97
- if (!Array.isArray(origin) || origin.length !== 3) {
98
- throw new Error('origin must be an array of 3 numbers');
99
- }
100
- if (!Array.isArray(size) || size.length !== 3) {
101
- throw new Error('size must be an array of 3 numbers');
102
- }
103
-
104
- const [x, y, z] = origin;
105
- const [width, height, depth] = size;
106
-
107
- if (x < -8 || x > 8 || y < 0 || y > 16 || z < -8 || z > 8) {
108
- throw new Error('origin must be in the range (-8, 0, -8) to (8, 16, 8)');
109
- }
110
- if (x + width < -8 || x + width > 8 || y + height < 0 || y + height > 16 || z + depth < -8 || z + depth > 8) {
111
- throw new Error('origin + size must be in the range (-8, 0, -8) to (8, 16, 8)');
112
- }
113
-
114
- return new Map().set("minecraft:collision_box", { origin, size });
115
- }
116
-
117
- /**
118
- * 设置方块的合成台属性。
119
- * @param {Array} craftingTags - 合成标签。
120
- * @param {String} tableName - 合成台名称。
121
- * @returns {Map} - 新的组件集合。
122
- */
123
- static setCraftingTable(craftingTags, tableName) {
124
- if (!Array.isArray(craftingTags) || craftingTags.length > 64) {
125
- throw new Error('craftingTags must be an array with a maximum of 64 tags');
126
- }
127
- for (const tag of craftingTags) {
128
- if (typeof tag !== "string" || tag.length > 64) {
129
- throw new Error('each crafting tag must be a string with a maximum of 64 characters');
130
- }
131
- }
132
-
133
- if (tableName && typeof tableName !== "string") {
134
- throw new Error('tableName must be a string');
135
- }
136
-
137
- return new Map().set("minecraft:crafting_table", {
138
- crafting_tags: craftingTags,
139
- table_name: tableName,
140
- });
141
- }
142
-
143
- /**
144
- * 启用或禁用方块的爆炸抗性。
145
- * @param {Boolean} enabled - 是否启用爆炸抗性。
146
- * @returns {Map} - 新的组件集合。
147
- */
148
- static setDestructibleByExplosionEnabled(enabled) {
149
- if (typeof enabled !== "boolean") {
150
- throw new Error('enabled must be a boolean');
151
- }
152
- return new Map().set("minecraft:destructible_by_explosion", enabled);
153
- }
154
-
155
- /**
156
- * 设置自定义的爆炸抗性。
157
- * @param {Number} explosionResistance - 爆炸抗性值。
158
- * @returns {Map} - 新的组件集合。
159
- */
160
- static setDestructibleByExplosionCustom(explosionResistance) {
161
- if (typeof explosionResistance !== "number") {
162
- throw new Error('explosionResistance must be a number');
163
- }
164
- return new Map().set("minecraft:destructible_by_explosion", {
165
- explosion_resistance: explosionResistance,
166
- });
167
- }
168
-
169
- /**
170
- * 启用或禁用方块的挖掘抗性。
171
- * @param {Boolean} enabled - 是否启用挖掘抗性。
172
- * @returns {Map} - 新的组件集合。
173
- */
174
- static setDestructibleByMiningEnabled(enabled) {
175
- if (typeof enabled !== "boolean") {
176
- throw new Error('enabled must be a boolean');
177
- }
178
- return new Map().set("minecraft:destructible_by_mining", enabled);
179
- }
180
-
181
- /**
182
- * 设置自定义的挖掘抗性。
183
- * @param {Number} secondsToDestroy - 破坏所需时间(秒)。
184
- * @param {Array} itemSpecificSpeeds - 特定工具的挖掘速度。
185
- * @returns {Map} - 新的组件集合。
186
- */
187
- static setDestructibleByMiningCustom(secondsToDestroy, itemSpecificSpeeds) {
188
- if (typeof secondsToDestroy !== "number") {
189
- throw new Error('secondsToDestroy must be a number');
190
- }
191
-
192
- if (itemSpecificSpeeds && Array.isArray(itemSpecificSpeeds)) {
193
- for (const speed of itemSpecificSpeeds) {
194
- if (typeof speed.destroy_speed !== "number") {
195
- throw new Error('destroy_speed must be a number');
196
- }
197
- if (!speed.item) {
198
- throw new Error('item is required in item_specific_speeds');
199
- }
200
- }
201
- }
202
-
203
- return new Map().set("minecraft:destructible_by_mining", {
204
- seconds_to_destroy: secondsToDestroy,
205
- item_specific_speeds: itemSpecificSpeeds,
206
- });
207
- }
208
-
209
- /**
210
- * 设置方块的显示名称。
211
- * @param {String} displayName - 显示名称。
212
- * @returns {Map} - 新的组件集合。
213
- */
214
- static setDisplayName(displayName) {
215
- if (typeof displayName !== "string") {
216
- throw new Error('displayName must be a string');
217
- }
218
- return new Map().set("minecraft:display_name", displayName);
219
- }
220
-
221
- /**
222
- * 启用或禁用方块的易燃性。
223
- * @param {Boolean} enabled - 是否启用易燃性。
224
- * @returns {Map} - 新的组件集合。
225
- */
226
- static setFlammableEnabled(enabled) {
227
- if (typeof enabled !== "boolean") {
228
- throw new Error('enabled must be a boolean');
229
- }
230
- return new Map().set("minecraft:flammable", enabled);
231
- }
232
-
233
- /**
234
- * 设置自定义的易燃性。
235
- * @param {Number} catchChanceModifier - 着火概率。
236
- * @param {Number} destroyChanceModifier - 被火焰摧毁的概率。
237
- * @returns {Map} - 新的组件集合。
238
- */
239
- static setFlammableCustom(catchChanceModifier, destroyChanceModifier) {
240
- if (typeof catchChanceModifier !== "number" || catchChanceModifier < 0) {
241
- throw new Error('catchChanceModifier must be a number greater than or equal to 0');
242
- }
243
- if (typeof destroyChanceModifier !== "number" || destroyChanceModifier < 0) {
244
- throw new Error('destroyChanceModifier must be a number greater than or equal to 0');
245
- }
246
-
247
- return new Map().set("minecraft:flammable", {
248
- catch_chance_modifier: catchChanceModifier,
249
- destroy_chance_modifier: destroyChanceModifier,
250
- });
251
- }
252
-
253
- /**
254
- * 设置方块的摩擦力。
255
- * @param {Number} value - 摩擦力值,范围为 0.0 到 0.9。
256
- * @returns {Map} - 新的组件集合。
257
- */
258
- static setFriction(value) {
259
- if (typeof value !== "number" || value < 0.0 || value > 0.9) {
260
- throw new Error('friction must be a number between 0.0 and 0.9');
261
- }
262
- return new Map().set("minecraft:friction", value);
263
- }
264
-
265
- /**
266
- * 设置方块的几何模型。
267
- * @param {String} identifier - 几何模型标识符。
268
- * @param {Object} bone_visibility - 骨骼可见性配置。
269
- * @returns {Map} - 新的组件集合。
270
- */
271
- static setGeometry(identifier, bone_visibility) {
272
- if (typeof identifier !== "string") {
273
- throw new Error('identifier must be a string');
274
- }
275
- return new Map().set("minecraft:geometry",
276
- {
277
- identifier: identifier,
278
- bone_visibility: bone_visibility
279
- });
280
- }
281
-
282
- /**
283
- * 设置方块的物品视觉属性。
284
- * @param {String} geometry - 几何模型标识符。
285
- * @param {Object} materialInstances - 材质实例配置。
286
- * @returns {Map} - 新的组件集合。
287
- */
288
- static setItemVisual(geometry, materialInstances) {
289
- if (typeof geometry !== "string") {
290
- throw new Error('geometry must be a string');
291
- }
292
- if (!materialInstances || typeof materialInstances !== "object") {
293
- throw new Error('materialInstances must be an object');
294
- }
295
-
296
- return new Map().set("minecraft:item_visual", {
297
- geometry,
298
- material_instances: materialInstances,
299
- });
300
- }
301
-
302
- /**
303
- * 设置方块的光衰减值。
304
- * @param {Number} value - 光的衰减值,范围为 0 到 15。
305
- * @returns {Map} - 新的组件集合。
306
- */
307
- static setLightDampening(value) {
308
- if (typeof value !== "number" || value < 0 || value > 15) {
309
- throw new Error('lightDampening must be a number between 0 and 15');
310
- }
311
- return new Map().set("minecraft:light_dampening", value);
312
- }
313
-
314
- /**
315
- * 设置方块的光照强度。
316
- * @param {Number} value - 光照强度,范围为 0 到 15。
317
- * @returns {Map} - 新的组件集合。
318
- */
319
- static setLightEmission(value) {
320
- if (typeof value !== "number" || value < 0 || value > 15) {
321
- throw new Error('lightEmission must be a number between 0 and 15');
322
- }
323
- return new Map().set("minecraft:light_emission", value);
324
- }
325
-
326
- /**
327
- * 设置方块的液体检测属性。
328
- * @param {Boolean} canContainLiquid - 是否可以包含液体。
329
- * @param {String} liquidType - 液体类型。
330
- * @param {String} onLiquidTouches - 对液体的反应方式。
331
- * @param {Array} stopsLiquidFlowingFromDirection - 阻止液体流动的方向。
332
- * @returns {Map} - 新的组件集合。
333
- */
334
- static setLiquidDetection(canContainLiquid, liquidType, onLiquidTouches, stopsLiquidFlowingFromDirection) {
335
- if (typeof canContainLiquid !== "boolean") {
336
- throw new Error('canContainLiquid must be a boolean');
337
- }
338
-
339
- if (liquidType && liquidType !== "water") {
340
- throw new Error('liquidType must be "water"');
341
- }
342
-
343
- const validReactions = ["blocking", "broken", "popped", "no_reaction"];
344
- if (onLiquidTouches && !validReactions.includes(onLiquidTouches)) {
345
- throw new Error('onLiquidTouches must be one of: "blocking", "broken", "popped", "no_reaction"');
346
- }
347
-
348
- const validDirections = ["up", "down", "north", "south", "east", "west"];
349
- if (stopsLiquidFlowingFromDirection && Array.isArray(stopsLiquidFlowingFromDirection)) {
350
- for (const direction of stopsLiquidFlowingFromDirection) {
351
- if (!validDirections.includes(direction)) {
352
- throw new Error('stopsLiquidFlowingFromDirection must be one of: "up", "down", "north", "south", "east", "west"');
353
- }
354
- }
355
- }
356
-
357
- return new Map().set("minecraft:liquid_detection", {
358
- can_contain_liquid: canContainLiquid,
359
- liquid_type: liquidType,
360
- on_liquid_touches: onLiquidTouches,
361
- stops_liquid_flowing_from_direction: stopsLiquidFlowingFromDirection,
362
- });
363
- }
364
-
365
- /**
366
- * 设置方块的战利品表路径。
367
- * @param {String} path - 战利品表路径。
368
- * @returns {Map} - 新的组件集合。
369
- */
370
- static setLoot(path) {
371
- if (typeof path !== "string" || path.length > 256) {
372
- throw new Error('path must be a string with a maximum length of 256 characters');
373
- }
374
- return new Map().set("minecraft:loot", path);
375
- }
376
-
377
- /**
378
- * 设置方块的地图颜色。
379
- * @param {String|Array} value - 地图颜色,可以是十六进制字符串或 RGB 数组。
380
- * @returns {Map} - 新的组件集合。
381
- */
382
- static setMapColor(value) {
383
- if (typeof value === "string") {
384
- if (!/^#[0-9A-Fa-f]{6}$/.test(value)) {
385
- throw new Error('mapColor must be a valid hex string (e.g., "#FFFFFF")');
386
- }
387
- } else if (Array.isArray(value)) {
388
- if (value.length !== 3 || value.some((v) => typeof v !== "number" || v < 0 || v > 255)) {
389
- throw new Error('mapColor must be a valid RGB array (e.g., [255, 255, 255])');
390
- }
391
- } else {
392
- throw new Error('mapColor must be a hex string or an RGB array');
393
- }
394
-
395
- return new Map().set("minecraft:map_color", value);
396
- }
397
-
398
- /**
399
- * 设置方块的材质实例。
400
- * @param {Object} instances - 材质实例配置。
401
- * @returns {Map} - 新的组件集合。
402
- */
403
- static setMaterialInstances(instances) {
404
- if (!instances || typeof instances !== "object") {
405
- throw new Error('instances must be an object');
406
- }
407
-
408
- if (!instances["*"] ) {
409
- throw new Error('material_instances must include a "*" material instance');
410
- }
411
-
412
- for (const [key, value] of Object.entries(instances)) {
413
- if (typeof value === "object") {
414
- if (!value.texture || typeof value.texture !== "string") {
415
- throw new Error(`material instance "${key}" must have a texture`);
416
- }
417
- if (value.ambient_occlusion !== undefined && typeof value.ambient_occlusion !== "boolean" && typeof value.ambient_occlusion !== "number") {
418
- throw new Error(`ambient_occlusion in material instance "${key}" must be a boolean or number`);
419
- }
420
- if (value.face_dimming !== undefined && typeof value.face_dimming !== "boolean") {
421
- throw new Error(`face_dimming in material instance "${key}" must be a boolean`);
422
- }
423
- if (value.render_method && !["opaque", "double_sided", "blend", "alpha_test", "alpha_test_single_sided"].includes(value.render_method)) {
424
- throw new Error(`render_method in material instance "${key}" must be one of: opaque, double_sided, blend, alpha_test, alpha_test_single_sided`);
425
- }
426
- } else if (typeof value !== "string") {
427
- throw new Error(`material instance "${key}" must be an object or a string`);
428
- }
429
- }
430
-
431
- return new Map().set("minecraft:material_instances", instances);
432
- }
433
-
434
- /**
435
- * 设置方块的放置过滤条件。
436
- * @param {Array} conditions - 放置条件列表。
437
- * @returns {Map} - 新的组件集合。
438
- */
439
- static setPlacementFilter(conditions) {
440
- if (!Array.isArray(conditions) || conditions.length === 0 || conditions.length > 64) {
441
- throw new Error('conditions must be an array with 1 to 64 elements');
442
- }
443
-
444
- for (const condition of conditions) {
445
- if (condition.allowed_faces && Array.isArray(condition.allowed_faces)) {
446
- const validFaces = ["up", "down", "north", "south", "east", "west", "side", "all"];
447
- for (const face of condition.allowed_faces) {
448
- if (!validFaces.includes(face)) {
449
- throw new Error(`allowed_faces must be one of: ${validFaces.join(", ")}`);
450
- }
451
- }
452
- }
453
-
454
- if (condition.block_filter && Array.isArray(condition.block_filter)) {
455
- for (const block of condition.block_filter) {
456
- if (typeof block === "string") {
457
- continue;
458
- } else if (typeof block === "object" && block !== null) {
459
- if (block.tags && typeof block.tags !== "string") {
460
- throw new Error('tags in block_filter must be a string');
461
- }
462
- if (block.name && typeof block.name !== "string") {
463
- throw new Error('name in block_filter must be a string');
464
- }
465
- if (block.states && typeof block.states !== "object") {
466
- throw new Error('states in block_filter must be an object');
467
- }
468
- } else {
469
- throw new Error('block_filter must be a string or a BlockDescriptor object');
470
- }
471
- }
472
- }
473
-
474
- if (!condition.allowed_faces && !condition.block_filter) {
475
- throw new Error('each condition must have at least one of allowed_faces or block_filter');
476
- }
477
- }
478
-
479
- return new Map().set("minecraft:placement_filter", { conditions });
480
- }
481
-
482
- /**
483
- * 设置方块的红石导电性。
484
- * @param {Boolean} allowsWireToStepDown - 是否允许红石线向下阶梯连接。
485
- * @param {Boolean} redstoneConductor - 方块是否可以被红石信号激活。
486
- * @returns {Map} - 新的组件集合。
487
- */
488
- static setRedstoneConductivity(allowsWireToStepDown, redstoneConductor) {
489
- if (typeof allowsWireToStepDown !== "boolean") {
490
- throw new Error('allowsWireToStepDown must be a boolean');
491
- }
492
- if (typeof redstoneConductor !== "boolean") {
493
- throw new Error('redstoneConductor must be a boolean');
494
- }
495
-
496
- return new Map().set("minecraft:redstone_conductivity", {
497
- allows_wire_to_step_down: allowsWireToStepDown,
498
- redstone_conductor: redstoneConductor,
499
- });
500
- }
501
-
502
- /**
503
- * 启用或禁用方块的选择框。
504
- * @param {Boolean} enabled - 是否启用选择框。
505
- * @returns {Map} - 新的组件集合。
506
- */
507
- static setSelectionBoxEnabled(enabled) {
508
- if (typeof enabled !== "boolean") {
509
- throw new Error('enabled must be a boolean');
510
- }
511
- return new Map().set("minecraft:selection_box", enabled);
512
- }
513
-
514
- /**
515
- * 设置自定义的选择框。
516
- * @param {Array} origin - 选择框的起点坐标 [x, y, z]。
517
- * @param {Array} size - 选择框的大小 [width, height, depth]。
518
- * @returns {Map} - 新的组件集合。
519
- */
520
- static setSelectionBoxCustom(origin, size) {
521
- if (!Array.isArray(origin) || origin.length !== 3) {
522
- throw new Error('origin must be an array of 3 numbers');
523
- }
524
- if (!Array.isArray(size) || size.length !== 3) {
525
- throw new Error('size must be an array of 3 numbers');
526
- }
527
-
528
- const [x, y, z] = origin;
529
- const [width, height, depth] = size;
530
-
531
- if (x < -8 || x > 8 || y < 0 || y > 16 || z < -8 || z > 8) {
532
- throw new Error('origin must be in the range (-8, 0, -8) to (8, 16, 8)');
533
- }
534
- if (x + width < -8 || x + width > 8 || y + height < 0 || y + height > 16 || z + depth < -8 || z + depth > 8) {
535
- throw new Error('origin + size must be in the range (-8, 0, -8) to (8, 16, 8)');
536
- }
537
-
538
- return new Map().set("minecraft:selection_box", { origin, size });
539
- }
540
-
541
- /**
542
- * 将多个组件集合合并为一个。
543
- * @param {...Map} componentMaps - 多个组件集合。
544
- * @returns {Map} - 合并后的组件集合。
545
- */
546
- static combineComponents(...componentMaps) {
547
- return new Map(componentMaps.flatMap(map => [...map]));
548
- }
549
-
550
- /**
551
- * 获取当前组件的 JSON 表示。
552
- * @param {Map} components - 组件集合。
553
- * @returns {Object} - 组件的 JSON 对象。
554
- */
555
- static toJSON(components) {
556
- return Object.fromEntries(components);
557
- }
1
+ export class BlockComponent {
2
+ static setTick(interval_range,looping){
3
+ return new Map().set("minecraft:tick",{
4
+ interval_range:interval_range,
5
+ looping:looping
6
+ })
7
+ }
8
+ /**
9
+ *
10
+ * @param {Array} custom_components
11
+ * @returns
12
+ */
13
+ static setCustomComponents(custom_components){
14
+ return new Map().set("minecraft:custom_components",[...custom_components])
15
+ }
16
+ /**
17
+ * 创建一个用于 Minecraft 方块的变换对象,并返回一个 Map。
18
+ * @param {number[]} [translation=[0, 0, 0]] - 平移向量 [x, y, z]。
19
+ * @param {number[]} [scale=[1, 1, 1]] - 缩放向量 [x, y, z]。
20
+ * @param {number[]} [scale_pivot=[0, 0, 0]] - 缩放的枢轴点 [x, y, z]。
21
+ * @param {number[]} [rotation=[0, 0, 0]] - 旋转向量(角度)[x, y, z]。
22
+ * @param {number[]} [rotation_pivot=[0, 0, 0]] - 旋转的枢轴点 [x, y, z]。
23
+ * @returns {Map} - 一个包含变换数据的 Map 对象。
24
+ * @throws {Error} - 如果任何参数无效,则抛出错误。
25
+ */
26
+ static setTransformation(
27
+ translation = [0, 0, 0],
28
+ scale = [1, 1, 1],
29
+ scale_pivot = [0, 0, 0],
30
+ rotation = [0, 0, 0],
31
+ rotation_pivot = [0, 0, 0]
32
+ ) {
33
+ // 验证输入参数是否为有效的 3D 向量
34
+ const validateVector = (vector, name) => {
35
+ if (
36
+ !Array.isArray(vector) ||
37
+ vector.length !== 3 ||
38
+ !vector.every((value) => typeof value === "number" && !isNaN(value))
39
+ ) {
40
+ throw new Error(`${name} 必须是一个包含 3 个有效数字的数组`);
41
+ }
42
+ };
43
+
44
+ // 验证所有输入参数
45
+ validateVector(translation, "translation");
46
+ validateVector(scale, "scale");
47
+ validateVector(scale_pivot, "scale_pivot");
48
+ validateVector(rotation, "rotation");
49
+ validateVector(rotation_pivot, "rotation_pivot");
50
+
51
+ // 创建变换对象
52
+ const transformation = {
53
+ translation,
54
+ scale,
55
+ scale_pivot,
56
+ rotation,
57
+ rotation_pivot,
58
+ };
59
+
60
+ // 将变换对象存入 Map
61
+ const transformationMap = new Map();
62
+ transformationMap.set("minecraft:transformation", transformation);
63
+
64
+ return transformationMap;
65
+ }
66
+ /**
67
+ * 设置方块的呼吸行为。
68
+ * @param {String} value - 呼吸行为,可选值为 "solid" 或 "air"。
69
+ * @returns {Map} - 新的组件集合。
70
+ */
71
+ static setBreathability(value) {
72
+ if (value !== "solid" && value !== "air") {
73
+ throw new Error('breathability must be either "solid" or "air"');
74
+ }
75
+ return new Map().set("minecraft:breathability", value);
76
+ }
77
+
78
+ /**
79
+ * 启用或禁用方块的碰撞箱。
80
+ * @param {Boolean} enabled - 是否启用碰撞箱。
81
+ * @returns {Map} - 新的组件集合。
82
+ */
83
+ static setCollisionBoxEnabled(enabled) {
84
+ if (typeof enabled !== "boolean") {
85
+ throw new Error('enabled must be a boolean');
86
+ }
87
+ return new Map().set("minecraft:collision_box", enabled);
88
+ }
89
+
90
+ /**
91
+ * 设置自定义的碰撞箱。
92
+ * @param {Array} origin - 碰撞箱的起点坐标 [x, y, z]。
93
+ * @param {Array} size - 碰撞箱的大小 [width, height, depth]。
94
+ * @returns {Map} - 新的组件集合。
95
+ */
96
+ static setCollisionBoxCustom(origin, size) {
97
+ if (!Array.isArray(origin) || origin.length !== 3) {
98
+ throw new Error('origin must be an array of 3 numbers');
99
+ }
100
+ if (!Array.isArray(size) || size.length !== 3) {
101
+ throw new Error('size must be an array of 3 numbers');
102
+ }
103
+
104
+ const [x, y, z] = origin;
105
+ const [width, height, depth] = size;
106
+
107
+ if (x < -8 || x > 8 || y < 0 || y > 16 || z < -8 || z > 8) {
108
+ throw new Error('origin must be in the range (-8, 0, -8) to (8, 16, 8)');
109
+ }
110
+ if (x + width < -8 || x + width > 8 || y + height < 0 || y + height > 16 || z + depth < -8 || z + depth > 8) {
111
+ throw new Error('origin + size must be in the range (-8, 0, -8) to (8, 16, 8)');
112
+ }
113
+
114
+ return new Map().set("minecraft:collision_box", { origin, size });
115
+ }
116
+
117
+ /**
118
+ * 设置方块的合成台属性。
119
+ * @param {Array} craftingTags - 合成标签。
120
+ * @param {String} tableName - 合成台名称。
121
+ * @returns {Map} - 新的组件集合。
122
+ */
123
+ static setCraftingTable(craftingTags, tableName) {
124
+ if (!Array.isArray(craftingTags) || craftingTags.length > 64) {
125
+ throw new Error('craftingTags must be an array with a maximum of 64 tags');
126
+ }
127
+ for (const tag of craftingTags) {
128
+ if (typeof tag !== "string" || tag.length > 64) {
129
+ throw new Error('each crafting tag must be a string with a maximum of 64 characters');
130
+ }
131
+ }
132
+
133
+ if (tableName && typeof tableName !== "string") {
134
+ throw new Error('tableName must be a string');
135
+ }
136
+
137
+ return new Map().set("minecraft:crafting_table", {
138
+ crafting_tags: craftingTags,
139
+ table_name: tableName,
140
+ });
141
+ }
142
+
143
+ /**
144
+ * 启用或禁用方块的爆炸抗性。
145
+ * @param {Boolean} enabled - 是否启用爆炸抗性。
146
+ * @returns {Map} - 新的组件集合。
147
+ */
148
+ static setDestructibleByExplosionEnabled(enabled) {
149
+ if (typeof enabled !== "boolean") {
150
+ throw new Error('enabled must be a boolean');
151
+ }
152
+ return new Map().set("minecraft:destructible_by_explosion", enabled);
153
+ }
154
+
155
+ /**
156
+ * 设置自定义的爆炸抗性。
157
+ * @param {Number} explosionResistance - 爆炸抗性值。
158
+ * @returns {Map} - 新的组件集合。
159
+ */
160
+ static setDestructibleByExplosionCustom(explosionResistance) {
161
+ if (typeof explosionResistance !== "number") {
162
+ throw new Error('explosionResistance must be a number');
163
+ }
164
+ return new Map().set("minecraft:destructible_by_explosion", {
165
+ explosion_resistance: explosionResistance,
166
+ });
167
+ }
168
+
169
+ /**
170
+ * 启用或禁用方块的挖掘抗性。
171
+ * @param {Boolean} enabled - 是否启用挖掘抗性。
172
+ * @returns {Map} - 新的组件集合。
173
+ */
174
+ static setDestructibleByMiningEnabled(enabled) {
175
+ if (typeof enabled !== "boolean") {
176
+ throw new Error('enabled must be a boolean');
177
+ }
178
+ return new Map().set("minecraft:destructible_by_mining", enabled);
179
+ }
180
+
181
+ /**
182
+ * 设置自定义的挖掘抗性。
183
+ * @param {Number} secondsToDestroy - 破坏所需时间(秒)。
184
+ * @param {Array} itemSpecificSpeeds - 特定工具的挖掘速度。
185
+ * @returns {Map} - 新的组件集合。
186
+ */
187
+ static setDestructibleByMiningCustom(secondsToDestroy, itemSpecificSpeeds) {
188
+ if (typeof secondsToDestroy !== "number") {
189
+ throw new Error('secondsToDestroy must be a number');
190
+ }
191
+
192
+ if (itemSpecificSpeeds && Array.isArray(itemSpecificSpeeds)) {
193
+ for (const speed of itemSpecificSpeeds) {
194
+ if (typeof speed.destroy_speed !== "number") {
195
+ throw new Error('destroy_speed must be a number');
196
+ }
197
+ if (!speed.item) {
198
+ throw new Error('item is required in item_specific_speeds');
199
+ }
200
+ }
201
+ }
202
+
203
+ return new Map().set("minecraft:destructible_by_mining", {
204
+ seconds_to_destroy: secondsToDestroy,
205
+ item_specific_speeds: itemSpecificSpeeds,
206
+ });
207
+ }
208
+
209
+ /**
210
+ * 设置方块的显示名称。
211
+ * @param {String} displayName - 显示名称。
212
+ * @returns {Map} - 新的组件集合。
213
+ */
214
+ static setDisplayName(displayName) {
215
+ if (typeof displayName !== "string") {
216
+ throw new Error('displayName must be a string');
217
+ }
218
+ return new Map().set("minecraft:display_name", displayName);
219
+ }
220
+
221
+ /**
222
+ * 启用或禁用方块的易燃性。
223
+ * @param {Boolean} enabled - 是否启用易燃性。
224
+ * @returns {Map} - 新的组件集合。
225
+ */
226
+ static setFlammableEnabled(enabled) {
227
+ if (typeof enabled !== "boolean") {
228
+ throw new Error('enabled must be a boolean');
229
+ }
230
+ return new Map().set("minecraft:flammable", enabled);
231
+ }
232
+
233
+ /**
234
+ * 设置自定义的易燃性。
235
+ * @param {Number} catchChanceModifier - 着火概率。
236
+ * @param {Number} destroyChanceModifier - 被火焰摧毁的概率。
237
+ * @returns {Map} - 新的组件集合。
238
+ */
239
+ static setFlammableCustom(catchChanceModifier, destroyChanceModifier) {
240
+ if (typeof catchChanceModifier !== "number" || catchChanceModifier < 0) {
241
+ throw new Error('catchChanceModifier must be a number greater than or equal to 0');
242
+ }
243
+ if (typeof destroyChanceModifier !== "number" || destroyChanceModifier < 0) {
244
+ throw new Error('destroyChanceModifier must be a number greater than or equal to 0');
245
+ }
246
+
247
+ return new Map().set("minecraft:flammable", {
248
+ catch_chance_modifier: catchChanceModifier,
249
+ destroy_chance_modifier: destroyChanceModifier,
250
+ });
251
+ }
252
+
253
+ /**
254
+ * 设置方块的摩擦力。
255
+ * @param {Number} value - 摩擦力值,范围为 0.0 到 0.9。
256
+ * @returns {Map} - 新的组件集合。
257
+ */
258
+ static setFriction(value) {
259
+ if (typeof value !== "number" || value < 0.0 || value > 0.9) {
260
+ throw new Error('friction must be a number between 0.0 and 0.9');
261
+ }
262
+ return new Map().set("minecraft:friction", value);
263
+ }
264
+
265
+ /**
266
+ * 设置方块的几何模型。
267
+ * @param {String} identifier - 几何模型标识符。
268
+ * @param {Object} bone_visibility - 骨骼可见性配置。
269
+ * @returns {Map} - 新的组件集合。
270
+ */
271
+ static setGeometry(identifier, bone_visibility) {
272
+ if (typeof identifier !== "string") {
273
+ throw new Error('identifier must be a string');
274
+ }
275
+ return new Map().set("minecraft:geometry",
276
+ {
277
+ identifier: identifier,
278
+ bone_visibility: bone_visibility
279
+ });
280
+ }
281
+
282
+ /**
283
+ * 设置方块的物品视觉属性。
284
+ * @param {String} geometry - 几何模型标识符。
285
+ * @param {Object} materialInstances - 材质实例配置。
286
+ * @returns {Map} - 新的组件集合。
287
+ */
288
+ static setItemVisual(geometry, materialInstances) {
289
+ if (typeof geometry !== "string") {
290
+ throw new Error('geometry must be a string');
291
+ }
292
+ if (!materialInstances || typeof materialInstances !== "object") {
293
+ throw new Error('materialInstances must be an object');
294
+ }
295
+
296
+ return new Map().set("minecraft:item_visual", {
297
+ geometry,
298
+ material_instances: materialInstances,
299
+ });
300
+ }
301
+
302
+ /**
303
+ * 设置方块的光衰减值。
304
+ * @param {Number} value - 光的衰减值,范围为 0 到 15。
305
+ * @returns {Map} - 新的组件集合。
306
+ */
307
+ static setLightDampening(value) {
308
+ if (typeof value !== "number" || value < 0 || value > 15) {
309
+ throw new Error('lightDampening must be a number between 0 and 15');
310
+ }
311
+ return new Map().set("minecraft:light_dampening", value);
312
+ }
313
+
314
+ /**
315
+ * 设置方块的光照强度。
316
+ * @param {Number} value - 光照强度,范围为 0 到 15。
317
+ * @returns {Map} - 新的组件集合。
318
+ */
319
+ static setLightEmission(value) {
320
+ if (typeof value !== "number" || value < 0 || value > 15) {
321
+ throw new Error('lightEmission must be a number between 0 and 15');
322
+ }
323
+ return new Map().set("minecraft:light_emission", value);
324
+ }
325
+
326
+ /**
327
+ * 设置方块的液体检测属性。
328
+ * @param {Boolean} canContainLiquid - 是否可以包含液体。
329
+ * @param {String} liquidType - 液体类型。
330
+ * @param {String} onLiquidTouches - 对液体的反应方式。
331
+ * @param {Array} stopsLiquidFlowingFromDirection - 阻止液体流动的方向。
332
+ * @returns {Map} - 新的组件集合。
333
+ */
334
+ static setLiquidDetection(canContainLiquid, liquidType, onLiquidTouches, stopsLiquidFlowingFromDirection) {
335
+ if (typeof canContainLiquid !== "boolean") {
336
+ throw new Error('canContainLiquid must be a boolean');
337
+ }
338
+
339
+ if (liquidType && liquidType !== "water") {
340
+ throw new Error('liquidType must be "water"');
341
+ }
342
+
343
+ const validReactions = ["blocking", "broken", "popped", "no_reaction"];
344
+ if (onLiquidTouches && !validReactions.includes(onLiquidTouches)) {
345
+ throw new Error('onLiquidTouches must be one of: "blocking", "broken", "popped", "no_reaction"');
346
+ }
347
+
348
+ const validDirections = ["up", "down", "north", "south", "east", "west"];
349
+ if (stopsLiquidFlowingFromDirection && Array.isArray(stopsLiquidFlowingFromDirection)) {
350
+ for (const direction of stopsLiquidFlowingFromDirection) {
351
+ if (!validDirections.includes(direction)) {
352
+ throw new Error('stopsLiquidFlowingFromDirection must be one of: "up", "down", "north", "south", "east", "west"');
353
+ }
354
+ }
355
+ }
356
+
357
+ return new Map().set("minecraft:liquid_detection", {
358
+ can_contain_liquid: canContainLiquid,
359
+ liquid_type: liquidType,
360
+ on_liquid_touches: onLiquidTouches,
361
+ stops_liquid_flowing_from_direction: stopsLiquidFlowingFromDirection,
362
+ });
363
+ }
364
+
365
+ /**
366
+ * 设置方块的战利品表路径。
367
+ * @param {String} path - 战利品表路径。
368
+ * @returns {Map} - 新的组件集合。
369
+ */
370
+ static setLoot(path) {
371
+ if (typeof path !== "string" || path.length > 256) {
372
+ throw new Error('path must be a string with a maximum length of 256 characters');
373
+ }
374
+ return new Map().set("minecraft:loot", path);
375
+ }
376
+
377
+ /**
378
+ * 设置方块的地图颜色。
379
+ * @param {String|Array} value - 地图颜色,可以是十六进制字符串或 RGB 数组。
380
+ * @returns {Map} - 新的组件集合。
381
+ */
382
+ static setMapColor(value) {
383
+ if (typeof value === "string") {
384
+ if (!/^#[0-9A-Fa-f]{6}$/.test(value)) {
385
+ throw new Error('mapColor must be a valid hex string (e.g., "#FFFFFF")');
386
+ }
387
+ } else if (Array.isArray(value)) {
388
+ if (value.length !== 3 || value.some((v) => typeof v !== "number" || v < 0 || v > 255)) {
389
+ throw new Error('mapColor must be a valid RGB array (e.g., [255, 255, 255])');
390
+ }
391
+ } else {
392
+ throw new Error('mapColor must be a hex string or an RGB array');
393
+ }
394
+
395
+ return new Map().set("minecraft:map_color", value);
396
+ }
397
+
398
+ /**
399
+ * 设置方块的材质实例。
400
+ * @param {Object} instances - 材质实例配置。
401
+ * @returns {Map} - 新的组件集合。
402
+ */
403
+ static setMaterialInstances(instances) {
404
+ if (!instances || typeof instances !== "object") {
405
+ throw new Error('instances must be an object');
406
+ }
407
+
408
+ if (!instances["*"] ) {
409
+ throw new Error('material_instances must include a "*" material instance');
410
+ }
411
+
412
+ for (const [key, value] of Object.entries(instances)) {
413
+ if (typeof value === "object") {
414
+ if (!value.texture || typeof value.texture !== "string") {
415
+ throw new Error(`material instance "${key}" must have a texture`);
416
+ }
417
+ if (value.ambient_occlusion !== undefined && typeof value.ambient_occlusion !== "boolean" && typeof value.ambient_occlusion !== "number") {
418
+ throw new Error(`ambient_occlusion in material instance "${key}" must be a boolean or number`);
419
+ }
420
+ if (value.face_dimming !== undefined && typeof value.face_dimming !== "boolean") {
421
+ throw new Error(`face_dimming in material instance "${key}" must be a boolean`);
422
+ }
423
+ if (value.render_method && !["opaque", "double_sided", "blend", "alpha_test", "alpha_test_single_sided"].includes(value.render_method)) {
424
+ throw new Error(`render_method in material instance "${key}" must be one of: opaque, double_sided, blend, alpha_test, alpha_test_single_sided`);
425
+ }
426
+ } else if (typeof value !== "string") {
427
+ throw new Error(`material instance "${key}" must be an object or a string`);
428
+ }
429
+ }
430
+
431
+ return new Map().set("minecraft:material_instances", instances);
432
+ }
433
+
434
+ /**
435
+ * 设置方块的放置过滤条件。
436
+ * @param {Array} conditions - 放置条件列表。
437
+ * @returns {Map} - 新的组件集合。
438
+ */
439
+ static setPlacementFilter(conditions) {
440
+ if (!Array.isArray(conditions) || conditions.length === 0 || conditions.length > 64) {
441
+ throw new Error('conditions must be an array with 1 to 64 elements');
442
+ }
443
+
444
+ for (const condition of conditions) {
445
+ if (condition.allowed_faces && Array.isArray(condition.allowed_faces)) {
446
+ const validFaces = ["up", "down", "north", "south", "east", "west", "side", "all"];
447
+ for (const face of condition.allowed_faces) {
448
+ if (!validFaces.includes(face)) {
449
+ throw new Error(`allowed_faces must be one of: ${validFaces.join(", ")}`);
450
+ }
451
+ }
452
+ }
453
+
454
+ if (condition.block_filter && Array.isArray(condition.block_filter)) {
455
+ for (const block of condition.block_filter) {
456
+ if (typeof block === "string") {
457
+ continue;
458
+ } else if (typeof block === "object" && block !== null) {
459
+ if (block.tags && typeof block.tags !== "string") {
460
+ throw new Error('tags in block_filter must be a string');
461
+ }
462
+ if (block.name && typeof block.name !== "string") {
463
+ throw new Error('name in block_filter must be a string');
464
+ }
465
+ if (block.states && typeof block.states !== "object") {
466
+ throw new Error('states in block_filter must be an object');
467
+ }
468
+ } else {
469
+ throw new Error('block_filter must be a string or a BlockDescriptor object');
470
+ }
471
+ }
472
+ }
473
+
474
+ if (!condition.allowed_faces && !condition.block_filter) {
475
+ throw new Error('each condition must have at least one of allowed_faces or block_filter');
476
+ }
477
+ }
478
+
479
+ return new Map().set("minecraft:placement_filter", { conditions });
480
+ }
481
+
482
+ /**
483
+ * 设置方块的红石导电性。
484
+ * @param {Boolean} allowsWireToStepDown - 是否允许红石线向下阶梯连接。
485
+ * @param {Boolean} redstoneConductor - 方块是否可以被红石信号激活。
486
+ * @returns {Map} - 新的组件集合。
487
+ */
488
+ static setRedstoneConductivity(allowsWireToStepDown, redstoneConductor) {
489
+ if (typeof allowsWireToStepDown !== "boolean") {
490
+ throw new Error('allowsWireToStepDown must be a boolean');
491
+ }
492
+ if (typeof redstoneConductor !== "boolean") {
493
+ throw new Error('redstoneConductor must be a boolean');
494
+ }
495
+
496
+ return new Map().set("minecraft:redstone_conductivity", {
497
+ allows_wire_to_step_down: allowsWireToStepDown,
498
+ redstone_conductor: redstoneConductor,
499
+ });
500
+ }
501
+
502
+ /**
503
+ * 启用或禁用方块的选择框。
504
+ * @param {Boolean} enabled - 是否启用选择框。
505
+ * @returns {Map} - 新的组件集合。
506
+ */
507
+ static setSelectionBoxEnabled(enabled) {
508
+ if (typeof enabled !== "boolean") {
509
+ throw new Error('enabled must be a boolean');
510
+ }
511
+ return new Map().set("minecraft:selection_box", enabled);
512
+ }
513
+
514
+ /**
515
+ * 设置自定义的选择框。
516
+ * @param {Array} origin - 选择框的起点坐标 [x, y, z]。
517
+ * @param {Array} size - 选择框的大小 [width, height, depth]。
518
+ * @returns {Map} - 新的组件集合。
519
+ */
520
+ static setSelectionBoxCustom(origin, size) {
521
+ if (!Array.isArray(origin) || origin.length !== 3) {
522
+ throw new Error('origin must be an array of 3 numbers');
523
+ }
524
+ if (!Array.isArray(size) || size.length !== 3) {
525
+ throw new Error('size must be an array of 3 numbers');
526
+ }
527
+
528
+ const [x, y, z] = origin;
529
+ const [width, height, depth] = size;
530
+
531
+ if (x < -8 || x > 8 || y < 0 || y > 16 || z < -8 || z > 8) {
532
+ throw new Error('origin must be in the range (-8, 0, -8) to (8, 16, 8)');
533
+ }
534
+ if (x + width < -8 || x + width > 8 || y + height < 0 || y + height > 16 || z + depth < -8 || z + depth > 8) {
535
+ throw new Error('origin + size must be in the range (-8, 0, -8) to (8, 16, 8)');
536
+ }
537
+
538
+ return new Map().set("minecraft:selection_box", { origin, size });
539
+ }
540
+
541
+ /**
542
+ * 将多个组件集合合并为一个。
543
+ * @param {...Map} componentMaps - 多个组件集合。
544
+ * @returns {Map} - 合并后的组件集合。
545
+ */
546
+ static combineComponents(...componentMaps) {
547
+ return new Map(componentMaps.flatMap(map => [...map]));
548
+ }
549
+
550
+ /**
551
+ * 获取当前组件的 JSON 表示。
552
+ * @param {Map} components - 组件集合。
553
+ * @returns {Object} - 组件的 JSON 对象。
554
+ */
555
+ static toJSON(components) {
556
+ return Object.fromEntries(components);
557
+ }
558
558
  }