@spyglassmc/java-edition 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +36 -0
  2. package/lib/binder/index.d.ts +15 -0
  3. package/lib/binder/index.js +102 -0
  4. package/lib/common/index.d.ts +7 -0
  5. package/lib/common/index.js +60 -0
  6. package/lib/dependency/common.d.ts +26 -0
  7. package/lib/dependency/common.js +39 -0
  8. package/lib/dependency/index.d.ts +30 -0
  9. package/lib/dependency/index.js +172 -0
  10. package/lib/dependency/mcmeta.d.ts +79 -0
  11. package/lib/dependency/mcmeta.js +205 -0
  12. package/lib/index.d.ts +6 -0
  13. package/lib/index.js +76 -0
  14. package/lib/json/checker/data/advancement.d.ts +14 -0
  15. package/lib/json/checker/data/advancement.js +450 -0
  16. package/lib/json/checker/data/biome.d.ts +4 -0
  17. package/lib/json/checker/data/biome.js +151 -0
  18. package/lib/json/checker/data/common.d.ts +22 -0
  19. package/lib/json/checker/data/common.js +286 -0
  20. package/lib/json/checker/data/dimension.d.ts +4 -0
  21. package/lib/json/checker/data/dimension.js +238 -0
  22. package/lib/json/checker/data/feature.d.ts +9 -0
  23. package/lib/json/checker/data/feature.js +733 -0
  24. package/lib/json/checker/data/index.d.ts +4 -0
  25. package/lib/json/checker/data/index.js +43 -0
  26. package/lib/json/checker/data/loot_table.d.ts +8 -0
  27. package/lib/json/checker/data/loot_table.js +279 -0
  28. package/lib/json/checker/data/recipe.d.ts +2 -0
  29. package/lib/json/checker/data/recipe.js +53 -0
  30. package/lib/json/checker/data/structure.d.ts +8 -0
  31. package/lib/json/checker/data/structure.js +148 -0
  32. package/lib/json/checker/data/tag.d.ts +7 -0
  33. package/lib/json/checker/data/tag.js +38 -0
  34. package/lib/json/checker/data/text_component.d.ts +2 -0
  35. package/lib/json/checker/data/text_component.js +142 -0
  36. package/lib/json/checker/index.d.ts +5 -0
  37. package/lib/json/checker/index.js +28 -0
  38. package/lib/json/checker/util/advancement.d.ts +3 -0
  39. package/lib/json/checker/util/advancement.js +20 -0
  40. package/lib/json/checker/util/block_states.d.ts +13 -0
  41. package/lib/json/checker/util/block_states.js +85 -0
  42. package/lib/json/checker/util/color.d.ts +4 -0
  43. package/lib/json/checker/util/color.js +64 -0
  44. package/lib/json/checker/util/index.d.ts +8 -0
  45. package/lib/json/checker/util/index.js +20 -0
  46. package/lib/json/checker/util/nbt.d.ts +17 -0
  47. package/lib/json/checker/util/nbt.js +71 -0
  48. package/lib/json/checker/util/recipe.d.ts +6 -0
  49. package/lib/json/checker/util/recipe.js +16 -0
  50. package/lib/json/checker/util/uuid.d.ts +2 -0
  51. package/lib/json/checker/util/uuid.js +12 -0
  52. package/lib/json/checker/util/version.d.ts +46 -0
  53. package/lib/json/checker/util/version.js +54 -0
  54. package/lib/json/index.d.ts +4 -0
  55. package/lib/json/index.js +32 -0
  56. package/lib/mcfunction/checker/index.d.ts +7 -0
  57. package/lib/mcfunction/checker/index.js +217 -0
  58. package/lib/mcfunction/colorizer/index.d.ts +6 -0
  59. package/lib/mcfunction/colorizer/index.js +38 -0
  60. package/lib/mcfunction/common/index.d.ts +7 -0
  61. package/lib/mcfunction/common/index.js +47 -0
  62. package/lib/mcfunction/completer/argument.d.ts +5 -0
  63. package/lib/mcfunction/completer/argument.js +292 -0
  64. package/lib/mcfunction/completer/index.d.ts +2 -0
  65. package/lib/mcfunction/completer/index.js +14 -0
  66. package/lib/mcfunction/index.d.ts +8 -0
  67. package/lib/mcfunction/index.js +72 -0
  68. package/lib/mcfunction/inlayHintProvider.d.ts +4 -0
  69. package/lib/mcfunction/inlayHintProvider.js +40 -0
  70. package/lib/mcfunction/node/argument.d.ts +187 -0
  71. package/lib/mcfunction/node/argument.js +281 -0
  72. package/lib/mcfunction/node/index.d.ts +2 -0
  73. package/lib/mcfunction/node/index.js +14 -0
  74. package/lib/mcfunction/parser/argument.d.ts +15 -0
  75. package/lib/mcfunction/parser/argument.js +934 -0
  76. package/lib/mcfunction/parser/index.d.ts +2 -0
  77. package/lib/mcfunction/parser/index.js +14 -0
  78. package/lib/mcfunction/signatureHelpProvider.d.ts +8 -0
  79. package/lib/mcfunction/signatureHelpProvider.js +103 -0
  80. package/lib/mcfunction/tree/1.15.d.ts +9 -0
  81. package/lib/mcfunction/tree/1.15.js +542 -0
  82. package/lib/mcfunction/tree/1.16.d.ts +10 -0
  83. package/lib/mcfunction/tree/1.16.js +77 -0
  84. package/lib/mcfunction/tree/1.17.d.ts +12 -0
  85. package/lib/mcfunction/tree/1.17.js +166 -0
  86. package/lib/mcfunction/tree/1.18.d.ts +26 -0
  87. package/lib/mcfunction/tree/1.18.js +6 -0
  88. package/lib/mcfunction/tree/1.19.d.ts +26 -0
  89. package/lib/mcfunction/tree/1.19.js +6 -0
  90. package/lib/mcfunction/tree/argument.d.ts +179 -0
  91. package/lib/mcfunction/tree/argument.js +3 -0
  92. package/lib/mcfunction/tree/index.d.ts +7 -0
  93. package/lib/mcfunction/tree/index.js +19 -0
  94. package/package.json +41 -0
@@ -0,0 +1,934 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.team = exports.tag = exports.scoreHolderFakeName = exports.component = exports.blockPredicate = exports.argument = void 0;
23
+ const core = __importStar(require("@spyglassmc/core"));
24
+ const core_1 = require("@spyglassmc/core");
25
+ const json = __importStar(require("@spyglassmc/json"));
26
+ const locales_1 = require("@spyglassmc/locales");
27
+ const mcf = __importStar(require("@spyglassmc/mcfunction"));
28
+ const nbt = __importStar(require("@spyglassmc/nbt"));
29
+ const dependency_1 = require("../../dependency");
30
+ const common_1 = require("../common");
31
+ const node_1 = require("../node");
32
+ const IntegerPattern = /^-?\d+$/;
33
+ /**
34
+ * A combination of:
35
+ * - https://github.com/Mojang/brigadier/blob/cf754c4ef654160dca946889c11941634c5db3d5/src/main/java/com/mojang/brigadier/StringReader.java#L137
36
+ * - https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#valueOf(java.lang.String)
37
+ *
38
+ * i.e. Only `[0-9\.\-]` is allowed in the number, and its format must follow The Java™ Language Specification.
39
+ *
40
+ * i.e.
41
+ * ```
42
+ * [NegativeSign] Digits [`.`] [Digits] |
43
+ * [NegativeSign] `.` Digits
44
+ * ```
45
+ */
46
+ const FloatPattern = /^-?(?:\d+\.?\d*|\.\d+)$/;
47
+ const DoubleMax = Number.MAX_VALUE;
48
+ const DoubleMin = -DoubleMax;
49
+ const FloatMax = (2 - (2 ** -23)) * (2 ** 127);
50
+ const FloatMin = -FloatMax;
51
+ const IntegerMax = 2 ** 31 - 1;
52
+ const IntegerMin = -(2 ** 31);
53
+ const LongMax = 9223372036854775807n;
54
+ const LongMin = -9223372036854775808n;
55
+ const FakeNameMaxLength = 40;
56
+ const ObjectiveMaxLength = 16;
57
+ const PlayerNameMaxLength = 16;
58
+ function shouldValidateLength(ctx) {
59
+ const major = ctx.project['loadedVersion'];
60
+ return !major || dependency_1.MajorVersion.cmp(major, '1.18') < 0;
61
+ }
62
+ /**
63
+ * @returns The parser for the specified argument tree node. All argument parsers used in the `mcfunction` package
64
+ * fail on empty input.
65
+ */
66
+ const argument = (rawTreeNode) => {
67
+ const treeNode = rawTreeNode;
68
+ const wrap = (parser) => core.failOnEmpty(core.stopBefore(parser, '\r', '\n'));
69
+ switch (treeNode.parser) {
70
+ case 'brigadier:bool':
71
+ return wrap(core.boolean);
72
+ case 'brigadier:double':
73
+ return wrap(double(treeNode.properties?.min, treeNode.properties?.max));
74
+ case 'brigadier:float':
75
+ return wrap(float(treeNode.properties?.min, treeNode.properties?.max));
76
+ case 'brigadier:integer':
77
+ return wrap(integer(treeNode.properties?.min, treeNode.properties?.max));
78
+ case 'brigadier:long':
79
+ return wrap(long(treeNode.properties?.min, treeNode.properties?.max));
80
+ case 'brigadier:string':
81
+ switch (treeNode.properties.type) {
82
+ case 'word':
83
+ return wrap(unquotedString);
84
+ case 'phrase':
85
+ return wrap(core.brigadierString);
86
+ case 'greedy':
87
+ default:
88
+ return wrap(greedyString);
89
+ }
90
+ case 'minecraft:angle':
91
+ return wrap(core.validate(coordinate(), res => res.notation !== '^', (0, locales_1.localize)('mcfunction.parser.vector.local-disallowed')));
92
+ case 'minecraft:block_pos':
93
+ return wrap(vector({ dimension: 3, integersOnly: true }));
94
+ case 'minecraft:block_predicate':
95
+ return wrap(exports.blockPredicate);
96
+ case 'minecraft:block_state':
97
+ return wrap(blockState);
98
+ case 'minecraft:color':
99
+ return wrap(core.map(core.literal(...common_1.ColorArgumentValues), res => ({
100
+ ...res,
101
+ color: core.Color.NamedColors.has(res.value)
102
+ ? core.Color.fromCompositeInt(core.Color.NamedColors.get(res.value))
103
+ : undefined,
104
+ })));
105
+ case 'minecraft:column_pos':
106
+ return wrap(vector({ dimension: 2, integersOnly: true }));
107
+ case 'minecraft:component':
108
+ return wrap(exports.component);
109
+ case 'minecraft:dimension':
110
+ return wrap(core.resourceLocation({
111
+ category: 'dimension',
112
+ }));
113
+ case 'minecraft:entity':
114
+ return wrap(entity(treeNode.properties.amount, treeNode.properties.type));
115
+ case 'minecraft:entity_anchor':
116
+ return wrap(core.literal(...common_1.EntityAnchorArgumentValues));
117
+ case 'minecraft:entity_summon':
118
+ return wrap(core.resourceLocation({
119
+ category: 'entity_type',
120
+ }));
121
+ case 'minecraft:float_range':
122
+ return wrap(range('float'));
123
+ case 'minecraft:function':
124
+ return wrap(core.resourceLocation({
125
+ category: 'function',
126
+ allowTag: true,
127
+ }));
128
+ case 'minecraft:game_profile':
129
+ return wrap(entity('multiple', 'players'));
130
+ case 'minecraft:int_range':
131
+ return wrap(range('integer'));
132
+ case 'minecraft:item_enchantment':
133
+ return wrap(core.resourceLocation({
134
+ category: 'enchantment',
135
+ }));
136
+ case 'minecraft:item_predicate':
137
+ return wrap(itemPredicate);
138
+ case 'minecraft:item_slot':
139
+ return wrap(core.literal(...common_1.ItemSlotArgumentValues));
140
+ case 'minecraft:item_stack':
141
+ return wrap(itemStack);
142
+ case 'minecraft:message':
143
+ return wrap(message);
144
+ case 'minecraft:mob_effect':
145
+ return wrap(core.resourceLocation({
146
+ category: 'mob_effect',
147
+ }));
148
+ case 'minecraft:nbt_compound_tag':
149
+ return wrap(nbt.parser.compound);
150
+ case 'minecraft:nbt_path':
151
+ return wrap(nbt.parser.path);
152
+ case 'minecraft:nbt_tag':
153
+ return wrap(nbt.parser.entry);
154
+ case 'minecraft:objective':
155
+ return wrap(objective(core.SymbolUsageType.is(treeNode.properties?.usageType)
156
+ ? treeNode.properties?.usageType
157
+ : undefined));
158
+ case 'minecraft:objective_criteria':
159
+ return wrap(objectiveCriteria);
160
+ case 'minecraft:operation':
161
+ return wrap(core.literal({
162
+ pool: common_1.OperationArgumentValues,
163
+ colorTokenType: 'operator',
164
+ }));
165
+ case 'minecraft:particle':
166
+ return wrap(particle);
167
+ case 'minecraft:resource':
168
+ case 'minecraft:resource_or_tag':
169
+ return wrap(core.resourceLocation({
170
+ category: core.ResourceLocation.shorten(treeNode.properties.registry),
171
+ allowTag: treeNode.parser === 'minecraft:resource_or_tag',
172
+ }));
173
+ case 'minecraft:resource_location':
174
+ return wrap(core.resourceLocation(treeNode.properties ?? {
175
+ pool: [],
176
+ allowUnknown: true,
177
+ }));
178
+ case 'minecraft:rotation':
179
+ return wrap(vector({ dimension: 2, noLocal: true }));
180
+ case 'minecraft:score_holder':
181
+ return wrap(scoreHolder(treeNode.properties.amount));
182
+ case 'minecraft:scoreboard_slot':
183
+ // `BELOWNAME` and `sidebar.team.r--.+++e----__d` are also legal slots.
184
+ // But I do not want to spend time supporting them.
185
+ return wrap(core.literal(...common_1.ScoreboardSlotArgumentValues));
186
+ case 'minecraft:swizzle':
187
+ return wrap(core.literal(...common_1.SwizzleArgumentValues));
188
+ case 'minecraft:team':
189
+ return wrap(team(core.SymbolUsageType.is(treeNode.properties?.usageType)
190
+ ? treeNode.properties?.usageType
191
+ : undefined));
192
+ case 'minecraft:time':
193
+ return wrap(time);
194
+ case 'minecraft:uuid':
195
+ return wrap(uuid);
196
+ case 'minecraft:vec2':
197
+ return wrap(vector({ dimension: 2, noLocal: true }));
198
+ case 'minecraft:vec3':
199
+ return wrap(vector({ dimension: 3 }));
200
+ case 'spyglassmc:tag':
201
+ return wrap(tag());
202
+ default:
203
+ // Unknown parser.
204
+ return undefined;
205
+ }
206
+ };
207
+ exports.argument = argument;
208
+ function block(isPredicate) {
209
+ return core.map(core.sequence([
210
+ core.resourceLocation({ category: 'block', allowTag: isPredicate }),
211
+ core.optional(core.map(core.failOnEmpty(core.record({
212
+ start: '[',
213
+ pair: {
214
+ key: core.string({
215
+ ...core.BrigadierStringOptions,
216
+ colorTokenType: 'property',
217
+ }),
218
+ sep: '=',
219
+ value: core.brigadierString,
220
+ end: ',',
221
+ trailingEnd: true,
222
+ },
223
+ end: ']',
224
+ })), res => ({
225
+ ...res,
226
+ type: 'mcfunction:block/states',
227
+ }))),
228
+ core.optional(core.failOnEmpty(nbt.parser.compound)),
229
+ ]), res => {
230
+ const ans = {
231
+ type: 'mcfunction:block',
232
+ range: res.range,
233
+ children: res.children,
234
+ id: res.children.find(core.ResourceLocationNode.is),
235
+ states: res.children.find(node_1.BlockStatesNode.is),
236
+ nbt: res.children.find(nbt.NbtCompoundNode.is),
237
+ };
238
+ return ans;
239
+ });
240
+ }
241
+ const blockState = block(false);
242
+ exports.blockPredicate = block(true);
243
+ exports.component = json.parser.json();
244
+ function double(min = DoubleMin, max = DoubleMax) {
245
+ return core.float({
246
+ pattern: FloatPattern,
247
+ min,
248
+ max,
249
+ });
250
+ }
251
+ function float(min = FloatMin, max = FloatMax) {
252
+ return core.float({
253
+ pattern: FloatPattern,
254
+ min,
255
+ max,
256
+ });
257
+ }
258
+ function integer(min = IntegerMin, max = IntegerMax) {
259
+ return core.integer({
260
+ pattern: IntegerPattern,
261
+ min,
262
+ max,
263
+ });
264
+ }
265
+ function long(min, max) {
266
+ return core.long({
267
+ pattern: IntegerPattern,
268
+ min: BigInt(min ?? LongMin),
269
+ max: BigInt(max ?? LongMax),
270
+ });
271
+ }
272
+ function coordinate(integerOnly = false) {
273
+ return (src, ctx) => {
274
+ const ans = {
275
+ type: 'mcfunction:coordinate',
276
+ notation: '',
277
+ range: core.Range.create(src),
278
+ value: 0,
279
+ };
280
+ if (src.trySkip('^')) {
281
+ ans.notation = '^';
282
+ }
283
+ else if (src.trySkip('~')) {
284
+ ans.notation = '~';
285
+ }
286
+ if ((src.canReadInLine() && src.peek() !== ' ') || ans.notation === '') {
287
+ const result = (integerOnly && ans.notation === '' ? integer : double)()(src, ctx);
288
+ ans.value = Number(result.value);
289
+ }
290
+ ans.range.end = src.cursor;
291
+ return ans;
292
+ };
293
+ }
294
+ function entity(amount, type) {
295
+ return core.map(core.select([
296
+ {
297
+ predicate: src => node_1.EntitySelectorAtVariable.is(src.peek(2)),
298
+ parser: selector(),
299
+ },
300
+ {
301
+ parser: core.any([
302
+ validateLength(core.brigadierString, PlayerNameMaxLength, 'mcfunction.parser.entity-selector.player-name.too-long'),
303
+ uuid,
304
+ ]),
305
+ },
306
+ ]), (res, _src, ctx) => {
307
+ const ans = {
308
+ type: 'mcfunction:entity',
309
+ range: res.range,
310
+ children: [res],
311
+ };
312
+ if (core.StringNode.is(res)) {
313
+ ans.playerName = res;
314
+ }
315
+ else if (node_1.EntitySelectorNode.is(res)) {
316
+ ans.selector = res;
317
+ }
318
+ else {
319
+ ans.uuid = res;
320
+ }
321
+ if (amount === 'single' && ans.selector && !ans.selector.single) {
322
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.multiple-disallowed'), ans);
323
+ }
324
+ if (type === 'players' && (ans.uuid || (ans.selector && !ans.selector.playersOnly && !ans.selector.currentEntity))) {
325
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.entities-disallowed'), ans);
326
+ }
327
+ return ans;
328
+ });
329
+ }
330
+ const greedyString = core.string({
331
+ unquotable: { blockList: new Set(['\n', '\r']) },
332
+ });
333
+ function item(isPredicate) {
334
+ return core.map(core.sequence([
335
+ core.resourceLocation({ category: 'item', allowTag: isPredicate }),
336
+ core.optional(core.failOnEmpty(nbt.parser.compound)),
337
+ ]), res => {
338
+ const ans = {
339
+ type: 'mcfunction:item',
340
+ range: res.range,
341
+ children: res.children,
342
+ id: res.children.find(core.ResourceLocationNode.is),
343
+ nbt: res.children.find(nbt.NbtCompoundNode.is),
344
+ };
345
+ return ans;
346
+ });
347
+ }
348
+ const itemStack = item(false);
349
+ const itemPredicate = item(true);
350
+ const message = (src, ctx) => {
351
+ const ans = {
352
+ type: 'mcfunction:message',
353
+ range: core.Range.create(src),
354
+ children: [],
355
+ };
356
+ while (src.canReadInLine()) {
357
+ if (node_1.EntitySelectorAtVariable.is(src.peek(2))) {
358
+ ans.children.push(selector()(src, ctx));
359
+ }
360
+ else {
361
+ ans.children.push(core.stopBefore(greedyString, ...node_1.EntitySelectorAtVariables)(src, ctx));
362
+ }
363
+ }
364
+ return ans;
365
+ };
366
+ const particle = (() => {
367
+ const sep = core.map(mcf.sep, () => []);
368
+ const vec = vector({ dimension: 3 });
369
+ const color = core.map(vec, res => ({
370
+ ...res,
371
+ color: res.children.length === 3
372
+ ? {
373
+ value: core.Color.fromDecRGB(res.children[0].value, res.children[1].value, res.children[2].value),
374
+ format: [core.ColorFormat.DecRGB],
375
+ }
376
+ : undefined,
377
+ }));
378
+ const map = {
379
+ block: blockState,
380
+ block_marker: blockState,
381
+ dust: (0, core_1.sequence)([color, float()], sep),
382
+ dust_color_transition: (0, core_1.sequence)([color, float(), color], sep),
383
+ falling_dust: blockState,
384
+ item: itemStack,
385
+ sculk_charge: float(),
386
+ vibration: (0, core_1.sequence)([vec, vec, integer()], sep),
387
+ };
388
+ return core.map((0, core_1.sequence)([
389
+ core.resourceLocation({ category: 'particle_type' }),
390
+ {
391
+ get: res => {
392
+ return map[core.ResourceLocationNode.toString(res.children[0], 'short')];
393
+ },
394
+ },
395
+ ], sep), res => {
396
+ const ans = {
397
+ type: 'mcfunction:particle',
398
+ range: res.range,
399
+ children: res.children,
400
+ id: res.children.find(core.ResourceLocationNode.is),
401
+ };
402
+ return ans;
403
+ });
404
+ })();
405
+ function range(type, min, max, cycleable) {
406
+ const number = type === 'float' ? float(min, max) : integer(min, max);
407
+ const low = core.failOnEmpty(core.stopBefore(number, '..'));
408
+ const sep = core.failOnEmpty(core.literal({ pool: ['..'], colorTokenType: 'keyword' }));
409
+ const high = core.failOnEmpty(number);
410
+ return core.map(core.any([
411
+ /* exactly */ core.sequence([low]),
412
+ /* atLeast */ core.sequence([low, sep]),
413
+ /* atMost */ core.sequence([sep, high]),
414
+ /* between */ core.sequence([low, sep, high]),
415
+ ]), (res, _src, ctx) => {
416
+ const valueNodes = type === 'float'
417
+ ? res.children.filter(core.FloatNode.is)
418
+ : res.children.filter(core.IntegerNode.is);
419
+ const sepNode = res.children.find(core.LiteralNode.is);
420
+ const ans = {
421
+ type: type === 'float' ? 'mcfunction:float_range' : 'mcfunction:int_range',
422
+ range: res.range,
423
+ children: res.children,
424
+ value: sepNode
425
+ ? valueNodes.length === 2
426
+ ? [valueNodes[0].value, valueNodes[1].value]
427
+ : core.Range.endsBefore(valueNodes[0].range, sepNode.range.start)
428
+ ? [valueNodes[0].value, undefined]
429
+ : [undefined, valueNodes[0].value]
430
+ : [valueNodes[0].value, valueNodes[0].value],
431
+ };
432
+ if (!cycleable && ans.value[0] !== undefined && ans.value[1] !== undefined && ans.value[0] > ans.value[1]) {
433
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.range.min>max', ans.value[0], ans.value[1]), res);
434
+ }
435
+ return ans;
436
+ });
437
+ }
438
+ /**
439
+ * Failure when not beginning with `@[parse]`
440
+ */
441
+ function selector() {
442
+ let chunkLimited;
443
+ let currentEntity;
444
+ let dimensionLimited;
445
+ let playersOnly;
446
+ let predicates;
447
+ let single;
448
+ let typeLimited;
449
+ return core.map(core.sequence([
450
+ core.failOnEmpty(core.literal({ pool: node_1.EntitySelectorAtVariables, colorTokenType: 'keyword' })),
451
+ {
452
+ get: res => {
453
+ const variable = core.LiteralNode.is(res.children?.[0]) ? res.children[0].value : undefined;
454
+ currentEntity = variable ? variable === '@s' : undefined;
455
+ playersOnly = variable ? variable === '@p' || variable === '@a' || variable === '@r' : undefined;
456
+ predicates = variable === '@e' ? ['Entity::isAlive'] : undefined;
457
+ single = variable ? variable === '@p' || variable === '@r' || variable === '@s' : undefined;
458
+ typeLimited = playersOnly;
459
+ function invertable(parser) {
460
+ return core.map(core.sequence([
461
+ core.optional(core.failOnEmpty(core.literal({ pool: ['!'], colorTokenType: 'keyword' }))),
462
+ src => { src.skipSpace(); return undefined; },
463
+ parser,
464
+ ]), res => {
465
+ const ans = {
466
+ type: 'mcfunction:entity_selector/arguments/value/invertable',
467
+ range: res.range,
468
+ children: res.children,
469
+ inverted: !!res.children.find(n => core.LiteralNode.is(n) && n.value === '!'),
470
+ value: res.children.find(n => !core.LiteralNode.is(n) || n.value !== '!'),
471
+ };
472
+ return ans;
473
+ });
474
+ }
475
+ return core.optional(core.map(core.failOnEmpty(core.record({
476
+ start: '[',
477
+ pair: {
478
+ key: core.string({
479
+ ...core.BrigadierStringOptions,
480
+ value: {
481
+ parser: core.literal({ pool: [...node_1.EntitySelectorNode.ArgumentKeys], colorTokenType: 'property' }),
482
+ type: 'literal',
483
+ },
484
+ }),
485
+ sep: '=',
486
+ value: {
487
+ get: (record, key) => {
488
+ const hasKey = (key) => !!record.children.find(p => p.key?.value === key);
489
+ const hasNonInvertedKey = (key) => !!record.children.find(p => p.key?.value === key && !p.value?.inverted);
490
+ switch (key?.value) {
491
+ case 'advancements':
492
+ return core.map(core.record({
493
+ start: '{',
494
+ pair: {
495
+ key: core.resourceLocation({ category: 'advancement' }),
496
+ sep: '=',
497
+ value: core.select([
498
+ {
499
+ predicate: src => src.peek() === '{',
500
+ parser: core.map(core.record({
501
+ start: '{',
502
+ pair: {
503
+ key: unquotedString,
504
+ sep: '=',
505
+ value: core.boolean,
506
+ end: ',',
507
+ trailingEnd: true,
508
+ },
509
+ end: '}',
510
+ }), res => {
511
+ const ans = {
512
+ ...res,
513
+ type: 'mcfunction:entity_selector/arguments/advancements/criteria',
514
+ };
515
+ return ans;
516
+ }),
517
+ },
518
+ {
519
+ parser: core.boolean,
520
+ },
521
+ ]),
522
+ end: ',',
523
+ trailingEnd: true,
524
+ },
525
+ end: '}',
526
+ }), (res, _, ctx) => {
527
+ if (hasKey(key.value)) {
528
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
529
+ }
530
+ const ans = {
531
+ ...res,
532
+ type: 'mcfunction:entity_selector/arguments/advancements',
533
+ };
534
+ return ans;
535
+ });
536
+ case 'distance':
537
+ return core.map(range('float', 0), (res, _, ctx) => {
538
+ dimensionLimited = true;
539
+ // x, y, z, dx, dy, dz take precedence over distance, so we use ??= instead of = to ensure it won't override the result.
540
+ chunkLimited ?? (chunkLimited = !playersOnly && res.value[1] !== undefined);
541
+ if (hasKey(key.value)) {
542
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
543
+ }
544
+ return res;
545
+ });
546
+ case 'gamemode':
547
+ return core.map(invertable(core.string({
548
+ unquotable: core.BrigadierUnquotableOption,
549
+ value: {
550
+ type: 'literal',
551
+ parser: core.literal('adventure', 'creative', 'spectator', 'survival'),
552
+ },
553
+ })), (res, _, ctx) => {
554
+ playersOnly = true;
555
+ if (res.inverted ? hasNonInvertedKey(key.value) : hasKey(key.value)) {
556
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
557
+ }
558
+ return res;
559
+ });
560
+ case 'limit':
561
+ return core.map(integer(0), (res, _, ctx) => {
562
+ single = res.value <= 1;
563
+ if (hasKey(key.value)) {
564
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
565
+ }
566
+ if (currentEntity) {
567
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.arguments.not-applicable', (0, locales_1.localeQuote)(key.value)), key);
568
+ }
569
+ return res;
570
+ });
571
+ case 'level':
572
+ return core.map(range('integer', 0), (res, _, ctx) => {
573
+ playersOnly = true;
574
+ if (hasKey(key.value)) {
575
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
576
+ }
577
+ return res;
578
+ });
579
+ case 'name':
580
+ return core.map(invertable(core.brigadierString), (res, _, ctx) => {
581
+ if (res.inverted ? hasNonInvertedKey(key.value) : hasKey(key.value)) {
582
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
583
+ }
584
+ return res;
585
+ });
586
+ case 'nbt':
587
+ return invertable(nbt.parser.compound);
588
+ case 'predicate':
589
+ return invertable(core.resourceLocation({ category: 'predicate' }));
590
+ case 'scores':
591
+ return core.map(core.record({
592
+ start: '{',
593
+ pair: {
594
+ key: objective('reference', ['[', '=', ',', ']', '{', '}']),
595
+ sep: '=',
596
+ value: range('integer'),
597
+ end: ',',
598
+ trailingEnd: true,
599
+ },
600
+ end: '}',
601
+ }), (res, _, ctx) => {
602
+ if (hasKey(key.value)) {
603
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
604
+ }
605
+ const ans = {
606
+ ...res,
607
+ type: 'mcfunction:entity_selector/arguments/scores',
608
+ };
609
+ return ans;
610
+ });
611
+ case 'sort':
612
+ return core.map(core.string({
613
+ unquotable: core.BrigadierUnquotableOption,
614
+ value: {
615
+ type: 'literal',
616
+ parser: core.literal('arbitrary', 'furthest', 'nearest', 'random'),
617
+ },
618
+ }), (res, _, ctx) => {
619
+ if (hasKey(key.value)) {
620
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
621
+ }
622
+ if (currentEntity) {
623
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.arguments.not-applicable', (0, locales_1.localeQuote)(key.value)), key);
624
+ }
625
+ return res;
626
+ });
627
+ case 'tag':
628
+ return invertable(tag(['[', '=', ',', ']', '{', '}']));
629
+ case 'team':
630
+ return core.map(invertable(team('reference', ['[', '=', ',', ']', '{', '}'])), (res, _, ctx) => {
631
+ if (res.inverted ? hasNonInvertedKey(key.value) : hasKey(key.value)) {
632
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
633
+ }
634
+ return res;
635
+ });
636
+ case 'type':
637
+ return core.map(invertable(core.resourceLocation({ category: 'entity_type', allowTag: true })), (res, _, ctx) => {
638
+ if (typeLimited) {
639
+ if (hasKey(key.value)) {
640
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
641
+ }
642
+ else {
643
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.arguments.not-applicable', (0, locales_1.localeQuote)(key.value)), key);
644
+ }
645
+ }
646
+ else if (!res.inverted && !res.value.isTag) {
647
+ typeLimited = true;
648
+ if (core.ResourceLocationNode.toString(res.value, 'short') === 'player') {
649
+ playersOnly = true;
650
+ }
651
+ }
652
+ return res;
653
+ });
654
+ case 'x':
655
+ case 'y':
656
+ case 'z':
657
+ return core.map(double(), (res, _, ctx) => {
658
+ dimensionLimited = true;
659
+ if (hasKey(key.value)) {
660
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
661
+ }
662
+ return res;
663
+ });
664
+ case 'dx':
665
+ case 'dy':
666
+ case 'dz':
667
+ return core.map(double(), (res, _, ctx) => {
668
+ dimensionLimited = true;
669
+ chunkLimited = !playersOnly;
670
+ if (hasKey(key.value)) {
671
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
672
+ }
673
+ return res;
674
+ });
675
+ case 'x_rotation':
676
+ case 'y_rotation':
677
+ return core.map(range('float', undefined, undefined, true), (res, _, ctx) => {
678
+ if (hasKey(key.value)) {
679
+ ctx.err.report((0, locales_1.localize)('duplicate-key', (0, locales_1.localeQuote)(key.value)), key);
680
+ }
681
+ return res;
682
+ });
683
+ case undefined:
684
+ // The key is empty. Let's just fail the value as well.
685
+ return () => core.Failure;
686
+ default:
687
+ // The key is unknown.
688
+ return (_src, ctx) => {
689
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.arguments.unknown', (0, locales_1.localeQuote)(key.value)), key);
690
+ return core.Failure;
691
+ };
692
+ }
693
+ },
694
+ },
695
+ end: ',',
696
+ trailingEnd: true,
697
+ },
698
+ end: ']',
699
+ })), res => {
700
+ const ans = {
701
+ ...res,
702
+ type: 'mcfunction:entity_selector/arguments',
703
+ };
704
+ return ans;
705
+ }));
706
+ },
707
+ },
708
+ ]), res => {
709
+ const ans = {
710
+ type: 'mcfunction:entity_selector',
711
+ range: res.range,
712
+ children: res.children,
713
+ variable: res.children.find(core.LiteralNode.is).value.slice(1),
714
+ arguments: res.children.find(node_1.EntitySelectorArgumentsNode.is),
715
+ chunkLimited,
716
+ currentEntity,
717
+ dimensionLimited,
718
+ playersOnly,
719
+ predicates,
720
+ single,
721
+ typeLimited,
722
+ };
723
+ ans.hover = getEntitySelectorHover(ans);
724
+ return ans;
725
+ });
726
+ }
727
+ // This is more like a proof-of-concept.
728
+ // Might not make into the actual release.
729
+ function getEntitySelectorHover(node) {
730
+ const grades = new Map([
731
+ [0, '🤢'],
732
+ [1, '😅'],
733
+ [2, 'Good'],
734
+ [3, 'Great'],
735
+ [4, '😌👌'], // Excellent
736
+ ]);
737
+ let ans;
738
+ if (node.currentEntity) {
739
+ ans = `**Performance**: ${grades.get(4)}
740
+ - \`currentEntity\`: \`${node.currentEntity}\``;
741
+ }
742
+ else {
743
+ const amountOfTrue = [node.chunkLimited, node.dimensionLimited, node.playersOnly, node.typeLimited].filter(v => v).length;
744
+ ans = `**Performance**: ${grades.get(amountOfTrue)}
745
+ - \`chunkLimited\`: \`${!!node.chunkLimited}\`
746
+ - \`dimensionLimited\`: \`${!!node.dimensionLimited}\`
747
+ - \`playersOnly\`: \`${!!node.playersOnly}\`
748
+ - \`typeLimited\`: \`${!!node.chunkLimited}\``;
749
+ }
750
+ if (node.predicates?.length) {
751
+ ans += `
752
+
753
+ ------
754
+ **Predicates**:
755
+ ${node.predicates.map(p => `- \`${p}\``).join('\n')}`;
756
+ }
757
+ return ans;
758
+ }
759
+ exports.scoreHolderFakeName = validateLength(symbol('score_holder'), FakeNameMaxLength, 'mcfunction.parser.score_holder.fake-name.too-long');
760
+ function scoreHolder(amount) {
761
+ return core.map(core.select([
762
+ {
763
+ predicate: src => node_1.EntitySelectorAtVariable.is(src.peek(2)),
764
+ parser: selector(),
765
+ },
766
+ {
767
+ parser: exports.scoreHolderFakeName,
768
+ },
769
+ ]), (res, _src, ctx) => {
770
+ const ans = {
771
+ type: 'mcfunction:score_holder',
772
+ range: res.range,
773
+ children: [res],
774
+ };
775
+ if (core.SymbolNode.is(res)) {
776
+ ans.fakeName = res;
777
+ }
778
+ else {
779
+ ans.selector = res;
780
+ }
781
+ if (amount === 'single' && ans.selector && !ans.selector.single) {
782
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.entity-selector.multiple-disallowed'), ans);
783
+ }
784
+ return ans;
785
+ });
786
+ }
787
+ function symbol(options, terminators = []) {
788
+ return core.stopBefore(core.symbol(options), core.Whitespaces, terminators);
789
+ }
790
+ function objective(usageType, terminators = []) {
791
+ return validateLength(unquotableSymbol({ category: 'objective', usageType }, terminators), ObjectiveMaxLength, 'mcfunction.parser.objective.too-long');
792
+ }
793
+ const objectiveCriteria = core.map(core.any([
794
+ core.sequence([
795
+ core.stopBefore(core.resourceLocation({ category: 'stat_type', namespacePathSep: '.' }), ':'),
796
+ core.failOnEmpty(core.literal(':')),
797
+ {
798
+ get: res => {
799
+ if (core.ResourceLocationNode.is(res.children[0])) {
800
+ const category = node_1.ObjectiveCriteriaNode.ComplexCategories.get(core.ResourceLocationNode.toString(res.children[0], 'short'));
801
+ if (category) {
802
+ return core.resourceLocation({ category, namespacePathSep: '.' });
803
+ }
804
+ }
805
+ return core.resourceLocation({ pool: [], allowUnknown: true, namespacePathSep: '.' });
806
+ },
807
+ },
808
+ ]),
809
+ core.literal(...node_1.ObjectiveCriteriaNode.SimpleValues),
810
+ ]), res => {
811
+ const ans = {
812
+ type: 'mcfunction:objective_criteria',
813
+ range: res.range,
814
+ };
815
+ if (core.LiteralNode.is(res)) {
816
+ ans.simpleValue = res.value;
817
+ }
818
+ else {
819
+ ans.children = res.children.filter(core.ResourceLocationNode.is);
820
+ }
821
+ return ans;
822
+ });
823
+ function tag(terminators = []) {
824
+ return unquotableSymbol('tag', terminators);
825
+ }
826
+ exports.tag = tag;
827
+ function team(usageType, terminators = []) {
828
+ return unquotableSymbol({ category: 'team', usageType }, terminators);
829
+ }
830
+ exports.team = team;
831
+ function unquotableSymbol(options, terminators) {
832
+ return validateUnquotable(symbol(options, terminators));
833
+ }
834
+ const time = core.map(core.sequence([float(0, undefined), core.optional(core.failOnEmpty(core.literal(...node_1.TimeNode.Units)))]), res => {
835
+ const valueNode = res.children.find(core.FloatNode.is);
836
+ const unitNode = res.children.find(core.LiteralNode.is);
837
+ const ans = {
838
+ type: 'mcfunction:time',
839
+ range: res.range,
840
+ children: res.children,
841
+ value: valueNode.value,
842
+ unit: unitNode?.value,
843
+ };
844
+ return ans;
845
+ });
846
+ const unquotedString = core.string({
847
+ unquotable: core.BrigadierUnquotableOption,
848
+ });
849
+ const UuidPattern = /^[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+$/i;
850
+ const uuid = (src, ctx) => {
851
+ const ans = {
852
+ type: 'mcfunction:uuid',
853
+ range: core.Range.create(src),
854
+ bits: [0n, 0n],
855
+ };
856
+ const raw = src.readUntil(' ', '\r', '\n', '\r');
857
+ /**
858
+ * According to the implementation of Minecraft's UUID parser and Java's `UUID#fromString` method,
859
+ * only strings that don't have five parts and strings where any part exceed the maximum Long value are
860
+ * considered invalid.
861
+ *
862
+ * http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/default/src/share/classes/java/util/UUID.java
863
+ */
864
+ let isLegal = false;
865
+ if (raw.match(UuidPattern)) {
866
+ try {
867
+ const parts = raw.split('-').map(p => BigInt(`0x${p}`));
868
+ if (parts.every(p => p <= LongMax)) {
869
+ isLegal = true;
870
+ ans.bits[0] = BigInt.asIntN(64, (parts[0] << 32n) | (parts[1] << 16n) | parts[2]);
871
+ ans.bits[1] = BigInt.asIntN(64, (parts[3] << 48n) | parts[4]);
872
+ }
873
+ }
874
+ catch {
875
+ // Ignored.
876
+ }
877
+ }
878
+ ans.range.end = src.cursor;
879
+ if (!isLegal) {
880
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.uuid.invalid'), ans);
881
+ }
882
+ return ans;
883
+ };
884
+ function validateLength(parser, maxLength, localeKey) {
885
+ return (src, ctx) => {
886
+ if (!shouldValidateLength(ctx)) {
887
+ return parser(src, ctx);
888
+ }
889
+ return core.map(parser, (res, _src, ctx) => {
890
+ if (res.value.length > maxLength) {
891
+ ctx.err.report((0, locales_1.localize)(localeKey, maxLength), res);
892
+ }
893
+ return res;
894
+ })(src, ctx);
895
+ };
896
+ }
897
+ function validateUnquotable(parser) {
898
+ return core.map(parser, (res, _src, ctx) => {
899
+ if (!res.value.match(core.BrigadierUnquotablePattern)) {
900
+ ctx.err.report((0, locales_1.localize)('parser.string.illegal-brigadier', (0, locales_1.localeQuote)(res.value)), res);
901
+ }
902
+ return res;
903
+ });
904
+ }
905
+ function vector(options) {
906
+ return (src, ctx) => {
907
+ const ans = {
908
+ type: 'mcfunction:vector',
909
+ range: core.Range.create(src),
910
+ children: [],
911
+ options,
912
+ system: 0 /* World */,
913
+ };
914
+ if (src.peek() === '^') {
915
+ ans.system = 1 /* Local */;
916
+ }
917
+ for (let i = 0; i < options.dimension; i++) {
918
+ if (i > 0) {
919
+ mcf.sep(src, ctx);
920
+ }
921
+ const coord = options.integersOnly ? coordinate(options.integersOnly)(src, ctx) : coordinate(options.integersOnly)(src, ctx);
922
+ ans.children.push(coord);
923
+ if ((ans.system === 1 /* Local */) !== (coord.notation === '^')) {
924
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.vector.mixed'), coord);
925
+ }
926
+ }
927
+ if (options.noLocal && ans.system === 1 /* Local */) {
928
+ ctx.err.report((0, locales_1.localize)('mcfunction.parser.vector.local-disallowed'), ans);
929
+ }
930
+ ans.range.end = src.cursor;
931
+ return ans;
932
+ };
933
+ }
934
+ //# sourceMappingURL=argument.js.map