@spyglassmc/nbt 0.3.1 → 0.3.2
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/lib/checker/index.d.ts +4 -7
- package/lib/checker/index.js +72 -32
- package/lib/checker/mcdocUtil.js +13 -41
- package/lib/node/index.js +10 -3
- package/lib/parser/collection.js +28 -4
- package/lib/parser/compound.js +4 -1
- package/lib/parser/entry.js +5 -5
- package/lib/parser/path.js +5 -7
- package/lib/parser/primitive.js +61 -12
- package/package.json +4 -4
package/lib/checker/index.d.ts
CHANGED
|
@@ -11,9 +11,9 @@ declare global {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* @param id If the registry is under the `custom` namespace, `id` can only be a string. Otherwise it can be a string, string array, or `undefined`.
|
|
15
|
-
* If set to `undefined` or an empty array, all mcdoc compound definitions for this registry will be merged for checking, and unknown keys are allowed.
|
|
16
|
-
*/
|
|
14
|
+
* @param id If the registry is under the `custom` namespace, `id` can only be a string. Otherwise it can be a string, string array, or `undefined`.
|
|
15
|
+
* If set to `undefined` or an empty array, all mcdoc compound definitions for this registry will be merged for checking, and unknown keys are allowed.
|
|
16
|
+
*/
|
|
17
17
|
export declare function index(registry: string, id: core.FullResourceLocation | readonly core.FullResourceLocation[] | undefined, options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
18
18
|
export declare function index(registry: string, id: core.FullResourceLocation, options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
19
19
|
/**
|
|
@@ -21,10 +21,7 @@ export declare function index(registry: string, id: core.FullResourceLocation, o
|
|
|
21
21
|
*/
|
|
22
22
|
export declare function definition(identifier: `::${string}::${string}`, options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
23
23
|
export declare function blockStates(blocks: string[], _options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
24
|
-
|
|
25
|
-
* @param path The {@link core.SymbolPath} to the compound definition.
|
|
26
|
-
*/
|
|
27
|
-
export declare function compound(data: any, options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
24
|
+
export declare function compound(typeDef: mcdoc.StructType, options?: Options): core.SyncChecker<NbtCompoundNode>;
|
|
28
25
|
export declare function enum_(path: core.SymbolPath | undefined, _options?: Options): core.SyncChecker<NbtPrimitiveNode>;
|
|
29
26
|
/**
|
|
30
27
|
* @param id If set to `undefined` or an empty array, all mcdoc compound definitions for this registry will be merged for checking, and unknown keys are allowed.
|
package/lib/checker/index.js
CHANGED
|
@@ -3,14 +3,12 @@ import { localeQuote, localize } from '@spyglassmc/locales';
|
|
|
3
3
|
import * as mcdoc from '@spyglassmc/mcdoc';
|
|
4
4
|
import { NbtListNode } from '../node/index.js';
|
|
5
5
|
import { localizeTag } from '../util.js';
|
|
6
|
-
import { getBlocksFromItem, getEntityFromItem, getSpecialStringParser } from './mcdocUtil.js';
|
|
6
|
+
import { getBlocksFromItem, getEntityFromItem, getSpecialStringParser, } from './mcdocUtil.js';
|
|
7
7
|
export function index(registry, id, options = {}) {
|
|
8
8
|
switch (registry) {
|
|
9
9
|
case 'custom:blockitemstates':
|
|
10
10
|
const blockIds = getBlocksFromItem(id);
|
|
11
|
-
return blockIds
|
|
12
|
-
? blockStates(blockIds, options)
|
|
13
|
-
: core.checker.noop;
|
|
11
|
+
return blockIds ? blockStates(blockIds, options) : core.checker.noop;
|
|
14
12
|
case 'custom:blockstates':
|
|
15
13
|
return blockStates([id], options);
|
|
16
14
|
case 'custom:spawnitemtag':
|
|
@@ -19,25 +17,44 @@ export function index(registry, id, options = {}) {
|
|
|
19
17
|
? index('entity_type', entityId, options)
|
|
20
18
|
: core.checker.noop;
|
|
21
19
|
default:
|
|
20
|
+
const identifier = getRegistryIdentifier(registry);
|
|
21
|
+
if (!identifier) {
|
|
22
|
+
return core.checker.noop;
|
|
23
|
+
}
|
|
22
24
|
return (node, ctx) => {
|
|
23
|
-
|
|
24
|
-
// options.allowUnknownKey ||= allowUnknownKey
|
|
25
|
-
// compound(value, options)(node, ctx)
|
|
25
|
+
definition(identifier, options)(node, ctx);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
function getRegistryIdentifier(registry) {
|
|
30
|
+
switch (registry) {
|
|
31
|
+
case 'block':
|
|
32
|
+
return '::java::server::world::block::BlockEntity';
|
|
33
|
+
case 'entity_type':
|
|
34
|
+
return '::java::server::world::entity::AnyEntity';
|
|
35
|
+
case 'item':
|
|
36
|
+
return '::java::server::world::item::AnyItem';
|
|
37
|
+
default:
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
29
41
|
/**
|
|
30
42
|
* @param identifier An identifier of mcdoc compound definition. e.g. `::minecraft::util::invitem::InventoryItem`
|
|
31
43
|
*/
|
|
32
44
|
export function definition(identifier, options = {}) {
|
|
33
|
-
const index = identifier.lastIndexOf('::');
|
|
34
|
-
const module = identifier.slice(0, index);
|
|
35
|
-
const compoundDef = identifier.slice(index + 2);
|
|
36
|
-
const path = { category: 'mcdoc', path: [module, compoundDef] };
|
|
37
45
|
return (node, ctx) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
const symbol = ctx.symbols.query(ctx.doc, 'mcdoc', identifier);
|
|
47
|
+
const typeDef = symbol.getData(mcdoc.binder.TypeDefSymbolData.is)?.typeDef;
|
|
48
|
+
if (!typeDef) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
switch (typeDef.kind) {
|
|
52
|
+
case 'struct':
|
|
53
|
+
compound(typeDef, options)(node, ctx);
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
ctx.logger.error(`[nbt.checker.definition] Expected a struct type, but got ${typeDef.kind}`);
|
|
57
|
+
}
|
|
41
58
|
};
|
|
42
59
|
}
|
|
43
60
|
export function blockStates(blocks, _options = {}) {
|
|
@@ -48,7 +65,9 @@ export function blockStates(blocks, _options = {}) {
|
|
|
48
65
|
continue;
|
|
49
66
|
}
|
|
50
67
|
// Type check.
|
|
51
|
-
if (valueNode.type === 'nbt:byte' &&
|
|
68
|
+
if (valueNode.type === 'nbt:byte' &&
|
|
69
|
+
(ctx.src.slice(valueNode.range).toLowerCase() === 'false' ||
|
|
70
|
+
ctx.src.slice(valueNode.range).toLowerCase() === 'true')) {
|
|
52
71
|
ctx.err.report(localize('nbt.checker.block-states.fake-boolean'), valueNode, 2 /* core.ErrorSeverity.Warning */);
|
|
53
72
|
continue;
|
|
54
73
|
}
|
|
@@ -70,25 +89,25 @@ export function blockStates(blocks, _options = {}) {
|
|
|
70
89
|
}
|
|
71
90
|
};
|
|
72
91
|
}
|
|
73
|
-
|
|
74
|
-
* @param path The {@link core.SymbolPath} to the compound definition.
|
|
75
|
-
*/
|
|
76
|
-
export function compound(data, options = {}) {
|
|
92
|
+
export function compound(typeDef, options = {}) {
|
|
77
93
|
return (node, ctx) => {
|
|
78
94
|
for (const { key: keyNode, value: valueNode } of node.children) {
|
|
79
95
|
if (!keyNode || !valueNode) {
|
|
80
96
|
continue;
|
|
81
97
|
}
|
|
82
98
|
const key = keyNode.value;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
// TODO: handle spread types
|
|
100
|
+
const fieldDef = typeDef.fields.find((p) => p.kind === 'pair' && p.key === key);
|
|
101
|
+
if (fieldDef) {
|
|
102
|
+
// TODO: enter a reference to the mcdoc key
|
|
103
|
+
fieldValue(fieldDef.type, options)(valueNode, ctx);
|
|
87
104
|
}
|
|
88
105
|
else if (!options.allowUnknownKey) {
|
|
89
106
|
ctx.err.report(localize('unknown-key', localeQuote(key)), keyNode, 2 /* core.ErrorSeverity.Warning */);
|
|
90
107
|
}
|
|
91
108
|
}
|
|
109
|
+
// TODO: check for required fields
|
|
110
|
+
// requires an update to vanilla-mcdoc to make most fields optional
|
|
92
111
|
};
|
|
93
112
|
}
|
|
94
113
|
export function enum_(path, _options = {}) {
|
|
@@ -243,7 +262,7 @@ export function path(registry, id) {
|
|
|
243
262
|
export function fieldValue(type, options) {
|
|
244
263
|
const isInRange = (value, { kind, min = -Infinity, max = Infinity }) => {
|
|
245
264
|
const comparator = (a, b, exclusive) => exclusive ? a < b : a <= b;
|
|
246
|
-
return comparator(min, value, kind & 0b10) && comparator(value, max, kind & 0b01);
|
|
265
|
+
return (comparator(min, value, kind & 0b10) && comparator(value, max, kind & 0b01));
|
|
247
266
|
};
|
|
248
267
|
const ExpectedTypes = {
|
|
249
268
|
boolean: 'nbt:byte',
|
|
@@ -263,7 +282,18 @@ export function fieldValue(type, options) {
|
|
|
263
282
|
};
|
|
264
283
|
return (node, ctx) => {
|
|
265
284
|
// Rough type check.
|
|
266
|
-
if (type.kind !== 'any' &&
|
|
285
|
+
if (type.kind !== 'any' &&
|
|
286
|
+
type.kind !== 'dispatcher' &&
|
|
287
|
+
type.kind !== 'enum' &&
|
|
288
|
+
type.kind !== 'literal' &&
|
|
289
|
+
type.kind !== 'reference' &&
|
|
290
|
+
type.kind !== 'union' &&
|
|
291
|
+
type.kind !== 'attributed' &&
|
|
292
|
+
type.kind !== 'unsafe' &&
|
|
293
|
+
type.kind !== 'concrete' &&
|
|
294
|
+
type.kind !== 'indexed' &&
|
|
295
|
+
type.kind !== 'template' &&
|
|
296
|
+
node.type !== ExpectedTypes[type.kind]) {
|
|
267
297
|
ctx.err.report(localize('expected', localizeTag(ExpectedTypes[type.kind])), node, 2 /* core.ErrorSeverity.Warning */);
|
|
268
298
|
return;
|
|
269
299
|
}
|
|
@@ -278,12 +308,14 @@ export function fieldValue(type, options) {
|
|
|
278
308
|
case 'int_array':
|
|
279
309
|
case 'long_array':
|
|
280
310
|
node = node;
|
|
281
|
-
if (type.lengthRange &&
|
|
311
|
+
if (type.lengthRange &&
|
|
312
|
+
!isInRange(node.children.length, type.lengthRange)) {
|
|
282
313
|
ctx.err.report(localize('expected', localize('nbt.checker.collection.length-between', localizeTag(node.type), type.lengthRange.min ?? '-∞', type.lengthRange.max ?? '+∞')), node, 2 /* core.ErrorSeverity.Warning */);
|
|
283
314
|
}
|
|
284
315
|
if (type.valueRange) {
|
|
285
316
|
for (const { value: childNode } of node.children) {
|
|
286
|
-
if (childNode &&
|
|
317
|
+
if (childNode &&
|
|
318
|
+
!isInRange(Number(childNode.value), type.valueRange)) {
|
|
287
319
|
ctx.err.report(localize('number.between', type.valueRange.min ?? '-∞', type.valueRange.max ?? '+∞'), node, 2 /* core.ErrorSeverity.Warning */);
|
|
288
320
|
}
|
|
289
321
|
}
|
|
@@ -296,7 +328,8 @@ export function fieldValue(type, options) {
|
|
|
296
328
|
case 'float':
|
|
297
329
|
case 'double':
|
|
298
330
|
node = node;
|
|
299
|
-
if (type.valueRange &&
|
|
331
|
+
if (type.valueRange &&
|
|
332
|
+
!isInRange(Number(node.value), type.valueRange)) {
|
|
300
333
|
ctx.err.report(localize('number.between', type.valueRange.min ?? '-∞', type.valueRange.max ?? '+∞'), node, 2 /* core.ErrorSeverity.Warning */);
|
|
301
334
|
}
|
|
302
335
|
break;
|
|
@@ -314,7 +347,8 @@ export function fieldValue(type, options) {
|
|
|
314
347
|
case 'list':
|
|
315
348
|
node = node;
|
|
316
349
|
type = mcdoc.simplifyListType(type);
|
|
317
|
-
if (type.lengthRange &&
|
|
350
|
+
if (type.lengthRange &&
|
|
351
|
+
!isInRange(node.children.length, type.lengthRange)) {
|
|
318
352
|
ctx.err.report(localize('expected', localize('nbt.checker.collection.length-between', localizeTag(node.type), type.lengthRange.min ?? '-∞', type.lengthRange.max ?? '+∞')), node, 2 /* core.ErrorSeverity.Warning */);
|
|
319
353
|
}
|
|
320
354
|
for (const { value: childNode } of node.children) {
|
|
@@ -327,7 +361,8 @@ export function fieldValue(type, options) {
|
|
|
327
361
|
node = node;
|
|
328
362
|
let suffix = '';
|
|
329
363
|
let valueNode = node;
|
|
330
|
-
if (core.ItemNode.is(node.parent) &&
|
|
364
|
+
if (core.ItemNode.is(node.parent) &&
|
|
365
|
+
NbtListNode.is(node.parent.parent)) {
|
|
331
366
|
suffix = '[]';
|
|
332
367
|
valueNode = node.parent.parent;
|
|
333
368
|
}
|
|
@@ -362,13 +397,18 @@ export function fieldValue(type, options) {
|
|
|
362
397
|
type = mcdoc.flattenUnionType(type);
|
|
363
398
|
if (type.members.length === 0) {
|
|
364
399
|
ctx.err.report(localize('nbt.checker.compound.field.union-empty-members'), core.PairNode.is(node.parent)
|
|
365
|
-
?
|
|
400
|
+
? node.parent.key ?? node.parent
|
|
366
401
|
: node, 2 /* core.ErrorSeverity.Warning */);
|
|
367
402
|
}
|
|
368
403
|
else {
|
|
369
|
-
|
|
404
|
+
;
|
|
405
|
+
core.checker.any(type.members.map((t) => fieldValue(t, options)))(node, ctx);
|
|
370
406
|
}
|
|
371
407
|
break;
|
|
408
|
+
case 'attributed':
|
|
409
|
+
// TODO: don't just ignore the attribute
|
|
410
|
+
fieldValue(type.child, options)(node, ctx);
|
|
411
|
+
break;
|
|
372
412
|
}
|
|
373
413
|
};
|
|
374
414
|
}
|
package/lib/checker/mcdocUtil.js
CHANGED
|
@@ -63,51 +63,23 @@ const BlockItems = {
|
|
|
63
63
|
'minecraft:dead_tube_coral_wall_fan',
|
|
64
64
|
],
|
|
65
65
|
// Torches.
|
|
66
|
-
'minecraft:torch': [
|
|
67
|
-
|
|
68
|
-
'minecraft:wall_torch',
|
|
69
|
-
],
|
|
70
|
-
'minecraft:soul_torch': [
|
|
71
|
-
'minecraft:soul_torch',
|
|
72
|
-
'minecraft:soul_wall_torch',
|
|
73
|
-
],
|
|
66
|
+
'minecraft:torch': ['minecraft:torch', 'minecraft:wall_torch'],
|
|
67
|
+
'minecraft:soul_torch': ['minecraft:soul_torch', 'minecraft:soul_wall_torch'],
|
|
74
68
|
'minecraft:redstone_torch': [
|
|
75
69
|
'minecraft:redstone_torch',
|
|
76
70
|
'minecraft:redstone_wall_torch',
|
|
77
71
|
],
|
|
78
|
-
'minecraft:beetroot_seeds': [
|
|
79
|
-
|
|
80
|
-
],
|
|
81
|
-
'minecraft:
|
|
82
|
-
|
|
83
|
-
],
|
|
84
|
-
'minecraft:
|
|
85
|
-
|
|
86
|
-
],
|
|
87
|
-
'minecraft:
|
|
88
|
-
|
|
89
|
-
],
|
|
90
|
-
'minecraft:melon_seeds': [
|
|
91
|
-
'minecraft:melon_stem',
|
|
92
|
-
],
|
|
93
|
-
'minecraft:potato': [
|
|
94
|
-
'minecraft:potatoes',
|
|
95
|
-
],
|
|
96
|
-
'minecraft:pumpkin_seeds': [
|
|
97
|
-
'minecraft:pumpkin_stem',
|
|
98
|
-
],
|
|
99
|
-
'minecraft:redstone': [
|
|
100
|
-
'minecraft:redstone_wire',
|
|
101
|
-
],
|
|
102
|
-
'minecraft:string': [
|
|
103
|
-
'minecraft:tripwire',
|
|
104
|
-
],
|
|
105
|
-
'minecraft:sweat_berries': [
|
|
106
|
-
'minecraft:sweat_berry_bush',
|
|
107
|
-
],
|
|
108
|
-
'minecraft:wheat_seeds': [
|
|
109
|
-
'minecraft:wheat',
|
|
110
|
-
],
|
|
72
|
+
'minecraft:beetroot_seeds': ['minecraft:beetroots'],
|
|
73
|
+
'minecraft:carrot': ['minecraft:carrots'],
|
|
74
|
+
'minecraft:cocoa_beans': ['minecraft:cocoa'],
|
|
75
|
+
'minecraft:glow_berries': ['minecraft:cave_vines'],
|
|
76
|
+
'minecraft:melon_seeds': ['minecraft:melon_stem'],
|
|
77
|
+
'minecraft:potato': ['minecraft:potatoes'],
|
|
78
|
+
'minecraft:pumpkin_seeds': ['minecraft:pumpkin_stem'],
|
|
79
|
+
'minecraft:redstone': ['minecraft:redstone_wire'],
|
|
80
|
+
'minecraft:string': ['minecraft:tripwire'],
|
|
81
|
+
'minecraft:sweat_berries': ['minecraft:sweat_berry_bush'],
|
|
82
|
+
'minecraft:wheat_seeds': ['minecraft:wheat'],
|
|
111
83
|
};
|
|
112
84
|
export function getBlocksFromItem(item) {
|
|
113
85
|
return BlockItems[item];
|
package/lib/node/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export var NbtNode;
|
|
|
3
3
|
(function (NbtNode) {
|
|
4
4
|
/* istanbul ignore next */
|
|
5
5
|
function is(node) {
|
|
6
|
-
return NbtPrimitiveNode.is(node) ||
|
|
6
|
+
return (NbtPrimitiveNode.is(node) ||
|
|
7
|
+
NbtCompoundNode.is(node) ||
|
|
8
|
+
NbtCollectionNode.is(node));
|
|
7
9
|
}
|
|
8
10
|
NbtNode.is = is;
|
|
9
11
|
})(NbtNode || (NbtNode = {}));
|
|
@@ -27,7 +29,10 @@ export var NbtIntegerAlikeNode;
|
|
|
27
29
|
(function (NbtIntegerAlikeNode) {
|
|
28
30
|
/* istanbul ignore next */
|
|
29
31
|
function is(node) {
|
|
30
|
-
return NbtByteNode.is(node) ||
|
|
32
|
+
return (NbtByteNode.is(node) ||
|
|
33
|
+
NbtShortNode.is(node) ||
|
|
34
|
+
NbtIntNode.is(node) ||
|
|
35
|
+
NbtLongNode.is(node));
|
|
31
36
|
}
|
|
32
37
|
NbtIntegerAlikeNode.is = is;
|
|
33
38
|
})(NbtIntegerAlikeNode || (NbtIntegerAlikeNode = {}));
|
|
@@ -115,7 +120,9 @@ export var NbtPrimitiveArrayNode;
|
|
|
115
120
|
(function (NbtPrimitiveArrayNode) {
|
|
116
121
|
/* istanbul ignore next */
|
|
117
122
|
function is(node) {
|
|
118
|
-
return NbtByteArrayNode.is(node) ||
|
|
123
|
+
return (NbtByteArrayNode.is(node) ||
|
|
124
|
+
NbtIntArrayNode.is(node) ||
|
|
125
|
+
NbtLongArrayNode.is(node));
|
|
119
126
|
}
|
|
120
127
|
NbtPrimitiveArrayNode.is = is;
|
|
121
128
|
})(NbtPrimitiveArrayNode || (NbtPrimitiveArrayNode = {}));
|
package/lib/parser/collection.js
CHANGED
|
@@ -4,7 +4,13 @@ import { localizeTag } from '../util.js';
|
|
|
4
4
|
import { entry } from './entry.js';
|
|
5
5
|
import { primitive } from './primitive.js';
|
|
6
6
|
export const list = (src, ctx) => {
|
|
7
|
-
const parser = core.list({
|
|
7
|
+
const parser = core.list({
|
|
8
|
+
start: '[',
|
|
9
|
+
value: entry,
|
|
10
|
+
sep: ',',
|
|
11
|
+
trailingSep: false,
|
|
12
|
+
end: ']',
|
|
13
|
+
});
|
|
8
14
|
const ans = parser(src, ctx);
|
|
9
15
|
ans.type = 'nbt:list';
|
|
10
16
|
ans.valueType = ans.children[0]?.value?.type;
|
|
@@ -19,7 +25,13 @@ export const list = (src, ctx) => {
|
|
|
19
25
|
return ans;
|
|
20
26
|
};
|
|
21
27
|
export const byteArray = (src, ctx) => {
|
|
22
|
-
const parser = core.list({
|
|
28
|
+
const parser = core.list({
|
|
29
|
+
start: '[B;',
|
|
30
|
+
value: primitive,
|
|
31
|
+
sep: ',',
|
|
32
|
+
trailingSep: false,
|
|
33
|
+
end: ']',
|
|
34
|
+
});
|
|
23
35
|
const ans = parser(src, ctx);
|
|
24
36
|
ans.type = 'nbt:byte_array';
|
|
25
37
|
// Check if every element is of the required type.
|
|
@@ -31,7 +43,13 @@ export const byteArray = (src, ctx) => {
|
|
|
31
43
|
return ans;
|
|
32
44
|
};
|
|
33
45
|
export const intArray = (src, ctx) => {
|
|
34
|
-
const parser = core.list({
|
|
46
|
+
const parser = core.list({
|
|
47
|
+
start: '[I;',
|
|
48
|
+
value: primitive,
|
|
49
|
+
sep: ',',
|
|
50
|
+
trailingSep: false,
|
|
51
|
+
end: ']',
|
|
52
|
+
});
|
|
35
53
|
const ans = parser(src, ctx);
|
|
36
54
|
ans.type = 'nbt:int_array';
|
|
37
55
|
// Check if every element is of the required type.
|
|
@@ -43,7 +61,13 @@ export const intArray = (src, ctx) => {
|
|
|
43
61
|
return ans;
|
|
44
62
|
};
|
|
45
63
|
export const longArray = (src, ctx) => {
|
|
46
|
-
const parser = core.list({
|
|
64
|
+
const parser = core.list({
|
|
65
|
+
start: '[L;',
|
|
66
|
+
value: primitive,
|
|
67
|
+
sep: ',',
|
|
68
|
+
trailingSep: false,
|
|
69
|
+
end: ']',
|
|
70
|
+
});
|
|
47
71
|
const ans = parser(src, ctx);
|
|
48
72
|
ans.type = 'nbt:long_array';
|
|
49
73
|
// Check if every element is of the required type.
|
package/lib/parser/compound.js
CHANGED
|
@@ -4,7 +4,10 @@ export const compound = (src, ctx) => {
|
|
|
4
4
|
return core.setType('nbt:compound', core.record({
|
|
5
5
|
start: '{',
|
|
6
6
|
pair: {
|
|
7
|
-
key: core.failOnEmpty(core.string({
|
|
7
|
+
key: core.failOnEmpty(core.string({
|
|
8
|
+
...core.BrigadierStringOptions,
|
|
9
|
+
colorTokenType: 'property',
|
|
10
|
+
})),
|
|
8
11
|
sep: ':',
|
|
9
12
|
value: entry,
|
|
10
13
|
end: ',',
|
package/lib/parser/entry.js
CHANGED
|
@@ -3,11 +3,11 @@ import { byteArray, intArray, list, longArray } from './collection.js';
|
|
|
3
3
|
import { compound } from './compound.js';
|
|
4
4
|
import { primitive } from './primitive.js';
|
|
5
5
|
export const entry = (src, ctx) => core.failOnEmpty(core.select([
|
|
6
|
-
{ predicate: src => src.tryPeek('[B;'), parser: byteArray },
|
|
7
|
-
{ predicate: src => src.tryPeek('[I;'), parser: intArray },
|
|
8
|
-
{ predicate: src => src.tryPeek('[L;'), parser: longArray },
|
|
9
|
-
{ predicate: src => src.tryPeek('['), parser: list },
|
|
10
|
-
{ predicate: src => src.tryPeek('{'), parser: compound },
|
|
6
|
+
{ predicate: (src) => src.tryPeek('[B;'), parser: byteArray },
|
|
7
|
+
{ predicate: (src) => src.tryPeek('[I;'), parser: intArray },
|
|
8
|
+
{ predicate: (src) => src.tryPeek('[L;'), parser: longArray },
|
|
9
|
+
{ predicate: (src) => src.tryPeek('['), parser: list },
|
|
10
|
+
{ predicate: (src) => src.tryPeek('{'), parser: compound },
|
|
11
11
|
{ parser: primitive },
|
|
12
12
|
]))(src, ctx);
|
|
13
13
|
//# sourceMappingURL=entry.js.map
|
package/lib/parser/path.js
CHANGED
|
@@ -51,9 +51,7 @@ const index = (children, src, ctx) => {
|
|
|
51
51
|
}
|
|
52
52
|
node.range.end = src.cursor;
|
|
53
53
|
children.push(node);
|
|
54
|
-
return src.trySkip('.')
|
|
55
|
-
? ['index', 'key']
|
|
56
|
-
: ['end', 'index'];
|
|
54
|
+
return src.trySkip('.') ? ['index', 'key'] : ['end', 'index'];
|
|
57
55
|
};
|
|
58
56
|
const key = (children, src, ctx) => {
|
|
59
57
|
const node = core.string({
|
|
@@ -61,12 +59,12 @@ const key = (children, src, ctx) => {
|
|
|
61
59
|
escapable: {},
|
|
62
60
|
// No single quotes: https://bugs.mojang.com/browse/MC-175504
|
|
63
61
|
quotes: ['"'],
|
|
64
|
-
unquotable: {
|
|
62
|
+
unquotable: {
|
|
63
|
+
blockList: new Set(['\n', '\r', '\t', ' ', '"', '[', ']', '.', '{', '}']),
|
|
64
|
+
},
|
|
65
65
|
})(src, ctx);
|
|
66
66
|
children.push(node);
|
|
67
|
-
return src.trySkip('.')
|
|
68
|
-
? ['index', 'key']
|
|
69
|
-
: ['end', 'filter', 'index'];
|
|
67
|
+
return src.trySkip('.') ? ['index', 'key'] : ['end', 'filter', 'index'];
|
|
70
68
|
};
|
|
71
69
|
function nextPart(src) {
|
|
72
70
|
switch (src.peek()) {
|
package/lib/parser/primitive.js
CHANGED
|
@@ -1,15 +1,64 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
2
|
import { localize } from '@spyglassmc/locales';
|
|
3
3
|
import { localizeTag } from '../util.js';
|
|
4
|
-
const FloatMaximum = (2 -
|
|
4
|
+
const FloatMaximum = (2 - 2 ** -23) * 2 ** 127;
|
|
5
5
|
const NumeralPatterns = [
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
{
|
|
7
|
+
pattern: /^[-+]?(?:0|[1-9][0-9]*)b$/i,
|
|
8
|
+
type: 'nbt:byte',
|
|
9
|
+
hasSuffix: true,
|
|
10
|
+
group: 2 /* Group.IntegerAlike */,
|
|
11
|
+
min: -128,
|
|
12
|
+
max: 127,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
pattern: /^[-+]?(?:0|[1-9][0-9]*)s$/i,
|
|
16
|
+
type: 'nbt:short',
|
|
17
|
+
hasSuffix: true,
|
|
18
|
+
group: 2 /* Group.IntegerAlike */,
|
|
19
|
+
min: -32768,
|
|
20
|
+
max: 32767,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /^[-+]?(?:0|[1-9][0-9]*)$/,
|
|
24
|
+
type: 'nbt:int',
|
|
25
|
+
hasSuffix: false,
|
|
26
|
+
group: 2 /* Group.IntegerAlike */,
|
|
27
|
+
min: -2147483648,
|
|
28
|
+
max: 2147483647,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
pattern: /^[-+]?(?:0|[1-9][0-9]*)l$/i,
|
|
32
|
+
type: 'nbt:long',
|
|
33
|
+
hasSuffix: true,
|
|
34
|
+
group: 3 /* Group.LongAlike */,
|
|
35
|
+
min: -9223372036854775808n,
|
|
36
|
+
max: 9223372036854775807n,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
pattern: /^[-+]?(?:[0-9]+\.?|[0-9]*\.[0-9]+)(?:e[-+]?[0-9]+)?f$/i,
|
|
40
|
+
type: 'nbt:float',
|
|
41
|
+
hasSuffix: true,
|
|
42
|
+
group: 1 /* Group.FloatAlike */,
|
|
43
|
+
min: -FloatMaximum,
|
|
44
|
+
max: FloatMaximum,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
pattern: /^[-+]?(?:[0-9]+\.|[0-9]*\.[0-9]+)(?:e[-+]?[0-9]+)?$/i,
|
|
48
|
+
type: 'nbt:double',
|
|
49
|
+
hasSuffix: false,
|
|
50
|
+
group: 1 /* Group.FloatAlike */,
|
|
51
|
+
min: -Number.MAX_VALUE,
|
|
52
|
+
max: Number.MAX_VALUE,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
pattern: /^[-+]?(?:[0-9]+\.?|[0-9]*\.[0-9]+)(?:e[-+]?[0-9]+)?d$/i,
|
|
56
|
+
type: 'nbt:double',
|
|
57
|
+
hasSuffix: true,
|
|
58
|
+
group: 1 /* Group.FloatAlike */,
|
|
59
|
+
min: -Number.MAX_VALUE,
|
|
60
|
+
max: Number.MAX_VALUE,
|
|
61
|
+
},
|
|
13
62
|
{ pattern: /^true$/i, type: 'nbt:byte', value: 1, group: 0 /* Group.Boolean */ },
|
|
14
63
|
{ pattern: /^false$/i, type: 'nbt:byte', value: 0, group: 0 /* Group.Boolean */ },
|
|
15
64
|
];
|
|
@@ -31,11 +80,11 @@ export const primitive = (src, ctx) => {
|
|
|
31
80
|
return ans;
|
|
32
81
|
}
|
|
33
82
|
let isOutOfRange = false;
|
|
34
|
-
const onOutOfRange = () => isOutOfRange = true;
|
|
83
|
+
const onOutOfRange = () => (isOutOfRange = true);
|
|
35
84
|
const numeralParser = e.group === 2 /* Group.IntegerAlike */
|
|
36
|
-
// As we already checked the format of the value with `e.pattern` in the if-block, there is no need to check
|
|
37
|
-
|
|
38
|
-
|
|
85
|
+
? // As we already checked the format of the value with `e.pattern` in the if-block, there is no need to check
|
|
86
|
+
// it again here in the parser, therefore we just pass in a simple /./ regex.
|
|
87
|
+
core.integer({ pattern: /./, min: e.min, max: e.max, onOutOfRange })
|
|
39
88
|
: e.group === 3 /* Group.LongAlike */
|
|
40
89
|
? core.long({ pattern: /./, min: e.min, max: e.max, onOutOfRange })
|
|
41
90
|
: core.float({ pattern: /./, min: e.min, max: e.max, onOutOfRange });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spyglassmc/nbt",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/SpyglassMC/Spyglass/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@spyglassmc/core": "0.4.
|
|
29
|
-
"@spyglassmc/locales": "0.3.
|
|
30
|
-
"@spyglassmc/mcdoc": "0.3.
|
|
28
|
+
"@spyglassmc/core": "0.4.1",
|
|
29
|
+
"@spyglassmc/locales": "0.3.1",
|
|
30
|
+
"@spyglassmc/mcdoc": "0.3.2"
|
|
31
31
|
}
|
|
32
32
|
}
|