sandstone 1.0.0-beta.4 → 1.0.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.
- package/README.md +3 -4
- package/dist/_internal/index.d.ts +992 -335
- package/dist/_internal/index.js +516 -518
- package/dist/_internal/index.js.map +1 -1
- package/dist/_internal/types/arguments/coords.d.ts +13 -14
- package/dist/_internal/types/arguments/generated/_registry/activities.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/atlases.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/attribute_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/attributes.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/banner_patterns.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/block_definitions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/block_entity_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/block_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/blocks.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/chunk_statuses.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/command_argument_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/creative_mode_tabs.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/custom_stats.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/damage_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/data_component_predicate_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/data_component_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/debug_subscriptions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/decorated_pot_patterns.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/dimension_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_effect_component_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_entity_effect_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_level_based_value_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_location_based_effect_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantment_value_effect_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/enchantments.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/equipments.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/float_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/fluids.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/game_events.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/game_rules.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/height_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/int_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/item_definitions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/items.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/jukebox_songs.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/loot_condition_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/loot_function_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/loot_nbt_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/loot_number_provider_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/memory_module_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/menus.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/mob_effects.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/models.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/painting_variants.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/particle_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/point_of_interest_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/post_effects.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/potions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/recipe_displays.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/recipe_serializers.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/recipe_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/recipes.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/slot_displays.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/slot_source_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/structures.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_blocks.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_entity_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_fluids.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_items.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_point_of_interest_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_timelines.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_villager_trades.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/tag_worldgen_structures.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/textures.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/ticket_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/trigger_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/trim_patterns.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/villager_professions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/wolf_variants.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_biomes.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_density_function_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_features.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_material_conditions.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_noise_settings.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_noises.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_placed_features.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_placement_modifier_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_processor_lists.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_structure_sets.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_structure_types.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_structures.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_template_pools.d.ts +1 -1
- package/dist/_internal/types/arguments/generated/_registry/worldgen_tree_decorator_types.d.ts +1 -1
- package/dist/_internal/types/arguments/objective.d.ts +1 -1
- package/dist/_internal/types/arguments/range.d.ts +7 -7
- package/dist/_internal/types/commands/commands.d.ts +1 -4
- package/dist/_internal/types/commands/implementations/entity/execute.d.ts +9 -3
- package/dist/_internal/types/commands/implementations/server/gamerule.d.ts +38 -3
- package/dist/_internal/types/commands/implementations/server/random.d.ts +3 -3
- package/dist/_internal/types/commands/implementations/world/time.d.ts +6 -6
- package/dist/_internal/types/core/Macro.d.ts +0 -1
- package/dist/_internal/types/core/sandstoneCore.d.ts +8 -0
- package/dist/_internal/types/pack/pack.d.ts +2 -3
- package/dist/_internal/types/utils.d.ts +79 -0
- package/dist/_internal/types/variables/Score.d.ts +20 -4
- package/dist/_internal/types/variables/Sleep.d.ts +0 -3
- package/dist/_internal/types/variables/nbt/NBTs.d.ts +28 -1
- package/dist/browser/package.json +3 -0
- package/dist/browser/sandstone.esm.js +61581 -0
- package/dist/browser/sandstone.esm.js.map +1 -0
- package/dist/exports/commands/index.d.ts +1 -1
- package/dist/exports/core/index.d.ts +1 -1
- package/dist/exports/index.d.ts +1 -1
- package/dist/exports/index.js +1 -1
- package/package.json +22 -18
- package/src/arguments/coords.ts +11 -14
- package/src/arguments/objective.ts +1 -1
- package/src/arguments/range.ts +9 -9
- package/src/commands/commands.ts +3 -3
- package/src/commands/implementations/block/fill.ts +3 -3
- package/src/commands/implementations/block/setblock.ts +2 -2
- package/src/commands/implementations/entity/clear.ts +5 -1
- package/src/commands/implementations/entity/execute.ts +27 -6
- package/src/commands/implementations/entity/summon.ts +2 -2
- package/src/commands/implementations/player/dialog.ts +2 -2
- package/src/commands/implementations/player/give.ts +2 -2
- package/src/commands/implementations/player/particle.ts +2 -2
- package/src/commands/implementations/server/debug.ts +6 -1
- package/src/commands/implementations/server/function.ts +8 -3
- package/src/commands/implementations/server/gamerule.ts +75 -3
- package/src/commands/implementations/server/random.ts +3 -3
- package/src/commands/implementations/server/schedule.ts +10 -2
- package/src/commands/implementations/world/data.ts +5 -5
- package/src/commands/implementations/world/item.ts +2 -2
- package/src/commands/implementations/world/time.ts +5 -5
- package/src/core/Macro.ts +0 -2
- package/src/core/nodes.ts +17 -1
- package/src/core/resources/datapack/mcfunction.ts +12 -5
- package/src/core/resources/datapack/structure.ts +1 -0
- package/src/core/resources/resourcepack/sound.ts +2 -4
- package/src/core/sandstoneCore.ts +17 -0
- package/src/flow/conditions/variables/block.ts +2 -2
- package/src/flow/loops/for_i.ts +17 -15
- package/src/flow/loops/for_of.ts +0 -1
- package/src/pack/pack.ts +13 -6
- package/src/sandstone.ts +2 -2
- package/src/utils.ts +159 -0
- package/src/variables/Data.ts +3 -3
- package/src/variables/ItemPredicate.ts +2 -2
- package/src/variables/Score.ts +18 -10
- package/src/variables/Selector.ts +21 -3
- package/src/variables/Sleep.ts +2 -10
- package/src/variables/Trigger.ts +3 -5
- package/src/variables/nbt/NBTs.ts +70 -19
package/src/variables/Score.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
} from 'sandstone/arguments'
|
|
14
14
|
import type { ExecuteCommand, SandstoneCommands } from 'sandstone/commands'
|
|
15
15
|
import type { NotNode } from 'sandstone/flow'
|
|
16
|
-
import {
|
|
16
|
+
import { nbtResolver, type ConditionClass } from 'sandstone/variables'
|
|
17
17
|
import * as util from 'util'
|
|
18
18
|
import { MacroArgument } from '../core/Macro'
|
|
19
19
|
import type { SandstonePack } from '../pack'
|
|
@@ -96,7 +96,7 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
toNBT() {
|
|
99
|
-
return
|
|
99
|
+
return nbtResolver(this._toChatComponent() as NBTObject).toString()
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
toJSON() {
|
|
@@ -353,6 +353,8 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
353
353
|
return this.binaryOperation('%=', ...args)
|
|
354
354
|
}
|
|
355
355
|
|
|
356
|
+
mod = this.modulo
|
|
357
|
+
|
|
356
358
|
'%=' = this.modulo
|
|
357
359
|
|
|
358
360
|
/**
|
|
@@ -443,6 +445,8 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
443
445
|
return createVariable(this.sandstonePack, this).binaryOperation('*=', ...args)
|
|
444
446
|
}
|
|
445
447
|
|
|
448
|
+
times = this.multipliedBy
|
|
449
|
+
|
|
446
450
|
'*' = this.multipliedBy
|
|
447
451
|
|
|
448
452
|
/**
|
|
@@ -487,6 +491,8 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
487
491
|
return createVariable(this.sandstonePack, this).binaryOperation('%=', ...args)
|
|
488
492
|
}
|
|
489
493
|
|
|
494
|
+
modBy = this.moduloBy
|
|
495
|
+
|
|
490
496
|
'%' = this.moduloBy
|
|
491
497
|
|
|
492
498
|
/** COMPARISONS OPERATORS */
|
|
@@ -548,20 +554,20 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
548
554
|
*
|
|
549
555
|
* @param objective The related objective. If not specified, default to the same objective as the current target.
|
|
550
556
|
*/
|
|
551
|
-
|
|
557
|
+
greaterThanOrEqualTo(targets: MultipleEntitiesArgument<false>, objective?: ObjectiveArgument): ConditionClass
|
|
552
558
|
|
|
553
559
|
/**
|
|
554
560
|
* Check if the current score is greater or equal than the given amount or score.
|
|
555
561
|
*
|
|
556
562
|
* @param amountOrTargetScore The amount or score compare the current score against.
|
|
557
563
|
*/
|
|
558
|
-
|
|
564
|
+
greaterThanOrEqualTo(amountOrTargetScore: number | Score): ConditionClass
|
|
559
565
|
|
|
560
|
-
|
|
566
|
+
greaterThanOrEqualTo(...args: OperationArguments) {
|
|
561
567
|
return this.comparison('>=', `${args[0]}..`, args)
|
|
562
568
|
}
|
|
563
569
|
|
|
564
|
-
'>=' = this.
|
|
570
|
+
'>=' = this.greaterThanOrEqualTo
|
|
565
571
|
|
|
566
572
|
/**
|
|
567
573
|
* Check if the current score is strictly lower than the given score.
|
|
@@ -592,20 +598,20 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
592
598
|
*
|
|
593
599
|
* @param objective The related objective. If not specified, default to the same objective as the current target.
|
|
594
600
|
*/
|
|
595
|
-
|
|
601
|
+
lessThanOrEqualTo(targets: MultipleEntitiesArgument<false>, objective?: ObjectiveArgument): ConditionClass
|
|
596
602
|
|
|
597
603
|
/**
|
|
598
604
|
* Check if the current score is lower or equal than the given amount or score.
|
|
599
605
|
*
|
|
600
606
|
* @param amountOrTargetScore The amount or score target to compare the current score against.
|
|
601
607
|
*/
|
|
602
|
-
|
|
608
|
+
lessThanOrEqualTo(amountOrTargetScore: number | Score): ConditionClass
|
|
603
609
|
|
|
604
|
-
|
|
610
|
+
lessThanOrEqualTo(...args: OperationArguments) {
|
|
605
611
|
return this.comparison('<=', `..${args[0]}`, args)
|
|
606
612
|
}
|
|
607
613
|
|
|
608
|
-
'<=' = this.
|
|
614
|
+
'<=' = this.lessThanOrEqualTo
|
|
609
615
|
|
|
610
616
|
/**
|
|
611
617
|
* Check if the current score is equal to than the given score.
|
|
@@ -627,6 +633,8 @@ export class Score extends MacroArgument implements ConditionClass, ComponentCla
|
|
|
627
633
|
return this.comparison('=', args[0].toString(), args)
|
|
628
634
|
}
|
|
629
635
|
|
|
636
|
+
equals = this.equalTo
|
|
637
|
+
|
|
630
638
|
'==' = this.equalTo
|
|
631
639
|
|
|
632
640
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { GAMEMODES, JSONTextComponent, NBTSerializable, Range, RootNBT, SymbolEntity } from 'sandstone/arguments'
|
|
5
5
|
import type { PredicateClass, SandstoneCore, TagClass } from 'sandstone/core'
|
|
6
6
|
import type { SandstonePack } from 'sandstone/pack'
|
|
7
|
-
import {
|
|
7
|
+
import { nbtResolver, ResolvedNBT } from 'sandstone/variables/nbt/NBTs'
|
|
8
8
|
import { rangeParser } from 'sandstone/variables/parsers'
|
|
9
9
|
import * as util from 'util'
|
|
10
10
|
import type { Macroable } from '../core/Macro'
|
|
@@ -316,6 +316,17 @@ export class SelectorClass<
|
|
|
316
316
|
|
|
317
317
|
arguments: SelectorProperties<IsSingle, IsPlayer, SelectorEntityType, MACRO>
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Whether the most recent `toString()` produced a selector string containing
|
|
321
|
+
* any `$(...)` macro substitution. `CommandNode.getValue()` reads this so it
|
|
322
|
+
* can flag the surrounding command as a macro command (prefixed with `$`),
|
|
323
|
+
* even though `toString()` itself returns a plain string (the `$(...)` is
|
|
324
|
+
* baked in via template literal coercion).
|
|
325
|
+
*
|
|
326
|
+
* @internal
|
|
327
|
+
*/
|
|
328
|
+
_hasMacro = false
|
|
329
|
+
|
|
319
330
|
constructor(
|
|
320
331
|
protected sandstonePack: SandstonePack,
|
|
321
332
|
public target: '@s' | '@p' | '@a' | '@e' | '@n' | '@r',
|
|
@@ -335,10 +346,11 @@ export class SelectorClass<
|
|
|
335
346
|
|
|
336
347
|
toString() {
|
|
337
348
|
if (!this.arguments || !Object.keys(this.arguments).length) {
|
|
349
|
+
this._hasMacro = false
|
|
338
350
|
return this.target
|
|
339
351
|
}
|
|
340
352
|
|
|
341
|
-
const result: (readonly [string, string])[] = []
|
|
353
|
+
const result: (readonly [string, string | ResolvedNBT])[] = []
|
|
342
354
|
|
|
343
355
|
const args = { ...this.arguments }
|
|
344
356
|
|
|
@@ -349,7 +361,13 @@ export class SelectorClass<
|
|
|
349
361
|
// Parse potentially multiple nbt
|
|
350
362
|
nbt: (nbt: RootNBT | RootNBT[]) => {
|
|
351
363
|
const nbts = Array.isArray(nbt) ? nbt : [nbt]
|
|
352
|
-
|
|
364
|
+
for (const nbt_ of nbts) {
|
|
365
|
+
const resolved = nbtResolver(nbt_)
|
|
366
|
+
if (resolved.containsMacro) {
|
|
367
|
+
this._hasMacro = true
|
|
368
|
+
}
|
|
369
|
+
result.push(['nbt', resolved] as const)
|
|
370
|
+
}
|
|
353
371
|
},
|
|
354
372
|
|
|
355
373
|
// Parse advancements
|
package/src/variables/Sleep.ts
CHANGED
|
@@ -69,6 +69,8 @@ export class SleepClass extends AwaitNode {
|
|
|
69
69
|
|
|
70
70
|
const timer = new ObjectiveClass(core.pack, name.replace(':', '.'), 'dummy', undefined, { creator: 'sandstone' })
|
|
71
71
|
|
|
72
|
+
core.pack.registerNewObjective(timer)
|
|
73
|
+
|
|
72
74
|
execute.store.result(timer('@s')).run.time.query('gametime')
|
|
73
75
|
|
|
74
76
|
timer('@s').add(Duration)
|
|
@@ -102,14 +104,4 @@ export class SleepClass extends AwaitNode {
|
|
|
102
104
|
|
|
103
105
|
core.awaitNodes.add(this)
|
|
104
106
|
}
|
|
105
|
-
|
|
106
|
-
promise() {
|
|
107
|
-
return {
|
|
108
|
-
// oxlint-disable-next-line no-thenable
|
|
109
|
-
then: (async (onfullfilled?: () => void | Promise<void>) => {
|
|
110
|
-
await onfullfilled?.()
|
|
111
|
-
return this
|
|
112
|
-
}) as any,
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
107
|
}
|
package/src/variables/Trigger.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { _RawMCFunctionClass, type MCFunctionClass } from 'sandstone/core/resour
|
|
|
3
3
|
import { ObjectiveClass } from './Objective'
|
|
4
4
|
import type { Score } from './Score'
|
|
5
5
|
|
|
6
|
-
const checkTriggers: Record<number, MCFunctionClass<undefined, undefined>> = {}
|
|
7
|
-
|
|
8
6
|
export type TriggerHandler =
|
|
9
7
|
| (() => any)
|
|
10
8
|
| MCFunctionClass<undefined, undefined>
|
|
@@ -26,14 +24,14 @@ export class TriggerClass<HANDLE extends TriggerHandler> {
|
|
|
26
24
|
|
|
27
25
|
registerNewObjective(this.objective)
|
|
28
26
|
|
|
29
|
-
if (!checkTriggers[pollingEvery]) {
|
|
30
|
-
checkTriggers[pollingEvery] = MCFunction(`triggers/check/${pollingEvery}`, {
|
|
27
|
+
if (!sandstoneCore.checkTriggers[pollingEvery]) {
|
|
28
|
+
sandstoneCore.checkTriggers[pollingEvery] = MCFunction(`triggers/check/${pollingEvery}`, {
|
|
31
29
|
creator: 'sandstone',
|
|
32
30
|
runEvery: pollingEvery,
|
|
33
31
|
})
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
checkTriggers[pollingEvery].push(() => {
|
|
34
|
+
sandstoneCore.checkTriggers[pollingEvery].push(() => {
|
|
37
35
|
commands.execute.as(`@a[scores={${name}=1..}]`).run(() => {
|
|
38
36
|
const score = this.objective('@s')
|
|
39
37
|
|
|
@@ -128,7 +128,7 @@ export class NotNBT<VALUE extends RootNBT = RootNBT> extends NBTClass {
|
|
|
128
128
|
this.nbt = nbt
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
[util.inspect.custom] = () => `!${
|
|
131
|
+
[util.inspect.custom] = () => `!${nbtResolver(this.nbt)}`
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
export type NBTAllNumberClasses<Range extends NBTRange = {}> = NBTLong<Range> | NBTShort<Range> | NBTByte<Range> | NBTFloat<Range> | NBTDouble<Range> | NBTInt<Range>
|
|
@@ -161,7 +161,7 @@ function customNumber<T extends number | number[], C extends NBTSimpleClasses>(
|
|
|
161
161
|
function dynamicNBT(template: TemplateStringsArray, ...args: unknown[]): NBTObject {
|
|
162
162
|
const mixedArgs = template.flatMap((s, i) => [s, args[i]]).slice(0, -1) // Remove the last argument, which will always be undefined
|
|
163
163
|
const result = mixedArgs
|
|
164
|
-
.map((element: any) => (element instanceof NBTClass ?
|
|
164
|
+
.map((element: any) => (element instanceof NBTClass ? nbtResolver(element).toString() : element.toString()))
|
|
165
165
|
.join('')
|
|
166
166
|
|
|
167
167
|
return parseNBT(NBT, result)
|
|
@@ -440,25 +440,45 @@ export const NBT: NBTInterface = makeCallable(
|
|
|
440
440
|
|
|
441
441
|
not: (nbt: RootNBT) => new NotNBT(nbt),
|
|
442
442
|
|
|
443
|
-
stringify: (nbt: NBTObject) =>
|
|
443
|
+
stringify: (nbt: NBTObject) => nbtResolver(nbt).toString(),
|
|
444
444
|
|
|
445
445
|
parse: (nbt: string) => parseNBT(NBT, nbt),
|
|
446
446
|
},
|
|
447
447
|
dynamicNBT,
|
|
448
448
|
)
|
|
449
449
|
|
|
450
|
-
|
|
450
|
+
/**
|
|
451
|
+
* The resolved result of converting a Sandstone NBT value (which may contain
|
|
452
|
+
* live `MacroArgument` references) into the final Minecraft SNBT string.
|
|
453
|
+
*
|
|
454
|
+
* Carries macro information up to `CommandNode.getValue()` so commands with
|
|
455
|
+
* `$(...)` substitutions can be flagged as macro commands (prefixed with `$`)
|
|
456
|
+
* even when the macro originated from inside a nested value rather than as
|
|
457
|
+
* a top-level arg object.
|
|
458
|
+
*/
|
|
459
|
+
export class ResolvedNBT {
|
|
460
|
+
constructor(
|
|
461
|
+
public readonly value: string,
|
|
462
|
+
public readonly containsMacro: boolean,
|
|
463
|
+
) {}
|
|
464
|
+
|
|
465
|
+
toString(): string {
|
|
466
|
+
return this.value
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const resolve = (nbt: NBTObject | MacroArgument): ResolvedNBT => {
|
|
451
471
|
if (nbt === null || nbt === undefined) {
|
|
452
472
|
throw new Error('Nullish nbt values are not allowed')
|
|
453
473
|
}
|
|
454
474
|
if (typeof nbt === 'number') {
|
|
455
475
|
// We have a double, integers are now required to be defined with NBT.int
|
|
456
|
-
return `${nbt}d
|
|
476
|
+
return new ResolvedNBT(`${nbt}d`, false)
|
|
457
477
|
}
|
|
458
478
|
|
|
459
479
|
if (typeof nbt === 'boolean') {
|
|
460
480
|
// We have a boolean
|
|
461
|
-
return nbt.toString()
|
|
481
|
+
return new ResolvedNBT(nbt.toString(), false)
|
|
462
482
|
}
|
|
463
483
|
|
|
464
484
|
if (typeof nbt === 'string') {
|
|
@@ -476,22 +496,29 @@ export const nbtStringifier = (nbt: NBTObject | MacroArgument): string => {
|
|
|
476
496
|
})
|
|
477
497
|
|
|
478
498
|
if (inspectedStr[0] === '`') {
|
|
479
|
-
return JSON.stringify(nbt)
|
|
499
|
+
return new ResolvedNBT(JSON.stringify(nbt), false)
|
|
480
500
|
}
|
|
481
501
|
|
|
482
|
-
return inspectedStr
|
|
502
|
+
return new ResolvedNBT(inspectedStr, false)
|
|
483
503
|
}
|
|
484
504
|
|
|
485
505
|
if (Array.isArray(nbt)) {
|
|
486
506
|
// We have an array
|
|
487
|
-
|
|
488
|
-
|
|
507
|
+
let containsMacro = false
|
|
508
|
+
const itemsStr = nbt
|
|
509
|
+
.map((item) => {
|
|
510
|
+
const resolved = resolve(item)
|
|
511
|
+
if (resolved.containsMacro) containsMacro = true
|
|
512
|
+
return resolved.value
|
|
513
|
+
})
|
|
514
|
+
.join(',')
|
|
515
|
+
return new ResolvedNBT(`[${itemsStr}]`, containsMacro)
|
|
489
516
|
}
|
|
490
517
|
|
|
491
518
|
// We have an object
|
|
492
519
|
if (nbt instanceof NBTClass) {
|
|
493
520
|
// It's actually a "Minecraft Primitive", like 3b, and not an object
|
|
494
|
-
return nbt[util.inspect.custom]()
|
|
521
|
+
return new ResolvedNBT(nbt[util.inspect.custom](), false)
|
|
495
522
|
}
|
|
496
523
|
|
|
497
524
|
if (typeof nbt === 'object' || typeof nbt === 'function') {
|
|
@@ -503,32 +530,56 @@ export const nbtStringifier = (nbt: NBTObject | MacroArgument): string => {
|
|
|
503
530
|
if (macro === '$()') {
|
|
504
531
|
failedMacro = true
|
|
505
532
|
} else {
|
|
506
|
-
return macro
|
|
533
|
+
return new ResolvedNBT(macro, true)
|
|
507
534
|
}
|
|
508
535
|
}
|
|
509
536
|
if ('toNBT' in nbt) {
|
|
537
|
+
// toNBT itself may recurse through nbtResolver, so reuse its result.
|
|
510
538
|
// @ts-ignore
|
|
511
|
-
|
|
539
|
+
const toNbtResult = nbt.toNBT()
|
|
540
|
+
if (toNbtResult instanceof ResolvedNBT) {
|
|
541
|
+
return toNbtResult
|
|
542
|
+
}
|
|
543
|
+
return new ResolvedNBT(String(toNbtResult), false)
|
|
512
544
|
} else if (failedMacro) {
|
|
513
|
-
throw new Error('[
|
|
545
|
+
throw new Error('[nbtResolver] A macro variable NBT insertion was attempted in an mcfunction without macros defined.')
|
|
514
546
|
}
|
|
515
547
|
if (typeof nbt === 'function') {
|
|
516
548
|
/* @ts-ignore */
|
|
517
|
-
throw new Error(`[
|
|
549
|
+
throw new Error(`[nbtResolver] This should never happen. A function or callable instance (${nbt.constructor?.name}) without toNBT was passed in as an NBT value.`)
|
|
518
550
|
}
|
|
519
551
|
if (nbt.constructor.name !== 'Object') {
|
|
520
552
|
if ('toString' in nbt) {
|
|
521
|
-
return `${toString}
|
|
553
|
+
return new ResolvedNBT(`${toString}`, false)
|
|
522
554
|
} else {
|
|
523
555
|
/* @ts-ignore */
|
|
524
|
-
throw new Error(`[
|
|
556
|
+
throw new Error(`[nbtResolver] A ${nbt.constructor?.name} was passed in as an NBT value. Hint: define toNBT or toString if this was intentional`)
|
|
525
557
|
}
|
|
526
558
|
}
|
|
527
559
|
}
|
|
528
560
|
|
|
529
561
|
// It's a real object.
|
|
562
|
+
let containsMacro = false
|
|
530
563
|
const objectStr = Object.entries(nbt)
|
|
531
|
-
.map(([key, value]) =>
|
|
564
|
+
.map(([key, value]) => {
|
|
565
|
+
const resolved = resolve(value as NBTObject)
|
|
566
|
+
if (resolved.containsMacro) containsMacro = true
|
|
567
|
+
return `${key}:${resolved.value}`
|
|
568
|
+
})
|
|
532
569
|
.join(',')
|
|
533
|
-
return `{${objectStr}}
|
|
570
|
+
return new ResolvedNBT(`{${objectStr}}`, containsMacro)
|
|
534
571
|
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Resolves a Sandstone NBT value into its Minecraft SNBT string form.
|
|
575
|
+
*
|
|
576
|
+
* Unlike the previous `nbtStringifier`, the result is a `ResolvedNBT` object
|
|
577
|
+
* that preserves whether the value contained `$(...)` macro substitutions.
|
|
578
|
+
* `CommandNode.getValue()` uses `containsMacro` to decide whether to emit the
|
|
579
|
+
* command as a macro command (prefixed with `$`).
|
|
580
|
+
*
|
|
581
|
+
* Callers that need a plain string (template literals, string concatenation)
|
|
582
|
+
* can rely on `ResolvedNBT`'s `toString()`, which is called automatically by
|
|
583
|
+
* JS coercion. To be explicit, call `.toString()` on the result.
|
|
584
|
+
*/
|
|
585
|
+
export const nbtResolver = (nbt: NBTObject | MacroArgument): ResolvedNBT => resolve(nbt)
|