sandstone 1.0.0-beta.1 → 1.0.0-beta.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 (189) hide show
  1. package/CLAUDE.md +320 -22
  2. package/bun.lock +23 -22
  3. package/dist/arguments/coords.d.ts +13 -15
  4. package/dist/arguments/generated/_registry/activities.d.ts +1 -1
  5. package/dist/arguments/generated/_registry/atlases.d.ts +1 -1
  6. package/dist/arguments/generated/_registry/attributes.d.ts +1 -1
  7. package/dist/arguments/generated/_registry/block_definitions.d.ts +1 -1
  8. package/dist/arguments/generated/_registry/block_entity_types.d.ts +1 -1
  9. package/dist/arguments/generated/_registry/block_predicate_types.d.ts +1 -1
  10. package/dist/arguments/generated/_registry/block_types.d.ts +1 -1
  11. package/dist/arguments/generated/_registry/blocks.d.ts +1 -1
  12. package/dist/arguments/generated/_registry/chunk_statuses.d.ts +1 -1
  13. package/dist/arguments/generated/_registry/damage_types.d.ts +1 -1
  14. package/dist/arguments/generated/_registry/data_component_types.d.ts +1 -1
  15. package/dist/arguments/generated/_registry/dialog_types.d.ts +1 -1
  16. package/dist/arguments/generated/_registry/dialogs.d.ts +1 -1
  17. package/dist/arguments/generated/_registry/dimension_types.d.ts +1 -1
  18. package/dist/arguments/generated/_registry/enchantment_effect_component_types.d.ts +1 -1
  19. package/dist/arguments/generated/_registry/enchantments.d.ts +1 -1
  20. package/dist/arguments/generated/_registry/equipments.d.ts +1 -1
  21. package/dist/arguments/generated/_registry/float_provider_types.d.ts +1 -1
  22. package/dist/arguments/generated/_registry/fluids.d.ts +1 -1
  23. package/dist/arguments/generated/_registry/fonts.d.ts +1 -1
  24. package/dist/arguments/generated/_registry/height_provider_types.d.ts +1 -1
  25. package/dist/arguments/generated/_registry/int_provider_types.d.ts +1 -1
  26. package/dist/arguments/generated/_registry/item_definitions.d.ts +1 -1
  27. package/dist/arguments/generated/_registry/items.d.ts +1 -1
  28. package/dist/arguments/generated/_registry/jukebox_songs.d.ts +1 -1
  29. package/dist/arguments/generated/_registry/loot_function_types.d.ts +1 -1
  30. package/dist/arguments/generated/_registry/loot_number_provider_types.d.ts +1 -1
  31. package/dist/arguments/generated/_registry/map_decoration_types.d.ts +1 -1
  32. package/dist/arguments/generated/_registry/memory_module_types.d.ts +1 -1
  33. package/dist/arguments/generated/_registry/mob_effects.d.ts +1 -1
  34. package/dist/arguments/generated/_registry/painting_variants.d.ts +1 -1
  35. package/dist/arguments/generated/_registry/particle_types.d.ts +1 -1
  36. package/dist/arguments/generated/_registry/potions.d.ts +1 -1
  37. package/dist/arguments/generated/_registry/recipes.d.ts +1 -1
  38. package/dist/arguments/generated/_registry/slot_source_types.d.ts +1 -1
  39. package/dist/arguments/generated/_registry/structures.d.ts +1 -1
  40. package/dist/arguments/generated/_registry/tag_blocks.d.ts +1 -1
  41. package/dist/arguments/generated/_registry/tag_fluids.d.ts +1 -1
  42. package/dist/arguments/generated/_registry/tag_items.d.ts +1 -1
  43. package/dist/arguments/generated/_registry/tag_villager_trades.d.ts +1 -1
  44. package/dist/arguments/generated/_registry/trim_materials.d.ts +1 -1
  45. package/dist/arguments/generated/_registry/trim_patterns.d.ts +1 -1
  46. package/dist/arguments/generated/_registry/worldgen_biomes.d.ts +1 -1
  47. package/dist/arguments/generated/_registry/worldgen_configured_carvers.d.ts +1 -1
  48. package/dist/arguments/generated/_registry/worldgen_density_function_types.d.ts +1 -1
  49. package/dist/arguments/generated/_registry/worldgen_features.d.ts +1 -1
  50. package/dist/arguments/generated/_registry/worldgen_material_conditions.d.ts +1 -1
  51. package/dist/arguments/generated/_registry/worldgen_noises.d.ts +1 -1
  52. package/dist/arguments/generated/_registry/worldgen_placed_features.d.ts +1 -1
  53. package/dist/arguments/generated/_registry/worldgen_pool_alias_bindings.d.ts +1 -1
  54. package/dist/arguments/generated/_registry/worldgen_structure_sets.d.ts +1 -1
  55. package/dist/arguments/generated/_registry/worldgen_structure_types.d.ts +1 -1
  56. package/dist/arguments/generated/_registry/worldgen_structures.d.ts +1 -1
  57. package/dist/arguments/generated/_registry/worldgen_template_pools.d.ts +1 -1
  58. package/dist/arguments/generated/_registry/worldgen_tree_decorator_types.d.ts +1 -1
  59. package/dist/arguments/index.js +1335 -474
  60. package/dist/arguments/selector.d.ts +6 -6
  61. package/dist/commands/commands.d.ts +2 -2
  62. package/dist/commands/implementations/_fake/comment.d.ts +4 -4
  63. package/dist/commands/implementations/block/setblock.d.ts +6 -9
  64. package/dist/commands/implementations/entity/execute.d.ts +36 -21
  65. package/dist/commands/implementations/server/return.d.ts +14 -7
  66. package/dist/commands/implementations/world/data.d.ts +29 -32
  67. package/dist/commands/index.js +1342 -469
  68. package/dist/core/index.js +2136 -1275
  69. package/dist/core/resources/datapack/mcfunction.d.ts +2 -1
  70. package/dist/core/resources/datapack/tag.d.ts +6 -5
  71. package/dist/core/resources/datapack/variant.d.ts +1 -1
  72. package/dist/core/resources/resource.d.ts +4 -4
  73. package/dist/flow/Flow.d.ts +21 -22
  74. package/dist/flow/if_else.d.ts +8 -3
  75. package/dist/flow/index.d.ts +1 -0
  76. package/dist/flow/index.js +2379 -1499
  77. package/dist/flow/loop.d.ts +5 -4
  78. package/dist/flow/loops/for_i.d.ts +1 -1
  79. package/dist/flow/loops/for_of.d.ts +4 -3
  80. package/dist/flow/loops/staticAnalysis.d.ts +26 -0
  81. package/dist/flow/loops/while.d.ts +1 -1
  82. package/dist/flow/switch_case.d.ts +94 -12
  83. package/dist/index.d.ts +16 -12
  84. package/dist/index.js +1341 -476
  85. package/dist/pack/index.js +1343 -469
  86. package/dist/pack/pack.d.ts +17 -17
  87. package/dist/pack/packType.d.ts +1 -1
  88. package/dist/pack/visitors/index.d.ts +1 -0
  89. package/dist/pack/visitors/loopTransformationVisitor.d.ts +13 -6
  90. package/dist/pack/visitors/simplifyExecuteFunction.d.ts +3 -2
  91. package/dist/pack/visitors/simplifyReturnRunFunction.d.ts +2 -1
  92. package/dist/pack/visitors/switchTransformationVisitor.d.ts +31 -0
  93. package/dist/pack/visitors/unifyChainedExecutes.d.ts +3 -2
  94. package/dist/pack/visitors/visitor.d.ts +5 -1
  95. package/dist/utils.d.ts +34 -3
  96. package/dist/variables/Data.d.ts +7 -5
  97. package/dist/variables/DataSets.d.ts +17 -14
  98. package/dist/variables/Label.d.ts +7 -5
  99. package/dist/variables/Loop.d.ts +10 -2
  100. package/dist/variables/ResolveNBT.d.ts +4 -3
  101. package/dist/variables/Score.d.ts +50 -4
  102. package/dist/variables/index.js +1308 -435
  103. package/package.json +6 -3
  104. package/scripts/plugins/hasinstance-plugin.ts +18 -2
  105. package/scripts/watch.ts +1 -1
  106. package/src/arguments/coords.ts +10 -6
  107. package/src/arguments/selector.ts +12 -0
  108. package/src/commands/commands.ts +2 -2
  109. package/src/commands/implementations/_fake/comment.ts +4 -4
  110. package/src/commands/implementations/block/setblock.ts +8 -12
  111. package/src/commands/implementations/entity/damage.ts +2 -2
  112. package/src/commands/implementations/entity/execute.ts +103 -34
  113. package/src/commands/implementations/server/return.ts +15 -7
  114. package/src/commands/implementations/world/data.ts +96 -48
  115. package/src/core/Macro.ts +18 -1
  116. package/src/core/nodes.ts +2 -2
  117. package/src/core/resources/datapack/advancement.ts +1 -1
  118. package/src/core/resources/datapack/bannerPattern.ts +1 -1
  119. package/src/core/resources/datapack/chatType.ts +1 -1
  120. package/src/core/resources/datapack/damageType.ts +1 -1
  121. package/src/core/resources/datapack/dialog.ts +1 -1
  122. package/src/core/resources/datapack/enchantment.ts +2 -2
  123. package/src/core/resources/datapack/gametest.ts +2 -2
  124. package/src/core/resources/datapack/instrument.ts +1 -1
  125. package/src/core/resources/datapack/itemModifier.ts +1 -1
  126. package/src/core/resources/datapack/jukeboxSong.ts +1 -1
  127. package/src/core/resources/datapack/lootTable.ts +1 -1
  128. package/src/core/resources/datapack/mcfunction.ts +47 -24
  129. package/src/core/resources/datapack/predicate.ts +1 -1
  130. package/src/core/resources/datapack/recipe.ts +1 -1
  131. package/src/core/resources/datapack/structure.ts +1 -1
  132. package/src/core/resources/datapack/tag.ts +33 -11
  133. package/src/core/resources/datapack/timeline.ts +2 -2
  134. package/src/core/resources/datapack/trialSpawner.ts +1 -1
  135. package/src/core/resources/datapack/trimMaterial.ts +1 -1
  136. package/src/core/resources/datapack/trimPattern.ts +1 -1
  137. package/src/core/resources/datapack/variant.ts +2 -2
  138. package/src/core/resources/datapack/villagerTrade.ts +2 -2
  139. package/src/core/resources/resource.ts +25 -20
  140. package/src/core/resources/resourcepack/atlas.ts +1 -1
  141. package/src/core/resources/resourcepack/blockstate.ts +1 -1
  142. package/src/core/resources/resourcepack/equipment.ts +1 -1
  143. package/src/core/resources/resourcepack/font.ts +1 -1
  144. package/src/core/resources/resourcepack/itemDefinition.ts +1 -1
  145. package/src/core/resources/resourcepack/language.ts +1 -1
  146. package/src/core/resources/resourcepack/model.ts +1 -1
  147. package/src/core/resources/resourcepack/particle.ts +1 -1
  148. package/src/core/resources/resourcepack/postEffect.ts +1 -1
  149. package/src/core/resources/resourcepack/shader.ts +1 -1
  150. package/src/core/resources/resourcepack/sound.ts +1 -1
  151. package/src/core/resources/resourcepack/waypointStyle.ts +1 -1
  152. package/src/core/sandstoneCore.ts +9 -1
  153. package/src/flow/Flow.ts +58 -94
  154. package/src/flow/conditions/command.ts +1 -1
  155. package/src/flow/conditions/variables/dataPoint.ts +2 -2
  156. package/src/flow/if_else.ts +14 -3
  157. package/src/flow/index.ts +1 -0
  158. package/src/flow/loop.ts +10 -6
  159. package/src/flow/loops/for_i.ts +21 -17
  160. package/src/flow/loops/for_of.ts +43 -36
  161. package/src/flow/loops/staticAnalysis.ts +114 -0
  162. package/src/flow/loops/while.ts +8 -5
  163. package/src/flow/switch_case.ts +214 -13
  164. package/src/index.ts +12 -5
  165. package/src/pack/pack.ts +38 -37
  166. package/src/pack/packType.ts +1 -1
  167. package/src/pack/visitors/containerCommandsToMCFunction.ts +12 -5
  168. package/src/pack/visitors/ifElseTransformationVisitor.ts +75 -38
  169. package/src/pack/visitors/index.ts +1 -0
  170. package/src/pack/visitors/initConstantsVisitor.ts +13 -11
  171. package/src/pack/visitors/loopTransformationVisitor.ts +30 -7
  172. package/src/pack/visitors/simplifyExecuteFunction.ts +83 -19
  173. package/src/pack/visitors/simplifyReturnRunFunction.ts +84 -15
  174. package/src/pack/visitors/switchTransformationVisitor.ts +452 -0
  175. package/src/pack/visitors/unifyChainedExecutes.ts +9 -1
  176. package/src/pack/visitors/visitor.ts +9 -1
  177. package/src/utils.ts +62 -12
  178. package/src/variables/Data.ts +20 -4
  179. package/src/variables/DataSets.ts +57 -23
  180. package/src/variables/JSONTextComponentClass.ts +6 -1
  181. package/src/variables/Label.ts +13 -10
  182. package/src/variables/Loop.ts +30 -1
  183. package/src/variables/Objective.ts +0 -1
  184. package/src/variables/ResolveNBT.ts +5 -3
  185. package/src/variables/Score.ts +239 -9
  186. package/src/variables/Sleep.ts +4 -4
  187. package/src/variables/UUID.ts +8 -6
  188. package/src/variables/nbt/NBTs.ts +41 -4
  189. package/src/variables/parsers.ts +40 -10
package/CLAUDE.md CHANGED
@@ -4,12 +4,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
 
5
5
  ## Build Commands
6
6
 
7
- - **Build**: `bun run build` - Builds the project using tsup and runs setup
8
- - **Watch**: `bun run watch` - Builds with watch mode
9
- - **Type checking**: `bun run build:types` - Generates TypeScript declaration files
10
- - **Setup**: `bun run setup` - Builds types and sets up package (required after build)
11
- - **Lint**: `bun run lint` or `bun oxlint src` - Lints TypeScript files using OxLint
12
- - **Format/Fix**: `bun run format` or `bun oxlint src --fix` - Lints and auto-fixes issues
7
+ - **Build**: `bun dev:build` - Builds the project using a custom Bun Build based script
8
+ - **Watch**: `bun dev:watch` - Builds with watch mode
9
+ - **Type checking**: `bun build:types` - Generates TypeScript declaration files
10
+ - **Lint**: `bun lint` - Lints TypeScript files using OxLint
11
+ - **Format/Fix**: `bun format` - Lints and auto-fixes issues
13
12
 
14
13
  ## Todo Directory
15
14
 
@@ -102,12 +101,146 @@ Central engine managing:
102
101
  - **ResourcePack resources**: Texture, BlockState, Model, Font, SoundEvent, Atlas
103
102
 
104
103
  #### Visitor Pattern (`src/pack/visitors/`)
105
- AST transformation visitors for:
106
- - Converting container commands to MCFunctions
107
- - Transforming if/else and loop constructs
108
- - Initializing constants and objectives
109
- - Inlining function calls
110
- - Simplifying execute commands
104
+
105
+ Visitors transform the AST before serialization. They run in sequence during `core.save()`.
106
+
107
+ **Visitor Base Class:**
108
+ ```typescript
109
+ class GenericSandstoneVisitor {
110
+ // Override to transform specific node types
111
+ visitExecuteCommandNode(node: ExecuteCommandNode) {
112
+ // Transform node, return replacement (or same node)
113
+ return this.genericVisit(node) // Recursively visit children
114
+ }
115
+ }
116
+ ```
117
+
118
+ **Execute-Related Visitors:**
119
+
120
+ | Visitor | Purpose |
121
+ |---------|---------|
122
+ | `UnifyChainedExecutesVisitor` | Merges `execute run execute run...` into single execute; unwraps empty executes (`execute run say hi` → `say hi`) |
123
+ | `SimplifyExecuteFunctionVisitor` | Inlines single-command MCFunctions called from execute |
124
+ | `ContainerCommandsToMCFunctionVisitor` | Extracts multi-command execute bodies into child MCFunctions |
125
+
126
+ **UnifyChainedExecutesVisitor Details:**
127
+ ```typescript
128
+ visitExecuteCommandNode = (node) => {
129
+ // Merge nested execute: execute.run.execute.run.say → execute.run.say
130
+ if (node.body[0] instanceof ExecuteCommandNode) {
131
+ node.body = chainedExecute.body
132
+ node.args.push(...chainedExecute.args)
133
+ }
134
+
135
+ // Unwrap empty execute: execute run say hi → say hi
136
+ const flattenedArgs = node.args.flat(1).filter(a => a != null)
137
+ if (flattenedArgs.length === 0 && node.body.length === 1) {
138
+ return this.genericVisit(node.body[0]) // Return child directly
139
+ }
140
+ }
141
+ ```
142
+
143
+ **Other Key Visitors:**
144
+
145
+ | Visitor | Purpose |
146
+ |---------|---------|
147
+ | `IfElseTransformationVisitor` | Transforms `_.if()` flow control into execute if/unless chains |
148
+ | `LoopTransformationVisitor` | Transforms `_.while()`, `_.forScore()` into recursive function calls; sets `loopExecute` on `LoopArgument` nodes |
149
+ | `SwitchTransformationVisitor` | Transforms `_.switch()` into MCFunctions with O(1) dispatch via macros |
150
+ | `InitConstantsVisitor` | Generates scoreboard objective creation commands |
151
+ | `InlineFunctionCallVisitor` | Inlines tiny MCFunctions to reduce function call overhead |
152
+
153
+ **Visitor Execution Order:**
154
+ Visitors run in a specific order defined in `pack.ts`. Order matters because:
155
+ - Flow transformations must run before container extraction
156
+ - Simplification visitors run after structural transformations
157
+ - Constant initialization runs early to set up scoreboards
158
+ - **SwitchTransformationVisitor runs before IfElseTransformationVisitor** since it creates IfNodes that need to be processed
159
+
160
+ #### Switch Transformation Flow
161
+
162
+ The `SwitchTransformationVisitor` transforms `_.switch()` into efficient MCFunction dispatch:
163
+
164
+ **Score-based switches** (switching on a `Score`):
165
+ - Case functions are named by their value: `case_0`, `case_5`, `case_100`
166
+ - Score is copied to NBT storage, then used as macro: `function case_$(value)`
167
+ - Uses `execute store success` to detect if the macro function exists
168
+ - Falls through to condition cases / default if no match
169
+ - Can be inlined when switch is last node in parent MCFunction
170
+
171
+ **Data-based switches** (switching on NBT data):
172
+ - Uses O(1) NBT storage lookup to map values to sequential indices
173
+ - Case functions are named by index: `case_0`, `case_1`, `case_2`
174
+ - Lookup table initialized in `initMCFunction`
175
+ - Falls through to condition cases / default if no match
176
+
177
+ **Key implementation details:**
178
+
179
+ 1. **enterContext with addNode=false**: When populating the IfNode body for data switches, pass `false` to `enterContext` to avoid auto-adding the node:
180
+ ```typescript
181
+ // Pass false - we manually push ifNode to body later
182
+ switchMCFunction.node.enterContext(ifNode, false)
183
+ functionCmd(innerMCFunction.name, 'with', switchMCFunction.macroPoint!)
184
+ switchMCFunction.node.exitContext()
185
+ ```
186
+
187
+ 2. **Push IfNode before buildFallback**: The IfNode must be added to the body BEFORE calling `buildFallback`, because `buildFallback` may create an `ElseNode` whose constructor auto-adds it to the body. This ensures correct order `[IfNode, ElseNode]` for `IfElseTransformationVisitor`.
188
+
189
+ 3. **Score switch inlining**: For Score-based switches, the macro call is isolated in a child function (`try_case`), so the main switch function body doesn't contain macros and can be inlined.
190
+
191
+ #### Loop Transformation Flow
192
+
193
+ Loops (`_.while()`, `_.for()`, etc.) undergo a multi-stage transformation:
194
+
195
+ **1. User Code Creates LoopNode:**
196
+ ```typescript
197
+ _.while(foo.matches([0,10]), () => {
198
+ say("foo")
199
+ foo['+='](1)
200
+ })
201
+ ```
202
+ Creates a `WhileNode` (extends `LoopNode`) with:
203
+ - `executeArgs`: The condition as execute subcommands
204
+ - `callback`: User's loop body
205
+ - `loopback`: Creates `IfStatement` containing `LoopArgument` for recursion
206
+
207
+ **2. LoopTransformationVisitor:**
208
+ - Transforms `LoopNode` → `ExecuteCommandNode` with `callbackName: 'loop'`
209
+ - Tracks `currentLoopExecute` while visiting children
210
+ - Sets `loopArgument.loopExecute = currentLoopExecute` on any `LoopArgument` found
211
+ - This reference is critical for later resolving the recursive call target
212
+
213
+ **3. IfElseTransformationVisitor:**
214
+ - Transforms the loopback's `IfNode` → `ExecuteCommandNode` with `callbackName: 'if'`
215
+ - Creates nested execute structure for the condition check
216
+
217
+ **4. ContainerCommandsToMCFunctionVisitor:**
218
+ - Extracts multi-command execute bodies into child MCFunctions
219
+ - For the loop execute: creates `parent/loop` MCFunction
220
+ - For the if execute: creates `parent/loop/if` (or `if2` on conflict) MCFunction
221
+ - **Critical**: Sets `executeNode.createdMCFunction` when creating the child function
222
+ - This allows `LoopArgument` to later resolve the correct function name
223
+
224
+ **5. SimplifyExecuteFunctionVisitor:**
225
+ - Finds execute nodes whose body is a single function call
226
+ - If that function contains only a `LoopArgument`:
227
+ - Gets `loopArgument.loopExecute.createdMCFunction.name` (the loop function)
228
+ - Replaces execute body with direct call to loop function
229
+ - Deletes the intermediate if function
230
+ - **Important**: Must check `instanceof LoopArgument` BEFORE `instanceof CommandNode` since `LoopArgument` extends `Node`, not `CommandNode`
231
+
232
+ **Final Output:**
233
+ ```mcfunction
234
+ # parent/loop.mcfunction
235
+ say foo
236
+ scoreboard players add counter __sandstone 1
237
+ execute if score counter __sandstone matches 0..10 run function namespace:parent/loop
238
+ ```
239
+
240
+ **Key Fields for Loop Resolution:**
241
+ - `ExecuteCommandNode.createdMCFunction`: Set by `createMCFunction()`, stores the MCFunction created from this execute
242
+ - `LoopArgument.loopExecute`: Set by `LoopTransformationVisitor`, references the loop's execute node
243
+ - These together allow `LoopArgument` to produce `function <correct-loop-name>` at serialization or simplification time
111
244
 
112
245
  **Visitor files** follow the naming convention `<transformationName>.ts` (e.g., `containerCommandsToMCFunction.ts`, `ifElseTransformationVisitor.ts`).
113
246
 
@@ -188,19 +321,156 @@ mcfunctionNode.exitContext()
188
321
  2. Gets the top of that function's `contextStack`
189
322
  3. Pushes the command node into that context's `body`
190
323
 
191
- #### Execute Command as Container
192
- `ExecuteCommandNode` extends `ContainerCommandNode` - it can contain child commands:
324
+ #### enterContext Pitfalls
325
+
326
+ The `enterContext` method has an `addNode` parameter that defaults to `true`:
327
+
193
328
  ```typescript
194
- // Single command: execute.as('@a').run.say('hi')
195
- // - Creates ExecuteCommandNode with isSingleExecute=true
196
- // - The say command goes into the execute's body
197
-
198
- // Multiple commands: execute.as('@a').run(() => { say('a'); say('b') })
199
- // - Creates ExecuteCommandNode with isSingleExecute=false
200
- // - Both commands go into execute's body
201
- // - Visitor later extracts to child MCFunction if needed
329
+ enterContext = (node: ContainerNode | ContainerCommandNode, addNode: boolean = true) => {
330
+ if (addNode) {
331
+ this.currentContext.append(node) // Auto-adds to current context's body!
332
+ }
333
+ this.contextStack.push(node)
334
+ }
202
335
  ```
203
336
 
337
+ **Pitfall 1: Duplicate nodes when manually pushing**
338
+
339
+ If you call `enterContext(node)` and later manually push the same node to the body, you'll get duplicates:
340
+
341
+ ```typescript
342
+ // WRONG - node gets added twice!
343
+ mcfunction.enterContext(ifNode) // Auto-adds ifNode to body
344
+ // ... populate ifNode.body ...
345
+ mcfunction.exitContext()
346
+ mcfunction.body.push(ifNode) // Duplicate!
347
+
348
+ // CORRECT - pass false to prevent auto-add
349
+ mcfunction.enterContext(ifNode, false) // Does NOT add to body
350
+ // ... populate ifNode.body ...
351
+ mcfunction.exitContext()
352
+ mcfunction.body.push(ifNode) // Only addition
353
+ ```
354
+
355
+ **Pitfall 2: Node constructors that call enterContext**
356
+
357
+ Some node constructors (like `ElseNode`) automatically call `enterContext(this)`:
358
+
359
+ ```typescript
360
+ export class ElseNode extends ContainerNode {
361
+ constructor(sandstoneCore: SandstoneCore, callback: () => void) {
362
+ super(sandstoneCore)
363
+ // This auto-adds the ElseNode to the current MCFunction's body!
364
+ this.sandstoneCore.getCurrentMCFunctionOrThrow().enterContext(this)
365
+ callback()
366
+ this.sandstoneCore.currentMCFunction?.exitContext()
367
+ }
368
+ }
369
+ ```
370
+
371
+ When creating such nodes in visitors, be aware they'll be auto-added to the body. If you only want to link them (e.g., via `nextFlowNode`), you may need to account for their position in the body.
372
+
373
+ **Pitfall 3: Order matters for if/else chains**
374
+
375
+ For `IfElseTransformationVisitor` to work correctly, nodes must be in the body in the correct order:
376
+
377
+ ```typescript
378
+ // WRONG order - ElseNode added before IfNode
379
+ this.buildFallback(ifNode, ...) // Creates ElseNode, auto-adds to body
380
+ mcfunction.body.push(ifNode) // IfNode comes after ElseNode
381
+
382
+ // CORRECT order - IfNode first, then ElseNode
383
+ mcfunction.body.push(ifNode) // IfNode added first
384
+ this.buildFallback(ifNode, ...) // ElseNode auto-added after
385
+ // Result: [IfNode, ElseNode] - correct order for visitor
386
+ ```
387
+
388
+ #### Execute Command Internals
389
+
390
+ `ExecuteCommandNode` extends `ContainerCommandNode` and has special context management for the fluent `.run` API.
391
+
392
+ **Key Properties:**
393
+ - `isSingleExecute`: `true` for `.run.command`, `false` for `.run(() => {...})` callbacks
394
+ - `pendingCommit`: Set when `.run` is accessed on an uncommitted execute; triggers commit after body receives command
395
+ - `args`: Array of subcommands like `[['as', '@a'], ['at', '@s'], ['positioned', '0 0 0']]`
396
+ - `body`: Child command(s) that run after the execute modifiers
397
+ - `createdMCFunction`: Set by `createMCFunction()` when body is extracted to a child MCFunction; used by `LoopArgument` to resolve recursive call targets
398
+ - `macroStorage`: If set, the child function is called with `function <name> with storage <macroStorage> {}`
399
+
400
+ **The `.run` Getter Flow:**
401
+
402
+ ```typescript
403
+ // execute.positioned(...).run.say('hello')
404
+
405
+ get run() {
406
+ const node = this.getNode() // Get or create ExecuteCommandNode
407
+
408
+ return new Proxy(commands, {
409
+ get: (_, prop) => {
410
+ // Mark for deferred commit if not already committed
411
+ if (!node.commited) {
412
+ node.pendingCommit = true
413
+ }
414
+ // Enter execute's context (commands go to execute.body)
415
+ mcfunction.enterContext(node, false) // false = don't add node yet
416
+ return commands[prop]
417
+ }
418
+ })
419
+ }
420
+ ```
421
+
422
+ **Context and Commit Lifecycle:**
423
+
424
+ 1. **Subcommand commits execute**: `.positioned(...)` calls `subCommand([...], ExecuteCommand, executable=true)` which commits the execute to MCFunction
425
+ 2. **`.run` enters context**: Pushes execute onto `contextStack`, subsequent commands go to `execute.body`
426
+ 3. **Child command commits**: `say('hello')` creates node, commits to current context (the execute)
427
+ 4. **`append()` handles cleanup**: Exits context AND commits execute if `pendingCommit` was set
428
+
429
+ ```typescript
430
+ // In ExecuteCommandNode
431
+ append = (...nodes: Node[]) => {
432
+ for (const node of nodes) {
433
+ this.body.push(node)
434
+ if (this.isSingleExecute) {
435
+ // Exit context first (parent becomes current)
436
+ mcfunction.exitContext()
437
+ // Then commit this execute to parent if pending
438
+ if (this.pendingCommit && !this.commited) {
439
+ this.commit() // Adds execute to parent context
440
+ }
441
+ }
442
+ }
443
+ }
444
+ ```
445
+
446
+ **Nested Execute Chains:**
447
+
448
+ For `execute.positioned(...).run.execute.run.say('hi')`:
449
+ 1. Outer execute committed via `.positioned`
450
+ 2. `.run.execute` enters outer's context, returns NEW ExecuteCommand (inner)
451
+ 3. `.run.say` on inner enters inner's context
452
+ 4. `say('hi')` commits to inner's body
453
+ 5. Inner's `append()` exits inner context, commits inner to outer's body (current context)
454
+ 6. Outer's `append()` exits outer context (outer already committed)
455
+
456
+ Result: `execute positioned 0 0 0 run execute run say hi` (visitor simplifies later)
457
+
458
+ **Single vs Multiple Command Mode:**
459
+
460
+ ```typescript
461
+ // Single command: isSingleExecute=true (default)
462
+ execute.as('@a').run.say('hi')
463
+ // - One command in body, stays as single execute node
464
+
465
+ // Callback mode: isSingleExecute=false
466
+ execute.as('@a').run(() => { say('a'); say('b') })
467
+ // - Multiple commands in body
468
+ // - ContainerCommandsToMCFunctionVisitor extracts to child MCFunction
469
+ ```
470
+
471
+ **IMPORTANT - isSingleExecute in Visitors:**
472
+ When creating `ExecuteCommandNode` during visitor transformation, always use `isSingleExecute: false` even for single-command bodies. The `append()` method has special behavior when `isSingleExecute: true` that calls `getCurrentMCFunctionOrThrow().exitContext()`, which fails during visitor passes (no active MCFunction context). Simplification of single-command executes should happen in later visitors like `SimplifyExecuteFunctionVisitor`, not by setting `isSingleExecute: true`.
473
+
204
474
  #### Deferred Execution with autoCommit
205
475
  Commands normally commit immediately when created. Use `autoCommit=false` to defer:
206
476
  ```typescript
@@ -258,6 +528,34 @@ return createDeferredMacroExecute(pack, deferred, {
258
528
  })
259
529
  ```
260
530
 
531
+ ### Debugging Context Issues
532
+
533
+ Context bugs manifest as commands appearing in wrong functions or being orphaned. Common symptoms:
534
+ - Commands from later in the code appear inside earlier execute blocks
535
+ - Commands disappear entirely (orphaned nodes)
536
+ - "Execute nodes can only have one child" errors during save
537
+
538
+ **Debugging Steps:**
539
+
540
+ 1. **Check context stack**: Add logging in `enterContext`/`exitContext` to trace stack state
541
+ 2. **Verify commit timing**: Ensure execute nodes are committed before their context is needed
542
+ 3. **Check `pendingCommit`**: For `.run.command` patterns, execute must commit after body receives command
543
+ 4. **Trace nested executes**: Each `.run` access enters context; ensure matching exits
544
+
545
+ **Common Pitfalls:**
546
+
547
+ | Issue | Cause | Fix |
548
+ |-------|-------|-----|
549
+ | Commands go to wrong execute | Context not exited after previous execute | Ensure `append()` calls `exitContext()` |
550
+ | Execute is orphaned | Never committed to parent | Use `pendingCommit` or ensure subcommand commits |
551
+ | Nested execute loses inner | Inner execute not added to outer's body | Inner must commit while outer's context is current |
552
+ | Double commands | Node committed multiple times | Check `commited` flag before `commit()` |
553
+
554
+ **Key Invariants:**
555
+ - `contextStack[0]` is always the MCFunction itself
556
+ - After a single execute completes, `contextStack.length` should return to previous value
557
+ - Every `enterContext` needs a matching `exitContext`
558
+
261
559
  ### Key Design Patterns
262
560
 
263
561
  - **Visitor Pattern**: AST transformations in `src/pack/visitors/`
package/bun.lock CHANGED
@@ -33,6 +33,9 @@
33
33
  },
34
34
  },
35
35
  },
36
+ "trustedDependencies": [
37
+ "@parcel/watcher",
38
+ ],
36
39
  "packages": {
37
40
  "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
38
41
 
@@ -148,25 +151,25 @@
148
151
 
149
152
  "@types/semver": ["@types/semver@7.5.4", "", {}, "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ=="],
150
153
 
151
- "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.55.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/type-utils": "8.55.0", "@typescript-eslint/utils": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.55.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ=="],
154
+ "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.56.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/type-utils": "8.56.1", "@typescript-eslint/utils": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.56.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A=="],
152
155
 
153
- "@typescript-eslint/parser": ["@typescript-eslint/parser@8.55.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw=="],
156
+ "@typescript-eslint/parser": ["@typescript-eslint/parser@8.56.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg=="],
154
157
 
155
- "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.55.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.55.0", "@typescript-eslint/types": "^8.55.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ=="],
158
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.56.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.56.1", "@typescript-eslint/types": "^8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ=="],
156
159
 
157
- "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0" } }, "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q=="],
160
+ "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1" } }, "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w=="],
158
161
 
159
- "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.55.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q=="],
162
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.56.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ=="],
160
163
 
161
- "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/utils": "8.55.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g=="],
164
+ "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg=="],
162
165
 
163
166
  "@typescript-eslint/types": ["@typescript-eslint/types@8.53.1", "", {}, "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A=="],
164
167
 
165
- "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.55.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.55.0", "@typescript-eslint/tsconfig-utils": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw=="],
168
+ "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.56.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.56.1", "@typescript-eslint/tsconfig-utils": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg=="],
166
169
 
167
- "@typescript-eslint/utils": ["@typescript-eslint/utils@8.55.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow=="],
170
+ "@typescript-eslint/utils": ["@typescript-eslint/utils@8.56.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA=="],
168
171
 
169
- "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA=="],
172
+ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw=="],
170
173
 
171
174
  "@typescript/analyze-trace": ["@typescript/analyze-trace@0.4.0", "", { "dependencies": { "chalk": "^4.1.2", "jsonstream-next": "^3.0.0", "p-limit": "^3.1.0", "split2": "^3.2.2", "treeify": "^1.1.0", "yargs": "^16.2.0" }, "bin": { "analyze-trace": "bin/analyze-trace", "print-trace-types": "bin/print-trace-types", "simplify-trace-types": "bin/simplify-trace-types" } }, "sha512-i7QVVGNNr20P5w3jMuGmozS07mCe8+XaAszFqeR+YpDj3sEbdNK0gRxKnwUbxAz3Auuc4skfSHlE0PaW+MXd1Q=="],
172
175
 
@@ -532,7 +535,7 @@
532
535
 
533
536
  "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
534
537
 
535
- "typescript-eslint": ["typescript-eslint@8.55.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.55.0", "@typescript-eslint/parser": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/utils": "8.55.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw=="],
538
+ "typescript-eslint": ["typescript-eslint@8.56.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.56.1", "@typescript-eslint/parser": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ=="],
536
539
 
537
540
  "unbzip2-stream": ["unbzip2-stream@1.4.3", "", { "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" } }, "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg=="],
538
541
 
@@ -586,23 +589,25 @@
586
589
 
587
590
  "@types/jsonfile/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
588
591
 
589
- "@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
592
+ "@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
590
593
 
591
- "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
594
+ "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
592
595
 
593
- "@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
596
+ "@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
594
597
 
595
- "@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
598
+ "@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
596
599
 
597
- "@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
600
+ "@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
598
601
 
599
- "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
602
+ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
600
603
 
601
604
  "@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
602
605
 
603
- "@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
606
+ "@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
604
607
 
605
- "@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
608
+ "@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
609
+
610
+ "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.0", "", {}, "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q=="],
606
611
 
607
612
  "bl/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
608
613
 
@@ -624,8 +629,6 @@
624
629
 
625
630
  "uri-js/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="],
626
631
 
627
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
628
-
629
632
  "bl/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
630
633
 
631
634
  "bl/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
@@ -633,7 +636,5 @@
633
636
  "tar-stream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
634
637
 
635
638
  "tar-stream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
636
-
637
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
638
639
  }
639
640
  }
@@ -1,4 +1,4 @@
1
- import type { MacroString } from "../core/index.js";
1
+ import type { Macroable, MacroString } from "../core/index.js";
2
2
  import type { VectorClass } from "../variables/index.js";
3
3
  type AbsoluteFloat<MACRO extends boolean = false> = MacroString<`${number}`, MACRO>;
4
4
  type RelativeFloat<MACRO extends boolean = false> = `~${MacroString<number | '', MACRO>}`;
@@ -9,38 +9,36 @@ type AbsoluteOrRelativeVec3<MACRO extends boolean = false> = `${AbsoluteOrRelati
9
9
  type LocalVec3<MACRO extends boolean = false> = `${LocalFloat<MACRO>} ${LocalFloat<MACRO>} ${LocalFloat<MACRO>}`;
10
10
  type AbsoluteOrRelativeVec2<MACRO extends boolean = false> = `${AbsoluteOrRelativeFloat<MACRO>} ${AbsoluteOrRelativeFloat<MACRO>}`;
11
11
  type LocalVec2<MACRO extends boolean = false> = `${LocalFloat<MACRO>} ${LocalFloat<MACRO>}`;
12
+ type AbsoluteVectorArrayComponent<MACRO extends boolean = false> = Macroable<AbsoluteFloat<MACRO> | number, MACRO>;
13
+ type VectorArrayComponent<MACRO extends boolean = false> = Macroable<AbsoluteOrRelativeFloat<MACRO> | LocalFloat<MACRO> | number, MACRO>;
12
14
  export type AbsoluteCoordinates<MACRO extends boolean = false> = [
13
- x: string,
14
- y: string,
15
- z: string
15
+ x: AbsoluteVectorArrayComponent<MACRO>,
16
+ y: AbsoluteVectorArrayComponent<MACRO>,
17
+ z: AbsoluteVectorArrayComponent<MACRO>
16
18
  ] | VectorClass<[
17
19
  string,
18
20
  string,
19
21
  string
20
22
  ]> | AbsoluteVec3<MACRO>;
21
23
  export type Coordinates<MACRO extends boolean = false> = [
22
- x: string,
23
- y: string,
24
- z: string
24
+ x: VectorArrayComponent<MACRO>,
25
+ y: VectorArrayComponent<MACRO>,
26
+ z: VectorArrayComponent<MACRO>
25
27
  ] | VectorClass<[
26
28
  string,
27
29
  string,
28
30
  string
29
31
  ]> | AbsoluteOrRelativeVec3<MACRO> | LocalVec3<MACRO>;
30
32
  export type Rotation<MACRO extends boolean = false> = [
31
- horizontal: AbsoluteOrRelativeFloat<MACRO> | VectorClass<[
32
- string
33
- ]>,
34
- vertical: AbsoluteOrRelativeFloat<MACRO> | VectorClass<[
35
- string
36
- ]>
33
+ horizontal: Macroable<AbsoluteOrRelativeFloat<MACRO> | number, MACRO>,
34
+ vertical: Macroable<AbsoluteOrRelativeFloat<MACRO> | number, MACRO>
37
35
  ] | VectorClass<[
38
36
  string,
39
37
  string
40
38
  ]>;
41
39
  export type ColumnCoordinates<MACRO extends boolean = false> = [
42
- x: string,
43
- z: string
40
+ x: VectorArrayComponent<MACRO>,
41
+ z: VectorArrayComponent<MACRO>
44
42
  ] | VectorClass<[
45
43
  string,
46
44
  string
@@ -1,4 +1,4 @@
1
1
  import { Set } from "../../../index.js";
2
2
  import type { NamespacedLiteralUnion, SetType } from "../../../index.js";
3
3
  export type ACTIVITIES = (NamespacedLiteralUnion<SetType<typeof ACTIVITIES_SET>> | `minecraft:${SetType<typeof ACTIVITIES_SET>}`);
4
- export declare const ACTIVITIES_SET: Set<"admire_item" | "avoid" | "celebrate" | "core" | "dig" | "emerge" | "fight" | "hide" | "idle" | "investigate" | "lay_spawn" | "long_jump" | "meet" | "panic" | "play" | "play_dead" | "pre_raid" | "raid" | "ram" | "rest" | "ride" | "roar" | "sniff" | "swim" | "tongue" | "work">;
4
+ export declare const ACTIVITIES_SET: Set<"core" | "admire_item" | "avoid" | "celebrate" | "dig" | "emerge" | "fight" | "hide" | "idle" | "investigate" | "lay_spawn" | "long_jump" | "meet" | "panic" | "play" | "play_dead" | "pre_raid" | "raid" | "ram" | "rest" | "ride" | "roar" | "sniff" | "swim" | "tongue" | "work">;
@@ -1,4 +1,4 @@
1
1
  import { Set } from "../../../index.js";
2
2
  import type { NamespacedLiteralUnion, SetType } from "../../../index.js";
3
3
  export type ATLASES = (NamespacedLiteralUnion<SetType<typeof ATLASES_SET>> | `minecraft:${SetType<typeof ATLASES_SET>}`);
4
- export declare const ATLASES_SET: Set<"gui" | "decorated_pot" | "armor_trims" | "banner_patterns" | "beds" | "blocks" | "celestials" | "chests" | "items" | "map_decorations" | "paintings" | "particles" | "shield_patterns" | "shulker_boxes" | "signs">;
4
+ export declare const ATLASES_SET: Set<"gui" | "decorated_pot" | "blocks" | "beds" | "shulker_boxes" | "signs" | "armor_trims" | "banner_patterns" | "celestials" | "chests" | "items" | "map_decorations" | "paintings" | "particles" | "shield_patterns">;
@@ -1,4 +1,4 @@
1
1
  import { Set } from "../../../index.js";
2
2
  import type { NamespacedLiteralUnion, SetType } from "../../../index.js";
3
3
  export type ATTRIBUTES = (NamespacedLiteralUnion<SetType<typeof ATTRIBUTES_SET>> | `minecraft:${SetType<typeof ATTRIBUTES_SET>}`);
4
- export declare const ATTRIBUTES_SET: Set<"armor" | "armor_toughness" | "attack_damage" | "attack_knockback" | "attack_speed" | "block_break_speed" | "block_interaction_range" | "burning_time" | "camera_distance" | "entity_interaction_range" | "explosion_knockback_resistance" | "fall_damage_multiplier" | "flying_speed" | "follow_range" | "gravity" | "jump_strength" | "knockback_resistance" | "luck" | "max_absorption" | "max_health" | "mining_efficiency" | "movement_efficiency" | "movement_speed" | "oxygen_bonus" | "safe_fall_distance" | "scale" | "sneaking_speed" | "spawn_reinforcements" | "step_height" | "submerged_mining_speed" | "sweeping_damage_ratio" | "tempt_range" | "water_movement_efficiency" | "waypoint_receive_range" | "waypoint_transmit_range">;
4
+ export declare const ATTRIBUTES_SET: Set<"luck" | "armor" | "armor_toughness" | "attack_damage" | "attack_knockback" | "attack_speed" | "block_break_speed" | "block_interaction_range" | "burning_time" | "camera_distance" | "entity_interaction_range" | "explosion_knockback_resistance" | "fall_damage_multiplier" | "flying_speed" | "follow_range" | "gravity" | "jump_strength" | "knockback_resistance" | "max_absorption" | "max_health" | "mining_efficiency" | "movement_efficiency" | "movement_speed" | "oxygen_bonus" | "safe_fall_distance" | "scale" | "sneaking_speed" | "spawn_reinforcements" | "step_height" | "submerged_mining_speed" | "sweeping_damage_ratio" | "tempt_range" | "water_movement_efficiency" | "waypoint_receive_range" | "waypoint_transmit_range">;