@spyglassmc/java-edition 0.3.8 → 0.3.10

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 (35) hide show
  1. package/lib/binder/index.d.ts +11 -9
  2. package/lib/binder/index.js +149 -150
  3. package/lib/common/index.js +6 -9
  4. package/lib/dependency/common.d.ts +5 -0
  5. package/lib/dependency/common.js +8 -0
  6. package/lib/dependency/index.js +7 -17
  7. package/lib/dependency/mcmeta.d.ts +6 -12
  8. package/lib/dependency/mcmeta.js +21 -38
  9. package/lib/index.d.ts +1 -0
  10. package/lib/index.js +74 -32
  11. package/lib/json/checker/index.d.ts +3 -10
  12. package/lib/json/checker/index.js +36 -244
  13. package/lib/json/index.d.ts +0 -1
  14. package/lib/json/index.js +0 -3
  15. package/lib/mcfunction/checker/index.d.ts +0 -2
  16. package/lib/mcfunction/checker/index.js +254 -183
  17. package/lib/mcfunction/common/index.d.ts +4 -2
  18. package/lib/mcfunction/common/index.js +56 -52
  19. package/lib/mcfunction/completer/argument.js +112 -57
  20. package/lib/mcfunction/index.d.ts +3 -2
  21. package/lib/mcfunction/index.js +18 -19
  22. package/lib/mcfunction/inlayHintProvider.js +2 -3
  23. package/lib/mcfunction/mcdocAttributes.d.ts +4 -0
  24. package/lib/mcfunction/mcdocAttributes.js +74 -0
  25. package/lib/mcfunction/node/argument.d.ts +115 -12
  26. package/lib/mcfunction/node/argument.js +131 -63
  27. package/lib/mcfunction/parser/argument.d.ts +14 -4
  28. package/lib/mcfunction/parser/argument.js +380 -212
  29. package/lib/mcfunction/signatureHelpProvider.d.ts +2 -1
  30. package/lib/mcfunction/signatureHelpProvider.js +10 -18
  31. package/lib/mcfunction/tree/argument.d.ts +68 -1
  32. package/lib/mcfunction/tree/patch.js +279 -77
  33. package/lib/mcfunction/tree/patchValidator.d.ts +7 -0
  34. package/lib/mcfunction/tree/patchValidator.js +25 -0
  35. package/package.json +8 -9
@@ -5,8 +5,8 @@ import { localeQuote, localize } from '@spyglassmc/locales';
5
5
  import * as mcf from '@spyglassmc/mcfunction';
6
6
  import * as nbt from '@spyglassmc/nbt';
7
7
  import { ReleaseVersion } from '../../dependency/index.js';
8
- import { ColorArgumentValues, EntityAnchorArgumentValues, GamemodeArgumentValues, HeightmapValues, ItemSlotArgumentValues, MirrorValues, OperationArgumentValues, RotationValues, ScoreboardSlotArgumentValues, SwizzleArgumentValues, } from '../common/index.js';
9
- import { BlockStatesNode, EntitySelectorArgumentsNode, EntitySelectorAtVariable, EntitySelectorAtVariables, EntitySelectorNode, ObjectiveCriteriaNode, TimeNode, } from '../node/index.js';
8
+ import { ColorArgumentValues, EntityAnchorArgumentValues, GamemodeArgumentValues, getItemSlotArgumentValues, getItemSlotsArgumentValues, getScoreboardSlotArgumentValues, HeightmapValues, MirrorValues, OperationArgumentValues, RotationValues, SwizzleArgumentValues, } from '../common/index.js';
9
+ import { BlockStatesNode, ComponentListNode, ComponentTestsNode, EntitySelectorArgumentsNode, EntitySelectorAtVariable, EntitySelectorNode, ObjectiveCriteriaNode, TimeNode, } from '../node/index.js';
10
10
  const IntegerPattern = /^-?\d+$/;
11
11
  /**
12
12
  * A combination of:
@@ -37,6 +37,10 @@ function shouldValidateLength(ctx) {
37
37
  const release = ctx.project['loadedVersion'];
38
38
  return !release || ReleaseVersion.cmp(release, '1.18') < 0;
39
39
  }
40
+ function shouldUseOldItemStackFormat(ctx) {
41
+ const release = ctx.project['loadedVersion'];
42
+ return !release || ReleaseVersion.cmp(release, '1.20.5') < 0;
43
+ }
40
44
  /**
41
45
  * @returns The parser for the specified argument tree node. All argument parsers used in the `mcfunction` package
42
46
  * fail on empty input.
@@ -83,26 +87,19 @@ export const argument = (rawTreeNode) => {
83
87
  case 'minecraft:column_pos':
84
88
  return wrap(vector({ dimension: 2, integersOnly: true }));
85
89
  case 'minecraft:component':
86
- return wrap(component);
90
+ return wrap(jsonParser('::java::server::util::text::Text'));
87
91
  case 'minecraft:dimension':
88
- return wrap(core.resourceLocation({
89
- category: 'dimension',
90
- }));
92
+ return wrap(core.resourceLocation({ category: 'dimension' }));
91
93
  case 'minecraft:entity':
92
94
  return wrap(entity(treeNode.properties.amount, treeNode.properties.type));
93
95
  case 'minecraft:entity_anchor':
94
96
  return wrap(core.literal(...EntityAnchorArgumentValues));
95
97
  case 'minecraft:entity_summon':
96
- return wrap(core.resourceLocation({
97
- category: 'entity_type',
98
- }));
98
+ return wrap(core.resourceLocation({ category: 'entity_type' }));
99
99
  case 'minecraft:float_range':
100
100
  return wrap(range('float'));
101
101
  case 'minecraft:function':
102
- return wrap(core.resourceLocation({
103
- category: 'function',
104
- allowTag: true,
105
- }));
102
+ return wrap(core.resourceLocation({ category: 'function', allowTag: true }));
106
103
  case 'minecraft:gamemode':
107
104
  return wrap(core.literal(...GamemodeArgumentValues));
108
105
  case 'minecraft:game_profile':
@@ -112,27 +109,31 @@ export const argument = (rawTreeNode) => {
112
109
  case 'minecraft:int_range':
113
110
  return wrap(range('integer'));
114
111
  case 'minecraft:item_enchantment':
115
- return wrap(core.resourceLocation({
116
- category: 'enchantment',
117
- }));
112
+ return wrap(core.resourceLocation({ category: 'enchantment' }));
118
113
  case 'minecraft:item_predicate':
119
114
  return wrap(itemPredicate);
120
115
  case 'minecraft:item_slot':
121
- return wrap(core.literal(...ItemSlotArgumentValues));
116
+ return wrap(itemSlot);
117
+ case 'minecraft:item_slots':
118
+ return wrap(itemSlots);
122
119
  case 'minecraft:item_stack':
123
120
  return wrap(itemStack);
121
+ case 'minecraft:loot_modifier':
122
+ return wrap(resourceOrInline('item_modifier'));
123
+ case 'minecraft:loot_predicate':
124
+ return wrap(resourceOrInline('predicate'));
125
+ case 'minecraft:loot_table':
126
+ return wrap(resourceOrInline('loot_table'));
124
127
  case 'minecraft:message':
125
128
  return wrap(message);
126
129
  case 'minecraft:mob_effect':
127
- return wrap(core.resourceLocation({
128
- category: 'mob_effect',
129
- }));
130
+ return wrap(core.resourceLocation({ category: 'mob_effect' }));
130
131
  case 'minecraft:nbt_compound_tag':
131
- return wrap(nbt.parser.compound);
132
+ return wrap(nbtParser(nbt.parser.compound, treeNode.properties));
132
133
  case 'minecraft:nbt_path':
133
- return wrap(nbt.parser.path);
134
+ return wrap(nbtPathParser(nbt.parser.path, treeNode.properties));
134
135
  case 'minecraft:nbt_tag':
135
- return wrap(nbt.parser.entry);
136
+ return wrap(nbtParser(nbt.parser.entry, treeNode.properties));
136
137
  case 'minecraft:objective':
137
138
  return wrap(objective(core.SymbolUsageType.is(treeNode.properties?.usageType)
138
139
  ? treeNode.properties?.usageType
@@ -140,32 +141,33 @@ export const argument = (rawTreeNode) => {
140
141
  case 'minecraft:objective_criteria':
141
142
  return wrap(objectiveCriteria);
142
143
  case 'minecraft:operation':
143
- return wrap(core.literal({
144
- pool: OperationArgumentValues,
145
- colorTokenType: 'operator',
146
- }));
144
+ return wrap(core.literal({ pool: OperationArgumentValues, colorTokenType: 'operator' }));
147
145
  case 'minecraft:particle':
148
146
  return wrap(particle);
149
147
  case 'minecraft:resource':
150
148
  case 'minecraft:resource_key':
151
149
  case 'minecraft:resource_or_tag':
150
+ case 'minecraft:resource_or_tag_key':
151
+ const allowTag = treeNode.parser === 'minecraft:resource_or_tag'
152
+ || treeNode.parser === 'minecraft:resource_or_tag_key';
152
153
  return wrap(core.resourceLocation({
153
154
  category: core.ResourceLocation.shorten(treeNode.properties.registry),
154
- allowTag: treeNode.parser === 'minecraft:resource_or_tag',
155
+ allowTag,
155
156
  }));
156
157
  case 'minecraft:resource_location':
157
- return wrap(core.resourceLocation(treeNode.properties ?? {
158
- pool: [],
159
- allowUnknown: true,
160
- }));
158
+ return wrap(core.resourceLocation(treeNode.properties ?? { pool: [], allowUnknown: true }));
161
159
  case 'minecraft:rotation':
162
160
  return wrap(vector({ dimension: 2, noLocal: true }));
163
161
  case 'minecraft:score_holder':
164
- return wrap(scoreHolder(treeNode.properties.amount));
162
+ return wrap(scoreHolder(treeNode.properties.usageType, treeNode.properties.amount));
165
163
  case 'minecraft:scoreboard_slot':
166
164
  // `BELOWNAME` and `sidebar.team.r--.+++e----__d` are also legal slots.
167
165
  // But I do not want to spend time supporting them.
168
- return wrap(core.literal(...ScoreboardSlotArgumentValues));
166
+ return wrap((src, ctx) => {
167
+ return core.literal(...getScoreboardSlotArgumentValues(ctx))(src, ctx);
168
+ });
169
+ case 'minecraft:style':
170
+ return wrap(jsonParser('::java::server::util::text::TextStyle'));
169
171
  case 'minecraft:swizzle':
170
172
  return wrap(core.literal(...SwizzleArgumentValues));
171
173
  case 'minecraft:team':
@@ -185,7 +187,9 @@ export const argument = (rawTreeNode) => {
185
187
  case 'minecraft:vec3':
186
188
  return wrap(vector({ dimension: 3 }));
187
189
  case 'spyglassmc:tag':
188
- return wrap(tag());
190
+ return wrap(tag(core.SymbolUsageType.is(treeNode.properties?.usageType)
191
+ ? treeNode.properties?.usageType
192
+ : undefined));
189
193
  default:
190
194
  // Unknown parser.
191
195
  return undefined;
@@ -207,10 +211,7 @@ function block(isPredicate) {
207
211
  trailingEnd: true,
208
212
  },
209
213
  end: ']',
210
- })), (res) => ({
211
- ...res,
212
- type: 'mcfunction:block/states',
213
- }))),
214
+ })), (res) => ({ ...res, type: 'mcfunction:block/states' }))),
214
215
  core.optional(core.failOnEmpty(nbt.parser.compound)),
215
216
  ]), (res) => {
216
217
  const ans = {
@@ -220,33 +221,21 @@ function block(isPredicate) {
220
221
  id: res.children.find(core.ResourceLocationNode.is),
221
222
  states: res.children.find(BlockStatesNode.is),
222
223
  nbt: res.children.find(nbt.NbtCompoundNode.is),
224
+ isPredicate,
223
225
  };
224
226
  return ans;
225
227
  });
226
228
  }
227
229
  const blockState = block(false);
228
230
  export const blockPredicate = block(true);
229
- export const component = json.parser.entry;
230
231
  function double(min = DoubleMin, max = DoubleMax) {
231
- return core.float({
232
- pattern: FloatPattern,
233
- min,
234
- max,
235
- });
232
+ return core.float({ pattern: FloatPattern, min, max });
236
233
  }
237
234
  function float(min = FloatMin, max = FloatMax) {
238
- return core.float({
239
- pattern: FloatPattern,
240
- min,
241
- max,
242
- });
235
+ return core.float({ pattern: FloatPattern, min, max });
243
236
  }
244
237
  function integer(min = IntegerMin, max = IntegerMax) {
245
- return core.integer({
246
- pattern: IntegerPattern,
247
- min,
248
- max,
249
- });
238
+ return core.integer({ pattern: IntegerPattern, min, max });
250
239
  }
251
240
  function long(min, max) {
252
241
  return core.long({
@@ -277,24 +266,14 @@ function coordinate(integerOnly = false) {
277
266
  return ans;
278
267
  };
279
268
  }
280
- function entity(amount, type) {
281
- return core.map(core.select([
282
- {
283
- predicate: (src) => EntitySelectorAtVariable.is(src.peek(2)),
284
- parser: selector(),
285
- },
286
- {
269
+ export function entity(amount, type) {
270
+ return core.map(core.select([{ predicate: (src) => src.peek() === '@', parser: selector() }, {
287
271
  parser: core.any([
272
+ core.failOnError(uuid),
288
273
  validateLength(core.brigadierString, PlayerNameMaxLength, 'mcfunction.parser.entity-selector.player-name.too-long'),
289
- uuid,
290
274
  ]),
291
- },
292
- ]), (res, _src, ctx) => {
293
- const ans = {
294
- type: 'mcfunction:entity',
295
- range: res.range,
296
- children: [res],
297
- };
275
+ }]), (res, _src, ctx) => {
276
+ const ans = { type: 'mcfunction:entity', range: res.range, children: [res] };
298
277
  if (core.StringNode.is(res)) {
299
278
  ans.playerName = res;
300
279
  }
@@ -307,11 +286,9 @@ function entity(amount, type) {
307
286
  if (amount === 'single' && ans.selector && !ans.selector.single) {
308
287
  ctx.err.report(localize('mcfunction.parser.entity-selector.multiple-disallowed'), ans);
309
288
  }
310
- if (type === 'players' &&
311
- (ans.uuid ||
312
- (ans.selector &&
313
- !ans.selector.playersOnly &&
314
- !ans.selector.currentEntity))) {
289
+ if (type === 'players'
290
+ && (ans.uuid
291
+ || (ans.selector && !ans.selector.playersOnly && !ans.selector.currentEntity))) {
315
292
  ctx.err.report(localize('mcfunction.parser.entity-selector.entities-disallowed'), ans);
316
293
  }
317
294
  return ans;
@@ -320,23 +297,64 @@ function entity(amount, type) {
320
297
  const greedyString = core.string({
321
298
  unquotable: { blockList: new Set(['\n', '\r']) },
322
299
  });
323
- function item(isPredicate) {
300
+ const itemSlot = (src, ctx) => {
301
+ return core.literal(...getItemSlotArgumentValues(ctx))(src, ctx);
302
+ };
303
+ export const itemSlots = (src, ctx) => {
304
+ return core.literal(...getItemSlotsArgumentValues(ctx))(src, ctx);
305
+ };
306
+ const itemStack = (src, ctx) => {
307
+ const oldFormat = shouldUseOldItemStackFormat(ctx);
324
308
  return core.map(core.sequence([
325
- core.resourceLocation({ category: 'item', allowTag: isPredicate }),
326
- core.optional(core.failOnEmpty(nbt.parser.compound)),
309
+ core.resourceLocation({ category: 'item' }),
310
+ oldFormat
311
+ ? core.optional(core.failOnEmpty(nbt.parser.compound))
312
+ : core.optional(core.failOnEmpty(components)),
327
313
  ]), (res) => {
328
314
  const ans = {
329
- type: 'mcfunction:item',
315
+ type: 'mcfunction:item_stack',
330
316
  range: res.range,
331
317
  children: res.children,
332
318
  id: res.children.find(core.ResourceLocationNode.is),
319
+ components: res.children.find(ComponentListNode.is),
333
320
  nbt: res.children.find(nbt.NbtCompoundNode.is),
334
321
  };
335
322
  return ans;
336
- });
323
+ })(src, ctx);
324
+ };
325
+ const itemPredicate = (src, ctx) => {
326
+ const oldFormat = shouldUseOldItemStackFormat(ctx);
327
+ return core.map(core.sequence([
328
+ oldFormat
329
+ ? core.resourceLocation({ category: 'item', allowTag: true })
330
+ : core.any([
331
+ core.resourceLocation({ category: 'item', allowTag: true }),
332
+ core.literal('*'),
333
+ ]),
334
+ oldFormat
335
+ ? core.optional(core.failOnEmpty(nbt.parser.compound))
336
+ : core.optional(componentTests),
337
+ ]), (res) => {
338
+ const ans = {
339
+ type: 'mcfunction:item_predicate',
340
+ range: res.range,
341
+ children: res.children,
342
+ id: (res.children.find(core.ResourceLocationNode.is)
343
+ || res.children.find(core.LiteralNode.is)),
344
+ tests: res.children.find(ComponentTestsNode.is),
345
+ nbt: res.children.find(nbt.NbtCompoundNode.is),
346
+ };
347
+ return ans;
348
+ })(src, ctx);
349
+ };
350
+ export function jsonParser(typeRef) {
351
+ return core.map(json.parser.entry, (res) => ({
352
+ type: 'json:typed',
353
+ range: res.range,
354
+ children: [res],
355
+ targetType: { kind: 'reference', path: typeRef },
356
+ }));
337
357
  }
338
- const itemStack = item(false);
339
- const itemPredicate = item(true);
340
358
  const message = (src, ctx) => {
341
359
  const ans = {
342
360
  type: 'mcfunction:message',
@@ -345,15 +363,47 @@ const message = (src, ctx) => {
345
363
  };
346
364
  while (src.canReadInLine()) {
347
365
  if (EntitySelectorAtVariable.is(src.peek(2))) {
348
- ans.children.push(selector()(src, ctx));
366
+ ans.children.push(selector(true)(src, ctx));
349
367
  }
350
368
  else {
351
- ans.children.push(core.stopBefore(greedyString, ...EntitySelectorAtVariables)(src, ctx));
369
+ ans.children.push(core.stopBefore(greedyString, ...EntitySelectorAtVariable.filterAvailable(ctx))(src, ctx));
352
370
  }
353
371
  }
354
372
  return ans;
355
373
  };
356
- export const particle = (() => {
374
+ function nbtParser(parser, properties) {
375
+ return core.map(parser, (res) => {
376
+ const ans = { type: 'mcfunction:nbt', range: res.range, children: [res], properties };
377
+ return ans;
378
+ });
379
+ }
380
+ function nbtPathParser(parser, properties) {
381
+ return core.map(parser, (res) => {
382
+ const ans = {
383
+ type: 'mcfunction:nbt_path',
384
+ range: res.range,
385
+ children: [res],
386
+ properties,
387
+ };
388
+ return ans;
389
+ });
390
+ }
391
+ export const particle = (src, ctx) => {
392
+ const release = ctx.project['loadedVersion'];
393
+ if (!release || ReleaseVersion.cmp(release, '1.20.5') >= 0) {
394
+ return core.map(sequence([
395
+ core.resourceLocation({ category: 'particle_type' }),
396
+ core.optional(core.failOnEmpty(nbt.parser.compound)),
397
+ ]), (res) => {
398
+ const ans = {
399
+ type: 'mcfunction:particle',
400
+ range: res.range,
401
+ children: res.children,
402
+ id: res.children.find(core.ResourceLocationNode.is),
403
+ };
404
+ return ans;
405
+ })(src, ctx);
406
+ }
357
407
  const sep = core.map(mcf.sep, () => []);
358
408
  const vec = vector({ dimension: 3 });
359
409
  const color = core.map(vec, (res) => ({
@@ -376,14 +426,11 @@ export const particle = (() => {
376
426
  shriek: integer(),
377
427
  vibration: sequence([vec, integer()], sep),
378
428
  };
379
- return core.map(sequence([
380
- core.resourceLocation({ category: 'particle_type' }),
381
- {
429
+ return core.map(sequence([core.resourceLocation({ category: 'particle_type' }), {
382
430
  get: (res) => {
383
431
  return map[core.ResourceLocationNode.toString(res.children[0], 'short')];
384
432
  },
385
- },
386
- ], sep), (res) => {
433
+ }], sep), (res) => {
387
434
  const ans = {
388
435
  type: 'mcfunction:particle',
389
436
  range: res.range,
@@ -391,10 +438,12 @@ export const particle = (() => {
391
438
  id: res.children.find(core.ResourceLocationNode.is),
392
439
  };
393
440
  return ans;
394
- });
395
- })();
441
+ })(src, ctx);
442
+ };
396
443
  function range(type, min, max, cycleable) {
397
- const number = type === 'float' ? float(min, max) : integer(min, max);
444
+ const number = type === 'float'
445
+ ? float(min, max)
446
+ : integer(min, max);
398
447
  const low = core.failOnEmpty(core.stopBefore(number, '..'));
399
448
  const sep = core.failOnEmpty(core.literal({ pool: ['..'], colorTokenType: 'keyword' }));
400
449
  const high = core.failOnEmpty(number);
@@ -409,9 +458,7 @@ function range(type, min, max, cycleable) {
409
458
  : res.children.filter(core.IntegerNode.is);
410
459
  const sepNode = res.children.find(core.LiteralNode.is);
411
460
  const ans = {
412
- type: type === 'float'
413
- ? 'mcfunction:float_range'
414
- : 'mcfunction:int_range',
461
+ type: type === 'float' ? 'mcfunction:float_range' : 'mcfunction:int_range',
415
462
  range: res.range,
416
463
  children: res.children,
417
464
  value: sepNode
@@ -422,19 +469,59 @@ function range(type, min, max, cycleable) {
422
469
  : [undefined, valueNodes[0].value]
423
470
  : [valueNodes[0].value, valueNodes[0].value],
424
471
  };
425
- if (!cycleable &&
426
- ans.value[0] !== undefined &&
427
- ans.value[1] !== undefined &&
428
- ans.value[0] > ans.value[1]) {
472
+ if (!cycleable
473
+ && ans.value[0] !== undefined
474
+ && ans.value[1] !== undefined
475
+ && ans.value[0] > ans.value[1]) {
429
476
  ctx.err.report(localize('mcfunction.parser.range.min>max', ans.value[0], ans.value[1]), res);
430
477
  }
431
478
  return ans;
432
479
  });
433
480
  }
481
+ function resourceOrInline(category) {
482
+ return core.select([{
483
+ predicate: (src) => core.LegalResourceLocationCharacters.has(src.peek()),
484
+ parser: core.resourceLocation({ category }),
485
+ }, {
486
+ parser: core.map(nbt.parser.entry, (res) => {
487
+ const ans = {
488
+ type: 'mcfunction:nbt_resource',
489
+ range: res.range,
490
+ children: [res],
491
+ category,
492
+ };
493
+ return ans;
494
+ }),
495
+ }]);
496
+ }
497
+ function selectorPrefix(ignoreInvalidPrefix) {
498
+ return (src, ctx) => {
499
+ const start = src.cursor;
500
+ let value;
501
+ if (ignoreInvalidPrefix) {
502
+ value = src.peek(2);
503
+ src.skip(2);
504
+ }
505
+ else {
506
+ value = src.readUntil(' ', '\r', '\n', '[');
507
+ }
508
+ const allowedVariables = EntitySelectorAtVariable.filterAvailable(ctx);
509
+ const ans = {
510
+ type: 'literal',
511
+ range: core.Range.create(start, src),
512
+ options: { pool: allowedVariables },
513
+ value,
514
+ };
515
+ if (!allowedVariables.includes(value) && !ignoreInvalidPrefix) {
516
+ ctx.err.report(localize('mcfunction.parser.entity-selector.invalid', ans.value), ans);
517
+ }
518
+ return ans;
519
+ };
520
+ }
434
521
  /**
435
522
  * Failure when not beginning with `@[parse]`
436
523
  */
437
- function selector() {
524
+ export function selector(ignoreInvalidPrefix = false) {
438
525
  let chunkLimited;
439
526
  let currentEntity;
440
527
  let dimensionLimited;
@@ -442,12 +529,7 @@ function selector() {
442
529
  let predicates;
443
530
  let single;
444
531
  let typeLimited;
445
- return core.map(core.sequence([
446
- core.failOnEmpty(core.literal({
447
- pool: EntitySelectorAtVariables,
448
- colorTokenType: 'keyword',
449
- })),
450
- {
532
+ return core.map(core.sequence([core.failOnEmpty(selectorPrefix(ignoreInvalidPrefix)), {
451
533
  get: (res) => {
452
534
  const variable = core.LiteralNode.is(res.children?.[0])
453
535
  ? res.children[0].value
@@ -457,16 +539,11 @@ function selector() {
457
539
  ? variable === '@p' || variable === '@a' || variable === '@r'
458
540
  : undefined;
459
541
  predicates = variable === '@e' ? ['Entity::isAlive'] : undefined;
460
- single = variable
461
- ? variable === '@p' || variable === '@r' || variable === '@s'
462
- : undefined;
542
+ single = variable ? ['@p', '@r', '@s', '@n'].includes(variable) : undefined;
463
543
  typeLimited = playersOnly;
464
544
  function invertable(parser) {
465
545
  return core.map(core.sequence([
466
- core.optional(core.failOnEmpty(core.literal({
467
- pool: ['!'],
468
- colorTokenType: 'keyword',
469
- }))),
546
+ core.optional(core.failOnEmpty(core.literal({ pool: ['!'], colorTokenType: 'keyword' }))),
470
547
  (src) => {
471
548
  src.skipSpace();
472
549
  return undefined;
@@ -490,9 +567,7 @@ function selector() {
490
567
  ...core.BrigadierStringOptions,
491
568
  value: {
492
569
  parser: core.literal({
493
- pool: [
494
- ...EntitySelectorNode.ArgumentKeys,
495
- ],
570
+ pool: [...EntitySelectorNode.ArgumentKeys],
496
571
  colorTokenType: 'property',
497
572
  }),
498
573
  type: 'literal',
@@ -502,8 +577,8 @@ function selector() {
502
577
  value: {
503
578
  get: (record, key) => {
504
579
  const hasKey = (key) => !!record.children.find((p) => p.key?.value === key);
505
- const hasNonInvertedKey = (key) => !!record.children.find((p) => p.key?.value === key &&
506
- !p.value?.inverted);
580
+ const hasNonInvertedKey = (key) => !!record.children.find((p) => p.key?.value === key
581
+ && !p.value?.inverted);
507
582
  switch (key?.value) {
508
583
  case 'advancements':
509
584
  return core.map(core.record({
@@ -513,16 +588,14 @@ function selector() {
513
588
  category: 'advancement',
514
589
  }),
515
590
  sep: '=',
516
- value: core.select([
517
- {
591
+ value: core.select([{
518
592
  predicate: (src) => src.peek() === '{',
519
593
  parser: core.map(core.record({
520
594
  start: '{',
521
595
  pair: {
522
596
  key: unquotedString,
523
597
  sep: '=',
524
- value: core
525
- .boolean,
598
+ value: core.boolean,
526
599
  end: ',',
527
600
  trailingEnd: true,
528
601
  },
@@ -534,11 +607,7 @@ function selector() {
534
607
  };
535
608
  return ans;
536
609
  }),
537
- },
538
- {
539
- parser: core.boolean,
540
- },
541
- ]),
610
+ }, { parser: core.boolean }]),
542
611
  end: ',',
543
612
  trailingEnd: true,
544
613
  },
@@ -557,8 +626,8 @@ function selector() {
557
626
  return core.map(range('float', 0), (res, _, ctx) => {
558
627
  dimensionLimited = true;
559
628
  // x, y, z, dx, dy, dz take precedence over distance, so we use ??= instead of = to ensure it won't override the result.
560
- chunkLimited ??= !playersOnly &&
561
- res.value[1] !== undefined;
629
+ chunkLimited ??= !playersOnly
630
+ && res.value[1] !== undefined;
562
631
  if (hasKey(key.value)) {
563
632
  ctx.err.report(localize('duplicate-key', localeQuote(key.value)), key);
564
633
  }
@@ -566,8 +635,7 @@ function selector() {
566
635
  });
567
636
  case 'gamemode':
568
637
  return core.map(invertable(core.string({
569
- unquotable: core
570
- .BrigadierUnquotableOption,
638
+ unquotable: core.BrigadierUnquotableOption,
571
639
  value: {
572
640
  type: 'literal',
573
641
  parser: core.literal(...GamemodeArgumentValues),
@@ -612,9 +680,7 @@ function selector() {
612
680
  case 'nbt':
613
681
  return invertable(nbt.parser.compound);
614
682
  case 'predicate':
615
- return invertable(core.resourceLocation({
616
- category: 'predicate',
617
- }));
683
+ return invertable(core.resourceLocation({ category: 'predicate' }));
618
684
  case 'scores':
619
685
  return core.map(core.record({
620
686
  start: '{',
@@ -645,8 +711,7 @@ function selector() {
645
711
  });
646
712
  case 'sort':
647
713
  return core.map(core.string({
648
- unquotable: core
649
- .BrigadierUnquotableOption,
714
+ unquotable: core.BrigadierUnquotableOption,
650
715
  value: {
651
716
  type: 'literal',
652
717
  parser: core.literal('arbitrary', 'furthest', 'nearest', 'random'),
@@ -661,23 +726,9 @@ function selector() {
661
726
  return res;
662
727
  });
663
728
  case 'tag':
664
- return invertable(tag([
665
- '[',
666
- '=',
667
- ',',
668
- ']',
669
- '{',
670
- '}',
671
- ]));
729
+ return invertable(tag('reference', ['[', '=', ',', ']', '{', '}']));
672
730
  case 'team':
673
- return core.map(invertable(team('reference', [
674
- '[',
675
- '=',
676
- ',',
677
- ']',
678
- '{',
679
- '}',
680
- ])), (res, _, ctx) => {
731
+ return core.map(invertable(team('reference', ['[', '=', ',', ']', '{', '}'])), (res, _, ctx) => {
681
732
  if (res.inverted
682
733
  ? hasNonInvertedKey(key.value)
683
734
  : hasKey(key.value)) {
@@ -698,11 +749,9 @@ function selector() {
698
749
  ctx.err.report(localize('mcfunction.parser.entity-selector.arguments.not-applicable', localeQuote(key.value)), key);
699
750
  }
700
751
  }
701
- else if (!res.inverted &&
702
- !res.value.isTag) {
752
+ else if (!res.inverted && !res.value.isTag) {
703
753
  typeLimited = true;
704
- if (core.ResourceLocationNode
705
- .toString(res.value, 'short') === 'player') {
754
+ if (core.ResourceLocationNode.toString(res.value, 'short') === 'player') {
706
755
  playersOnly = true;
707
756
  }
708
757
  }
@@ -761,15 +810,12 @@ function selector() {
761
810
  return ans;
762
811
  }));
763
812
  },
764
- },
765
- ]), (res) => {
813
+ }]), (res) => {
766
814
  const ans = {
767
815
  type: 'mcfunction:entity_selector',
768
816
  range: res.range,
769
817
  children: res.children,
770
- variable: res.children
771
- .find(core.LiteralNode.is)
772
- .value.slice(1),
818
+ variable: res.children.find(core.LiteralNode.is).value.slice(1),
773
819
  arguments: res.children.find(EntitySelectorArgumentsNode.is),
774
820
  chunkLimited,
775
821
  currentEntity,
@@ -799,17 +845,12 @@ function getEntitySelectorHover(node) {
799
845
  - \`currentEntity\`: \`${node.currentEntity}\``;
800
846
  }
801
847
  else {
802
- const amountOfTrue = [
803
- node.chunkLimited,
804
- node.dimensionLimited,
805
- node.playersOnly,
806
- node.typeLimited,
807
- ].filter((v) => v).length;
848
+ const amountOfTrue = [node.chunkLimited, node.dimensionLimited, node.playersOnly, node.typeLimited].filter((v) => v).length;
808
849
  ans = `**Performance**: ${grades.get(amountOfTrue)}
809
850
  - \`chunkLimited\`: \`${!!node.chunkLimited}\`
810
851
  - \`dimensionLimited\`: \`${!!node.dimensionLimited}\`
811
852
  - \`playersOnly\`: \`${!!node.playersOnly}\`
812
- - \`typeLimited\`: \`${!!node.chunkLimited}\``;
853
+ - \`typeLimited\`: \`${!!node.typeLimited}\``;
813
854
  }
814
855
  if (node.predicates?.length) {
815
856
  ans += `
@@ -820,17 +861,13 @@ ${node.predicates.map((p) => `- \`${p}\``).join('\n')}`;
820
861
  }
821
862
  return ans;
822
863
  }
823
- export const scoreHolderFakeName = validateLength(symbol('score_holder'), FakeNameMaxLength, 'mcfunction.parser.score_holder.fake-name.too-long');
824
- function scoreHolder(amount) {
825
- return core.map(core.select([
826
- {
827
- predicate: (src) => EntitySelectorAtVariable.is(src.peek(2)),
828
- parser: selector(),
829
- },
830
- {
831
- parser: scoreHolderFakeName,
832
- },
833
- ]), (res, _src, ctx) => {
864
+ export function scoreHolderFakeName(usageType) {
865
+ return validateLength(symbol({ category: 'score_holder', usageType }), FakeNameMaxLength, 'mcfunction.parser.score_holder.fake-name.too-long');
866
+ }
867
+ export function scoreHolder(usageType, amount) {
868
+ return core.map(core.select([{ predicate: (src) => src.peek() === '@', parser: selector() }, {
869
+ parser: scoreHolderFakeName(usageType),
870
+ }]), (res, _src, ctx) => {
834
871
  const ans = {
835
872
  type: 'mcfunction:score_holder',
836
873
  range: res.range,
@@ -851,43 +888,28 @@ function scoreHolder(amount) {
851
888
  function symbol(options, terminators = []) {
852
889
  return core.stopBefore(core.symbol(options), core.Whitespaces, terminators);
853
890
  }
854
- function objective(usageType, terminators = []) {
891
+ export function objective(usageType, terminators = []) {
855
892
  return validateLength(unquotableSymbol({ category: 'objective', usageType }, terminators), ObjectiveMaxLength, 'mcfunction.parser.objective.too-long');
856
893
  }
857
- const objectiveCriteria = core
858
- .map(core.any([
894
+ const objectiveCriteria = core.map(core.any([
859
895
  core.sequence([
860
- core.stopBefore(core.resourceLocation({
861
- category: 'stat_type',
862
- namespacePathSep: '.',
863
- }), ':'),
896
+ core.stopBefore(core.resourceLocation({ category: 'stat_type', namespacePathSep: '.' }), ':'),
864
897
  core.failOnEmpty(core.literal(':')),
865
898
  {
866
899
  get: (res) => {
867
900
  if (core.ResourceLocationNode.is(res.children[0])) {
868
- const category = ObjectiveCriteriaNode.ComplexCategories
869
- .get(core.ResourceLocationNode.toString(res.children[0], 'short'));
901
+ const category = ObjectiveCriteriaNode.ComplexCategories.get(core.ResourceLocationNode.toString(res.children[0], 'short'));
870
902
  if (category) {
871
- return core.resourceLocation({
872
- category,
873
- namespacePathSep: '.',
874
- });
903
+ return core.resourceLocation({ category, namespacePathSep: '.' });
875
904
  }
876
905
  }
877
- return core.resourceLocation({
878
- pool: [],
879
- allowUnknown: true,
880
- namespacePathSep: '.',
881
- });
906
+ return core.resourceLocation({ pool: [], allowUnknown: true, namespacePathSep: '.' });
882
907
  },
883
908
  },
884
909
  ]),
885
910
  core.literal(...ObjectiveCriteriaNode.SimpleValues),
886
911
  ]), (res) => {
887
- const ans = {
888
- type: 'mcfunction:objective_criteria',
889
- range: res.range,
890
- };
912
+ const ans = { type: 'mcfunction:objective_criteria', range: res.range };
891
913
  if (core.LiteralNode.is(res)) {
892
914
  ans.simpleValue = res.value;
893
915
  }
@@ -896,8 +918,8 @@ const objectiveCriteria = core
896
918
  }
897
919
  return ans;
898
920
  });
899
- export function tag(terminators = []) {
900
- return unquotableSymbol('tag', terminators);
921
+ export function tag(usageType, terminators = []) {
922
+ return unquotableSymbol({ category: 'tag', usageType }, terminators);
901
923
  }
902
924
  export function team(usageType, terminators = []) {
903
925
  return unquotableSymbol({ category: 'team', usageType }, terminators);
@@ -924,12 +946,8 @@ const unquotedString = core.string({
924
946
  unquotable: core.BrigadierUnquotableOption,
925
947
  });
926
948
  const UuidPattern = /^[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+$/i;
927
- const uuid = (src, ctx) => {
928
- const ans = {
929
- type: 'mcfunction:uuid',
930
- range: core.Range.create(src),
931
- bits: [0n, 0n],
932
- };
949
+ export const uuid = (src, ctx) => {
950
+ const ans = { type: 'mcfunction:uuid', range: core.Range.create(src), bits: [0n, 0n] };
933
951
  const raw = src.readUntil(' ', '\r', '\n', '\r');
934
952
  /**
935
953
  * According to the implementation of Minecraft's UUID parser and Java's `UUID#fromString` method,
@@ -999,8 +1017,7 @@ function vector(options) {
999
1017
  ? coordinate(options.integersOnly)(src, ctx)
1000
1018
  : coordinate(options.integersOnly)(src, ctx);
1001
1019
  ans.children.push(coord);
1002
- if ((ans.system === 1 /* CoordinateSystem.Local */) !==
1003
- (coord.notation === '^')) {
1020
+ if ((ans.system === 1 /* CoordinateSystem.Local */) !== (coord.notation === '^')) {
1004
1021
  ctx.err.report(localize('mcfunction.parser.vector.mixed'), coord);
1005
1022
  }
1006
1023
  }
@@ -1011,4 +1028,155 @@ function vector(options) {
1011
1028
  return ans;
1012
1029
  };
1013
1030
  }
1031
+ const components = core.map(core.record({
1032
+ start: '[',
1033
+ pair: {
1034
+ key: core.resourceLocation({ category: 'data_component_type' }),
1035
+ sep: '=',
1036
+ value: nbt.parser.entry,
1037
+ end: ',',
1038
+ trailingEnd: true,
1039
+ },
1040
+ end: ']',
1041
+ }), (res) => {
1042
+ const ans = {
1043
+ type: 'mcfunction:component_list',
1044
+ range: res.range,
1045
+ children: res.children,
1046
+ };
1047
+ return ans;
1048
+ });
1049
+ const componentTest = (src, ctx) => {
1050
+ const start = src.cursor;
1051
+ src.skipWhitespace();
1052
+ const negated = src.trySkip('!');
1053
+ src.skipWhitespace();
1054
+ const key = core.resourceLocation({ category: 'data_component_type' })(src, ctx);
1055
+ src.skipWhitespace();
1056
+ if (core.ResourceLocationNode.toString(key, 'full') === 'minecraft:count') {
1057
+ key.options.category = undefined;
1058
+ key.options.pool = ['minecraft:count'];
1059
+ }
1060
+ if (src.trySkip('=')) {
1061
+ const ans = {
1062
+ type: 'mcfunction:component_test_exact',
1063
+ range: core.Range.create(start, src),
1064
+ children: [key],
1065
+ key,
1066
+ negated,
1067
+ };
1068
+ const value = nbt.parser.entry(src, ctx);
1069
+ if (value == core.Failure) {
1070
+ ctx.err.report(localize('expected', localize('nbt.node')), src);
1071
+ src.skipUntilOrEnd(',', '|', ']');
1072
+ }
1073
+ else {
1074
+ ans.children.push(value);
1075
+ ans.value = value;
1076
+ }
1077
+ src.skipWhitespace();
1078
+ ans.range.end = src.cursor;
1079
+ return ans;
1080
+ }
1081
+ if (src.trySkip('~')) {
1082
+ if (key.options.category !== undefined) {
1083
+ key.options.category = 'item_sub_predicate_type';
1084
+ }
1085
+ const ans = {
1086
+ type: 'mcfunction:component_test_sub_predicate',
1087
+ range: core.Range.create(start, src),
1088
+ children: [key],
1089
+ key,
1090
+ negated,
1091
+ };
1092
+ const predicate = nbt.parser.entry(src, ctx);
1093
+ if (predicate == core.Failure) {
1094
+ ctx.err.report(localize('expected', localize('nbt.node')), src);
1095
+ src.skipUntilOrEnd(',', '|', ']');
1096
+ }
1097
+ else {
1098
+ ans.children.push(predicate);
1099
+ ans.value = predicate;
1100
+ }
1101
+ src.skipWhitespace();
1102
+ ans.range.end = src.cursor;
1103
+ return ans;
1104
+ }
1105
+ const ans = {
1106
+ type: 'mcfunction:component_test_exists',
1107
+ range: core.Range.create(start, src),
1108
+ children: [key],
1109
+ key,
1110
+ negated,
1111
+ };
1112
+ return ans;
1113
+ };
1114
+ const componentTestsAllOf = (src, ctx) => {
1115
+ const ans = {
1116
+ type: 'mcfunction:component_tests_all_of',
1117
+ range: core.Range.create(src),
1118
+ children: [],
1119
+ };
1120
+ while (src.canRead()) {
1121
+ src.skipWhitespace();
1122
+ const testNode = componentTest(src, ctx);
1123
+ ans.children.push(testNode);
1124
+ src.skipWhitespace();
1125
+ if (src.peek() === ',') {
1126
+ src.skip();
1127
+ }
1128
+ else if (src.peek() === '|' || src.peek() === ']') {
1129
+ break;
1130
+ }
1131
+ else {
1132
+ ctx.err.report(localize('expected', localeQuote(']')), src);
1133
+ src.skipUntilOrEnd(',', '|', ']');
1134
+ }
1135
+ }
1136
+ ans.range.end = src.cursor;
1137
+ return ans;
1138
+ };
1139
+ const componentTestsAnyOf = (src, ctx) => {
1140
+ const ans = {
1141
+ type: 'mcfunction:component_tests_any_of',
1142
+ range: core.Range.create(src),
1143
+ children: [],
1144
+ };
1145
+ while (src.canRead()) {
1146
+ src.skipWhitespace();
1147
+ const allOfNode = componentTestsAllOf(src, ctx);
1148
+ ans.children.push(allOfNode);
1149
+ src.skipWhitespace();
1150
+ if (src.peek() === '|') {
1151
+ src.skip();
1152
+ }
1153
+ else if (src.peek() === ']') {
1154
+ break;
1155
+ }
1156
+ else {
1157
+ ctx.err.report(localize('expected', localeQuote(']')), src);
1158
+ src.skipUntilOrEnd('|', ']');
1159
+ }
1160
+ }
1161
+ ans.range.end = src.cursor;
1162
+ return ans;
1163
+ };
1164
+ const componentTests = (src, ctx) => {
1165
+ const ans = {
1166
+ type: 'mcfunction:component_tests',
1167
+ range: core.Range.create(src),
1168
+ };
1169
+ if (!src.trySkip('[')) {
1170
+ return core.Failure;
1171
+ }
1172
+ src.skipWhitespace();
1173
+ const tests = core.optional(core.failOnEmpty(componentTestsAnyOf))(src, ctx);
1174
+ if (tests) {
1175
+ ans.children = [tests];
1176
+ }
1177
+ src.skipWhitespace();
1178
+ core.literal(']')(src, ctx);
1179
+ ans.range.end = src.cursor;
1180
+ return ans;
1181
+ };
1014
1182
  //# sourceMappingURL=argument.js.map