sandstone 1.1.3 → 1.1.5

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 (54) hide show
  1. package/dist/_internal/index.d.ts +7 -15
  2. package/dist/_internal/index.d.ts.map +1 -1
  3. package/dist/_internal/index.js +227 -75
  4. package/dist/_internal/index.js.map +1 -1
  5. package/dist/_internal/types/arguments/generated/resources.d.ts +2 -2
  6. package/dist/_internal/types/arguments/generated/resources.d.ts.map +1 -1
  7. package/dist/_internal/types/commands/implementations/block/place.d.ts +1 -1
  8. package/dist/_internal/types/commands/implementations/block/place.d.ts.map +1 -1
  9. package/dist/_internal/types/commands/implementations/server/schedule.d.ts +1 -1
  10. package/dist/_internal/types/core/resources/index.d.ts +1 -1
  11. package/dist/_internal/types/core/resources/resourcepack/blockstate.d.ts +13 -13
  12. package/dist/_internal/types/core/resources/resourcepack/blockstate.d.ts.map +1 -1
  13. package/dist/_internal/types/flow/Flow.d.ts +27 -13
  14. package/dist/_internal/types/flow/Flow.d.ts.map +1 -1
  15. package/dist/_internal/types/flow/conditions/command.d.ts.map +1 -1
  16. package/dist/_internal/types/flow/conditions/condition.d.ts +8 -0
  17. package/dist/_internal/types/flow/conditions/condition.d.ts.map +1 -1
  18. package/dist/_internal/types/flow/conditions/variables/dataPoint.d.ts.map +1 -1
  19. package/dist/_internal/types/flow/loop.d.ts +1 -1
  20. package/dist/_internal/types/pack/index.d.ts +1 -1
  21. package/dist/_internal/types/pack/pack.d.ts +7 -7
  22. package/dist/_internal/types/pack/pack.d.ts.map +1 -1
  23. package/dist/_internal/types/pack/visitors/orTransformationVisitor.d.ts +41 -6
  24. package/dist/_internal/types/pack/visitors/orTransformationVisitor.d.ts.map +1 -1
  25. package/dist/_internal/types/variables/Data.d.ts +1 -1
  26. package/dist/_internal/types/variables/DataSets.d.ts +4 -4
  27. package/dist/_internal/types/variables/DataSets.d.ts.map +1 -1
  28. package/dist/_internal/types/variables/ResolveNBT.d.ts +2 -2
  29. package/dist/_internal/types/variables/abstractClasses.d.ts +9 -0
  30. package/dist/_internal/types/variables/abstractClasses.d.ts.map +1 -1
  31. package/dist/browser/sandstone.esm.js +227 -75
  32. package/dist/browser/sandstone.esm.js.map +1 -1
  33. package/dist/exports/core/index.d.ts +1 -1
  34. package/dist/exports/core/index.js +1 -1
  35. package/dist/exports/index.d.ts +1 -1
  36. package/dist/exports/index.js +1 -1
  37. package/dist/exports/variables/index.d.ts +1 -1
  38. package/dist/exports/variables/index.js +1 -1
  39. package/package.json +3 -3
  40. package/src/arguments/generated/resources.ts +2 -2
  41. package/src/commands/implementations/block/place.ts +1 -1
  42. package/src/core/resources/datapack/itemModifier.ts +2 -2
  43. package/src/core/resources/resourcepack/blockstate.ts +32 -32
  44. package/src/flow/Flow.ts +24 -4
  45. package/src/flow/conditions/command.ts +7 -0
  46. package/src/flow/conditions/condition.ts +9 -0
  47. package/src/flow/conditions/variables/dataPoint.ts +11 -3
  48. package/src/pack/pack.ts +19 -38
  49. package/src/pack/visitors/orTransformationVisitor.ts +311 -37
  50. package/src/sandstone.ts +4 -20
  51. package/src/variables/DataSets.ts +4 -4
  52. package/src/variables/abstractClasses.ts +10 -0
  53. package/src/core/resources/datapack/decoratedPotPattern.ts.disable +0 -47
  54. package/src/core/resources/datapack/slotSource.ts.disable +0 -47
@@ -1,68 +1,342 @@
1
- import { ScoreboardCommandNode } from '../../commands'
2
- import type { Node } from '../../core'
3
- import { AndNode, type ConditionNode, IfNode, NotNode, OrNode } from '../../flow'
1
+ import { ExecuteCommandNode, type SubCommand, ReturnCommandNode, ScoreboardCommandNode } from '../../commands'
2
+ import { MCFunctionClass, type MCFunctionNode, type Node, type SandstoneCore } from '../../core'
3
+ import type { Score } from '../../variables'
4
+ import { AndNode, ConditionNode, IfNode, NotNode, OrNode } from '../../flow'
4
5
  import { GenericSandstoneVisitor } from './visitor'
5
6
 
7
+ /**
8
+ * Condition node whose `getValue()` returns `"if function <name>"`.
9
+ * Used to make an IfNode's existing `IfElseTransformationVisitor` emit
10
+ * `execute if function <child> run <body>`, which succeeds exactly when the
11
+ * child MCFunction returns a positive value (e.g. via an early `return 1`).
12
+ */
13
+ class FunctionReturnConditionNode extends ConditionNode {
14
+ constructor(
15
+ public sandstoneCore: SandstoneCore,
16
+ public functionName: string,
17
+ ) {
18
+ super(sandstoneCore)
19
+ }
20
+
21
+ getValue = () => `if function ${this.functionName}`
22
+ }
23
+
6
24
  export class OrTransformationVisitor extends GenericSandstoneVisitor {
7
25
  visitIfNode = (node_: IfNode) => {
8
- const { preNodes, conditionNode } = this.parseConditionNode(node_.condition)
26
+ const { preNodes, conditionNode } = this.parseConditionNode(node_.condition, node_.parentMCFunction)
9
27
  node_.condition = conditionNode
10
28
  return [...preNodes, this.genericVisit(node_)]
11
29
  }
12
30
 
13
- parseConditionNode = (node: ConditionNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
31
+ parseConditionNode = (node: ConditionNode, parentMCFunction?: MCFunctionNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
14
32
  if (node instanceof OrNode) {
15
- return this.parseOrNode(node)
33
+ return this.parseOrNode(node, parentMCFunction)
16
34
  }
17
35
  if (node instanceof AndNode) {
18
- return this.parseAndNode(node)
36
+ return this.parseAndNode(node, parentMCFunction)
19
37
  }
20
38
  if (node instanceof NotNode) {
21
- return this.parseNotNode(node)
39
+ return this.parseNotNode(node, parentMCFunction)
22
40
  }
23
41
 
24
- // Default case, just return the node as is
25
- return { preNodes: [], conditionNode: node }
42
+ // `preNodes` is optional on ConditionNode. Side-effecting conditions (those that
43
+ // commit commands at construction, e.g. `data.equals`, `Label.equals`, any
44
+ // `CommandCondition`) populate it; pure predicates leave it unset.
45
+ return { preNodes: [...(node.preNodes ?? [])], conditionNode: node }
26
46
  }
27
- parseOrNode = (node: OrNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
28
- const variable = this.core.pack.Variable(undefined, 'condition')
29
47
 
30
- const conditionNode = variable.equalTo(1)._toMinecraftCondition()
48
+ parseOrNode = (node: OrNode, parentMCFunction?: MCFunctionNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
49
+ // Single branch: collapse through so the IfNode behaves as if it had the inner condition.
50
+ if (node.conditions.length === 1) {
51
+ return this.parseConditionNode(node.conditions[0], parentMCFunction)
52
+ }
53
+
54
+ // Multiple branches: extract to a child MCFunction with execute-if-return-1 short-circuit.
55
+ // Inside the child: `execute if <c1> run return 1`, `execute if <c2> run return 1`, ..., `return 0`.
56
+ // The first matching branch returns 1 and exits the function immediately; the rest are skipped.
57
+ // The caller uses `execute if function <child>` to test whether any branch matched.
58
+ const parentName = parentMCFunction?.resource.name ?? '__sandstone'
59
+ const orMCFunction = new MCFunctionClass(
60
+ this.core,
61
+ `${parentName}/or_check`,
62
+ {
63
+ addToSandstoneCore: true,
64
+ creator: 'sandstone',
65
+ onConflict: 'rename',
66
+ },
67
+ )
31
68
 
32
- const realPreNodes: Node[] = [new ScoreboardCommandNode(this.pack, 'players', 'reset', variable)]
33
- const orExecuteNodes = node.conditions.map((condition) => {
34
- const { preNodes, conditionNode: parsedConditionNode } = this.parseConditionNode(condition)
35
- realPreNodes.push(...preNodes)
69
+ this.core.enterMCFunction(orMCFunction)
36
70
 
37
- const ifNode = new IfNode(this.core, parsedConditionNode)
38
- ifNode.body = [new ScoreboardCommandNode(this.pack, 'players', 'set', variable, 1)]
39
- return ifNode
40
- })
71
+ try {
72
+ for (const condition of node.conditions) {
73
+ this.pushCheckBranch(orMCFunction.node, this.parseConditionNode(condition, orMCFunction.node), false, new ReturnCommandNode(this.pack, [1]))
74
+ }
75
+
76
+ // Default return: no branch matched.
77
+ orMCFunction.node.body.push(new ReturnCommandNode(this.pack, [0]))
78
+ } finally {
79
+ this.core.exitMCFunction()
80
+ }
41
81
 
42
82
  return {
43
- preNodes: [...realPreNodes, ...orExecuteNodes],
44
- conditionNode,
83
+ preNodes: [],
84
+ conditionNode: new FunctionReturnConditionNode(this.core, orMCFunction.name),
45
85
  }
46
86
  }
47
- parseAndNode = (node: AndNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
48
- const finalPreNodes: Node[] = []
49
-
50
- const conditionNode = new AndNode(
51
- node.sandstoneCore,
52
- node.conditions.map((condition) => {
53
- const { preNodes, conditionNode } = this.parseConditionNode(condition)
54
- finalPreNodes.push(...preNodes)
55
- return conditionNode
56
- }),
87
+
88
+ parseAndNode = (node: AndNode, parentMCFunction?: MCFunctionNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
89
+ // Single branch: collapse through so the IfNode behaves as if it had the inner condition.
90
+ if (node.conditions.length === 1) {
91
+ return this.parseConditionNode(node.conditions[0], parentMCFunction)
92
+ }
93
+
94
+ // Parse every condition to learn whether it carries commands (preNodes) that must run
95
+ // before the predicate is evaluated. Pure-predicate conditions chain cleanly inside a
96
+ // single execute — those are batched. Command-needing conditions force the AND into a
97
+ // child MCFunction so commands can run inline before their check.
98
+ const parsed = node.conditions.map((condition) => this.parseConditionNode(condition, parentMCFunction))
99
+ const anyHasCommands = parsed.some((p) => (p.preNodes ?? []).length > 0)
100
+
101
+ if (!anyHasCommands) {
102
+ // Inline: pure conditions chain via the existing AndNode behavior. Order is preserved
103
+ // by `Array.prototype.map`. No child function needed.
104
+ const finalPreNodes: Node[] = []
105
+ const conditionNode = new AndNode(
106
+ node.sandstoneCore,
107
+ parsed.map((p) => {
108
+ finalPreNodes.push(...p.preNodes)
109
+ return p.conditionNode
110
+ }),
111
+ )
112
+ return { preNodes: finalPreNodes, conditionNode }
113
+ }
114
+
115
+ // At least one condition needs to run commands. Extract to a child MCFunction:
116
+ // - Pure-predicate runs are batched into `execute <pos-c1> <pos-c2> ... run return 1`
117
+ // (positive form, NOT flipped — chain fires `return 1` only when the whole batch
118
+ // holds; otherwise we fall through to the next check).
119
+ // - Command-needing conditions emit their stashed side-effects inline, then a flipped
120
+ // `execute if <failure-form> run return 0` so the function returns 0 as soon as a
121
+ // side-effecting check fails to hold.
122
+ // - Default `return 0` reaches the end only when no command-needing check failed and
123
+ // no pure batch all-held; the function returns 1 only via a pure-batch success path,
124
+ // signalled to the caller by `execute if function <and>`.
125
+ const parentName = parentMCFunction?.resource.name ?? '__sandstone'
126
+ const andMCFunction = new MCFunctionClass(
127
+ this.core,
128
+ `${parentName}/and_check`,
129
+ {
130
+ addToSandstoneCore: true,
131
+ creator: 'sandstone',
132
+ onConflict: 'rename',
133
+ },
57
134
  )
58
135
 
136
+ this.core.enterMCFunction(andMCFunction)
137
+
138
+ try {
139
+ let batch: { preNodes: Node[][]; conditionNodes: ConditionNode[] } = { preNodes: [], conditionNodes: [] }
140
+
141
+ const flushBatch = () => {
142
+ if (batch.conditionNodes.length === 0 && batch.preNodes.every((pn) => pn.length === 0)) {
143
+ batch = { preNodes: [], conditionNodes: [] }
144
+ return
145
+ }
146
+ // Per-batch tracker-var pattern: reset the tracker, run the chained execute to set
147
+ // the tracker to 1 only when the entire batch holds, then check the tracker and
148
+ // `return 0` if any condition failed (var != 1). Each batch uses its own tracker var
149
+ // so concurrent/sequential batches stay independent.
150
+ const tracker = this.core.pack.Variable(undefined, 'and_batch')
151
+ this.pushBatchedCheckBranch(
152
+ andMCFunction.node,
153
+ batch.preNodes.flat(),
154
+ batch.conditionNodes,
155
+ tracker,
156
+ )
157
+ batch = { preNodes: [], conditionNodes: [] }
158
+ }
159
+
160
+ for (const p of parsed) {
161
+ if (p.preNodes.length === 0) {
162
+ // Pure predicate: extend the current batch (still in declared order).
163
+ batch.preNodes.push(p.preNodes)
164
+ batch.conditionNodes.push(p.conditionNode)
165
+ } else {
166
+ // Command-needing condition: flush any pending batch first (preserving order),
167
+ // then emit this condition's commands followed by its own fail-fast check.
168
+ flushBatch()
169
+ this.pushFailFastBranch(
170
+ andMCFunction.node,
171
+ p,
172
+ new ReturnCommandNode(this.pack, [0]),
173
+ )
174
+ }
175
+ }
176
+ flushBatch()
177
+
178
+ // Default return: every check ran without success.
179
+ andMCFunction.node.body.push(new ReturnCommandNode(this.pack, [1]))
180
+ } finally {
181
+ this.core.exitMCFunction()
182
+ }
183
+
59
184
  return {
60
- preNodes: finalPreNodes,
61
- conditionNode,
185
+ preNodes: [],
186
+ conditionNode: new FunctionReturnConditionNode(this.core, andMCFunction.name),
62
187
  }
63
188
  }
64
- parseNotNode = (node: NotNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
65
- const { preNodes, conditionNode } = this.parseConditionNode(node.condition)
189
+
190
+ /**
191
+ * Pushes a batched check into `targetMCFunction.body` using the tracker-var pattern:
192
+ * <preNodes...>
193
+ * scoreboard players reset <tracker>
194
+ * execute <if|unless> <c1> <if|unless> <c2> ... run scoreboard players set <tracker> 1
195
+ * execute unless score <tracker> matches 1 run return 0
196
+ *
197
+ * Consecutive pure-predicate conditions from the AND list coalesce into a single chained
198
+ * execute that sets the tracker to 1 only when the entire batch holds. The trailing
199
+ * fail-check returns 0 from the child MCFunction when any condition failed (var != 1).
200
+ * Using a tracker var avoids the "execute-chain only fires on ALL-pass" limitation of
201
+ * pure MC chains while keeping the body tight.
202
+ */
203
+ private pushBatchedCheckBranch = (
204
+ targetMCFunction: MCFunctionNode,
205
+ preNodes: Node[],
206
+ conditionNodes: ConditionNode[],
207
+ tracker: Score,
208
+ ) => {
209
+ for (const n of preNodes) {
210
+ targetMCFunction.body.push(n)
211
+ }
212
+
213
+ targetMCFunction.body.push(new ScoreboardCommandNode(this.pack, 'players', 'reset', tracker))
214
+
215
+ const args: SubCommand[] = []
216
+ for (const c of conditionNodes) {
217
+ const condStr = c.getValue(false)
218
+ const match = condStr.match(/^(if|unless)\s+([\s\S]+)$/)
219
+ if (!match) {
220
+ throw new Error(`OrTransformationVisitor: unexpected condition getValue() shape: ${condStr}`)
221
+ }
222
+ const [, keyword, condBody] = match
223
+ args.push([keyword, condBody])
224
+ }
225
+
226
+ if (args.length === 0) {
227
+ // No conditions but preNodes ran — push an unconditional set so the trailing check
228
+ // doesn't fire on a stale tracker.
229
+ targetMCFunction.body.push(new ScoreboardCommandNode(this.pack, 'players', 'set', tracker, 1))
230
+ } else {
231
+ const executeNode = new ExecuteCommandNode(this.pack, args, {
232
+ isSingleExecute: true,
233
+ body: [],
234
+ })
235
+ targetMCFunction.enterContext(executeNode, false)
236
+ executeNode.body = [new ScoreboardCommandNode(this.pack, 'players', 'set', tracker, 1)]
237
+ targetMCFunction.body.push(executeNode)
238
+ targetMCFunction.exitContext()
239
+ }
240
+
241
+ const failCheckNode = new ExecuteCommandNode(
242
+ this.pack,
243
+ [['unless', `score ${tracker} matches 1`]],
244
+ {
245
+ isSingleExecute: true,
246
+ body: [],
247
+ },
248
+ )
249
+ targetMCFunction.enterContext(failCheckNode, false)
250
+ failCheckNode.body = [new ReturnCommandNode(this.pack, [0])]
251
+ targetMCFunction.body.push(failCheckNode)
252
+ targetMCFunction.exitContext()
253
+ }
254
+
255
+ /**
256
+ * Pushes a single check branch into `targetMCFunction.body`:
257
+ * <preNodes...> (side-effect commands that must run before checking)
258
+ * execute <if|unless> <condBody> run <bodyNode>
259
+ *
260
+ * When `negated` is false, the helper uses the condition's positive form
261
+ * (`getValue(false)`); when true, it uses the failure form (`getValue(true)`).
262
+ * For OR semantics: pass `negated=false` with `bodyNode = return 1` (exit on first match).
263
+ */
264
+ private pushCheckBranch = (
265
+ targetMCFunction: MCFunctionNode,
266
+ parsed: { preNodes: Node[]; conditionNode: ConditionNode },
267
+ negated: boolean,
268
+ bodyNode: Node,
269
+ ) => {
270
+ // Any nested preNodes (e.g. nested or/and reset+score commands, or the inner
271
+ // condition's side-effect commands) run inside the child function body in order.
272
+ for (const n of parsed.preNodes) {
273
+ targetMCFunction.body.push(n)
274
+ }
275
+
276
+ // Extract the chain keyword ("if" or "unless") and the condition body from `getValue()`.
277
+ // SingleConditionNode returns "if <body>"; NotNode-wrapped conditions return "unless <body>".
278
+ // AndNode already produces execute-chain strings; a nested FunctionReturnConditionNode
279
+ // returns "if function <name>" which fits the same shape.
280
+ const condStr = parsed.conditionNode.getValue(negated)
281
+ const match = condStr.match(/^(if|unless)\s+([\s\S]+)$/)
282
+ if (!match) {
283
+ throw new Error(`OrTransformationVisitor: unexpected condition getValue() shape: ${condStr}`)
284
+ }
285
+ const [, keyword, condBody] = match
286
+
287
+ // Construct ExecuteCommandNode for `execute <keyword> <condBody> run <bodyNode>`.
288
+ // The constructor's append() calls exitContext, so we first push an empty executeNode
289
+ // into the MCFunction context stack (addNode=false) so the exit succeeds.
290
+ const executeNode = new ExecuteCommandNode(this.pack, [[keyword, condBody]], {
291
+ isSingleExecute: true,
292
+ body: [],
293
+ })
294
+ targetMCFunction.enterContext(executeNode, false)
295
+ executeNode.body = [bodyNode]
296
+ targetMCFunction.body.push(executeNode)
297
+ targetMCFunction.exitContext()
298
+ }
299
+
300
+ /**
301
+ * Pushes a fail-fast check for an AND command-needing condition into `targetMCFunction.body`:
302
+ * <preNodes...>
303
+ * execute <if|unless> <condBody> run <bodyNode>
304
+ *
305
+ * Uses the condition's FAILURE form (`getValue(true)`) and flips the leading
306
+ * `if`/`unless` keyword so the execute fires when the condition fails to hold. The
307
+ * `bodyNode` (typically `return 0`) exits the child MCFunction immediately. When the
308
+ * condition holds, the chain doesn't fire and we fall through to the next check.
309
+ */
310
+ private pushFailFastBranch = (
311
+ targetMCFunction: MCFunctionNode,
312
+ parsed: { preNodes: Node[]; conditionNode: ConditionNode },
313
+ bodyNode: Node,
314
+ ) => {
315
+ for (const n of parsed.preNodes) {
316
+ targetMCFunction.body.push(n)
317
+ }
318
+
319
+ const condStr = parsed.conditionNode.getValue(true)
320
+ const match = condStr.match(/^(if|unless)\s+([\s\S]+)$/)
321
+ if (!match) {
322
+ throw new Error(`OrTransformationVisitor: unexpected condition getValue() shape: ${condStr}`)
323
+ }
324
+ // Flip the leading keyword so the execute fires on failure rather than success.
325
+ const flippedKeyword = match[1] === 'if' ? 'unless' : 'if'
326
+ const condBody = match[2]
327
+
328
+ const executeNode = new ExecuteCommandNode(this.pack, [[flippedKeyword, condBody]], {
329
+ isSingleExecute: true,
330
+ body: [],
331
+ })
332
+ targetMCFunction.enterContext(executeNode, false)
333
+ executeNode.body = [bodyNode]
334
+ targetMCFunction.body.push(executeNode)
335
+ targetMCFunction.exitContext()
336
+ }
337
+
338
+ parseNotNode = (node: NotNode, parentMCFunction?: MCFunctionNode): { preNodes: Node[]; conditionNode: ConditionNode } => {
339
+ const { preNodes, conditionNode } = this.parseConditionNode(node.condition, parentMCFunction)
66
340
  return {
67
341
  preNodes,
68
342
  conditionNode: new NotNode(node.sandstoneCore, conditionNode),
package/src/sandstone.ts CHANGED
@@ -5,10 +5,9 @@ import type {
5
5
  AdvancementClassArguments,
6
6
  AtlasClassArguments,
7
7
  BannerPatternClassArguments,
8
- BlockStateArguments,
8
+ BlockStateDefinitionArguments,
9
9
  ChatTypeClassArguments,
10
10
  DamageTypeClassArguments,
11
- // DecoratedPotPatternClassArguments,
12
11
  DialogClassArguments,
13
12
  EnchantmentClassArguments,
14
13
  EnchantmentProviderClassArguments,
@@ -28,7 +27,6 @@ import type {
28
27
  PredicateClassArguments,
29
28
  RecipeClassArguments,
30
29
  ShaderClassArguments,
31
- // SlotSourceClassArguments,
32
30
  SoundEventArguments,
33
31
  SoundsIndexArguments,
34
32
  SulfurCubeArchetypeClassArguments,
@@ -295,7 +293,6 @@ export const {
295
293
  BannerPattern,
296
294
  ChatType,
297
295
  DamageType,
298
- // DecoratedPotPattern,
299
296
  Dialog,
300
297
  Enchantment,
301
298
  EnchantmentProvider,
@@ -305,7 +302,6 @@ export const {
305
302
  LootTable,
306
303
  Predicate,
307
304
  Recipe,
308
- // SlotSource,
309
305
  SulfurCubeArchetype,
310
306
  Tag,
311
307
  TestEnvironment,
@@ -320,7 +316,7 @@ export const {
320
316
  WorldClock,
321
317
 
322
318
  Atlas,
323
- BlockState,
319
+ BlockStateDefinition,
324
320
  Equipment,
325
321
  Font,
326
322
  ItemModelDefinition,
@@ -380,7 +376,6 @@ export {
380
376
  BannerPatternClass,
381
377
  ChatTypeClass,
382
378
  DamageTypeClass,
383
- // DecoratedPotPatternClass,
384
379
  DialogClass,
385
380
  EnchantmentClass,
386
381
  EnchantmentProviderClass,
@@ -390,7 +385,6 @@ export {
390
385
  LootTableClass,
391
386
  PredicateClass,
392
387
  RecipeClass,
393
- // SlotSourceClass,
394
388
  StructureClass,
395
389
  SulfurCubeArchetypeClass,
396
390
  TagClass,
@@ -407,7 +401,7 @@ export {
407
401
 
408
402
  // Resourcepack resources
409
403
  AtlasClass,
410
- BlockStateClass,
404
+ BlockStateDefinitionClass,
411
405
  EquipmentClass,
412
406
  FontClass,
413
407
  ItemModelDefinitionClass,
@@ -673,11 +667,6 @@ type ContentStrategy =
673
667
  * Will override the defined `default` strategy.
674
668
  */
675
669
  | ContentStrategyKind<'recipe', NonNullable<RecipeClassArguments['onConflict']>>
676
- /**
677
- * The conflict strategy to use for Slot sources.
678
- * Will override the defined `default` strategy.
679
- */
680
- // | ContentStrategyKind<'slot_source', NonNullable<SlotSourceClassArguments['onConflict']>>
681
670
  /**
682
671
  * The conflict strategy to use for Sulfur cube archetypes.
683
672
  * Will override the defined `default` strategy.
@@ -713,11 +702,6 @@ type ContentStrategy =
713
702
  * Will override the defined `default` strategy.
714
703
  */
715
704
  | ContentStrategyKind<'chat_type', NonNullable<ChatTypeClassArguments['onConflict']>>
716
- /**
717
- * The conflict strategy to use for Decorated pot patterns.
718
- * Will override the defined `default` strategy.
719
- */
720
- // | ContentStrategyKind<'decorated_pot_pattern', NonNullable<DecoratedPotPatternClassArguments['onConflict']>>
721
705
  /**
722
706
  * The conflict strategy to use for Dialogs.
723
707
  * Will override the defined `default` strategy.
@@ -793,7 +777,7 @@ type ContentStrategy =
793
777
  * The conflict strategy to use for Block states.
794
778
  * Will override the defined `default` strategy.
795
779
  */
796
- | ContentStrategyKind<'block_state', NonNullable<BlockStateArguments<any>['onConflict']>>
780
+ | ContentStrategyKind<'block_definition', NonNullable<BlockStateDefinitionArguments<any>['onConflict']>>
797
781
  /**
798
782
  * The conflict strategy to use for Fonts.
799
783
  * Will override the defined `default` strategy.
@@ -456,7 +456,7 @@ export class DataArrayClass<INITIAL extends DataArrayInitial> extends IterableDa
456
456
  }
457
457
  }
458
458
 
459
- export function DataIndexMap<INITIAL extends DataIndexMapInitial>(
459
+ export function DataIndexMapInternal<INITIAL extends DataIndexMapInitial>(
460
460
  pack: SandstonePack,
461
461
  initialize: INITIAL,
462
462
  dataPoint?: DataPointClass<'storage'>,
@@ -486,11 +486,11 @@ export function DataIndexMap<INITIAL extends DataIndexMapInitial>(
486
486
  }
487
487
  }
488
488
 
489
- export type DataIndexMap<INITIAL extends DataIndexMapInitial> = DataIndexMapClass<INITIAL> & {
489
+ export type DataIndexMapType<INITIAL extends DataIndexMapInitial> = DataIndexMapClass<INITIAL> & {
490
490
  [K in keyof INITIAL]: DataIndexMapInitial[`${any}${string}`]
491
491
  } & { [K in string]: DataIndexMapInitial[`${any}${string}`] }
492
492
 
493
- export function DataArray<INITIAL extends DataArrayInitial>(
493
+ export function DataArrayInternal<INITIAL extends DataArrayInitial>(
494
494
  pack: SandstonePack,
495
495
  initialize: INITIAL,
496
496
  dataPoint?: DataPointClass<'storage'>,
@@ -520,6 +520,6 @@ export function DataArray<INITIAL extends DataArrayInitial>(
520
520
  }
521
521
  }
522
522
 
523
- export type DataArray<INITIAL extends DataArrayInitial> = DataArrayClass<INITIAL> & {
523
+ export type DataArrayType<INITIAL extends DataArrayInitial> = DataArrayClass<INITIAL> & {
524
524
  [K in keyof INITIAL]: DataArrayInitial[number]
525
525
  } & { [K in number]: DataArrayInitial[number] }
@@ -1,4 +1,5 @@
1
1
  import type { JSONTextComponent } from 'sandstone/arguments/jsonTextComponent'
2
+ import type { Node } from 'sandstone/core'
2
3
  import type { ConditionNode } from '../flow'
3
4
  import type { SelectorClass } from './Selector'
4
5
  import type { NBTSerializable } from 'sandstone/arguments'
@@ -24,6 +25,15 @@ export class ConditionClass {
24
25
  */
25
26
  declare readonly __conditionClassBrand: true
26
27
 
28
+ /**
29
+ * Optional commands that must run before this condition's predicate is evaluated.
30
+ * Conditions that emit side-effect commands at construction (e.g. `data.equals`
31
+ * building `execute store result ...`) capture them here so the visitor pass can
32
+ * re-emit them at the right location — inline before the IfNode, or inside the
33
+ * child MCFunction when AND/OR extracts. Optional; pure predicates leave it unset.
34
+ */
35
+ preNodes?: Node[]
36
+
27
37
  /**
28
38
  * @internal
29
39
  */
@@ -1,47 +0,0 @@
1
- import { RESOURCE_PATHS, type SymbolResource } from 'sandstone/arguments'
2
- import { ContainerNode } from '../../nodes'
3
- import type { SandstoneCore } from '../../sandstoneCore'
4
- import type { ResourceClassArguments, ResourceNode } from '../resource'
5
- import { ResourceClass, jsonStringify } from '../resource'
6
-
7
- /**
8
- * A node representing a Minecraft decorated pot pattern.
9
- */
10
- export class DecoratedPotPatternNode extends ContainerNode implements ResourceNode<DecoratedPotPatternClass> {
11
- constructor(
12
- sandstoneCore: SandstoneCore,
13
- public resource: DecoratedPotPatternClass,
14
- ) {
15
- super(sandstoneCore)
16
- }
17
-
18
- getValue = () => jsonStringify(this.resource.decoratedPotPatternJSON, this.resource._resourceType as keyof typeof RESOURCE_PATHS)
19
- }
20
-
21
- export type DecoratedPotPatternClassArguments = {
22
- /**
23
- * The decorated pot pattern's JSON.
24
- */
25
- json: SymbolResource[(typeof DecoratedPotPatternClass)['resourceType']]
26
- } & ResourceClassArguments<'default'>
27
-
28
- export class DecoratedPotPatternClass extends ResourceClass<DecoratedPotPatternNode> {
29
- static readonly resourceType = 'decorated_pot_pattern' as const
30
-
31
- public decoratedPotPatternJSON: NonNullable<DecoratedPotPatternClassArguments['json']>
32
-
33
- constructor(sandstoneCore: SandstoneCore, name: string, args: DecoratedPotPatternClassArguments) {
34
- super(
35
- sandstoneCore,
36
- { packType: sandstoneCore.pack.dataPack(), extension: 'json' },
37
- DecoratedPotPatternNode,
38
- DecoratedPotPatternClass.resourceType,
39
- sandstoneCore.pack.resourceToPath(name, RESOURCE_PATHS[DecoratedPotPatternClass.resourceType].path),
40
- args,
41
- )
42
-
43
- this.decoratedPotPatternJSON = args.json
44
-
45
- this.handleConflicts()
46
- }
47
- }
@@ -1,47 +0,0 @@
1
- import { RESOURCE_PATHS, type SymbolResource } from 'sandstone/arguments'
2
- import { ContainerNode } from '../../nodes'
3
- import type { SandstoneCore } from '../../sandstoneCore'
4
- import type { ResourceClassArguments, ResourceNode } from '../resource'
5
- import { ResourceClass, jsonStringify } from '../resource'
6
-
7
- /**
8
- * A node representing a Minecraft slot source.
9
- */
10
- export class SlotSourceNode extends ContainerNode implements ResourceNode<SlotSourceClass> {
11
- constructor(
12
- sandstoneCore: SandstoneCore,
13
- public resource: SlotSourceClass,
14
- ) {
15
- super(sandstoneCore)
16
- }
17
-
18
- getValue = () => jsonStringify(this.resource.slotSourceJSON, this.resource._resourceType as keyof typeof RESOURCE_PATHS)
19
- }
20
-
21
- export type SlotSourceClassArguments = {
22
- /**
23
- * The slot source's JSON.
24
- */
25
- json: NonNullable<SymbolResource[(typeof SlotSourceClass)['resourceType']]>
26
- } & ResourceClassArguments<'default'>
27
-
28
- export class SlotSourceClass extends ResourceClass<SlotSourceNode> {
29
- static readonly resourceType = 'slot_source' as const
30
-
31
- public slotSourceJSON: NonNullable<SlotSourceClassArguments['json']>
32
-
33
- constructor(sandstoneCore: SandstoneCore, name: string, args: SlotSourceClassArguments) {
34
- super(
35
- sandstoneCore,
36
- { packType: sandstoneCore.pack.dataPack(), extension: 'json' },
37
- SlotSourceNode,
38
- SlotSourceClass.resourceType,
39
- sandstoneCore.pack.resourceToPath(name, RESOURCE_PATHS[SlotSourceClass.resourceType].path),
40
- args,
41
- )
42
-
43
- this.slotSourceJSON = args.json
44
-
45
- this.handleConflicts()
46
- }
47
- }