@spyglassmc/java-edition 0.3.7 → 0.3.9
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/binder/index.d.ts +11 -9
- package/lib/binder/index.js +149 -150
- package/lib/common/index.js +6 -9
- package/lib/dependency/common.d.ts +5 -0
- package/lib/dependency/common.js +8 -0
- package/lib/dependency/index.js +7 -17
- package/lib/dependency/mcmeta.d.ts +6 -12
- package/lib/dependency/mcmeta.js +21 -38
- package/lib/index.d.ts +1 -0
- package/lib/index.js +74 -32
- package/lib/json/checker/index.d.ts +3 -10
- package/lib/json/checker/index.js +36 -244
- package/lib/json/index.d.ts +0 -1
- package/lib/json/index.js +0 -3
- package/lib/mcfunction/checker/index.d.ts +0 -2
- package/lib/mcfunction/checker/index.js +254 -183
- package/lib/mcfunction/common/index.d.ts +4 -2
- package/lib/mcfunction/common/index.js +56 -52
- package/lib/mcfunction/completer/argument.js +112 -57
- package/lib/mcfunction/index.d.ts +3 -2
- package/lib/mcfunction/index.js +18 -19
- package/lib/mcfunction/inlayHintProvider.js +2 -3
- package/lib/mcfunction/mcdocAttributes.d.ts +4 -0
- package/lib/mcfunction/mcdocAttributes.js +71 -0
- package/lib/mcfunction/node/argument.d.ts +115 -12
- package/lib/mcfunction/node/argument.js +131 -63
- package/lib/mcfunction/parser/argument.d.ts +14 -4
- package/lib/mcfunction/parser/argument.js +380 -212
- package/lib/mcfunction/signatureHelpProvider.d.ts +2 -1
- package/lib/mcfunction/signatureHelpProvider.js +10 -18
- package/lib/mcfunction/tree/argument.d.ts +68 -1
- package/lib/mcfunction/tree/patch.js +279 -77
- package/lib/mcfunction/tree/patchValidator.d.ts +7 -0
- package/lib/mcfunction/tree/patchValidator.js +25 -0
- package/package.json +8 -9
|
@@ -3,236 +3,300 @@ import * as json from '@spyglassmc/json';
|
|
|
3
3
|
import { localize } from '@spyglassmc/locales';
|
|
4
4
|
import * as mcf from '@spyglassmc/mcfunction';
|
|
5
5
|
import * as nbt from '@spyglassmc/nbt';
|
|
6
|
+
import { dissectUri, reportDissectError } from '../../binder/index.js';
|
|
6
7
|
import { getTagValues } from '../../common/index.js';
|
|
7
|
-
import {
|
|
8
|
+
import { ReleaseVersion } from '../../dependency/common.js';
|
|
9
|
+
import { BlockNode, ComponentTestExactNode, ComponentTestExistsNode, ComponentTestSubpredicateNode, EntityNode, ItemPredicateNode, ItemStackNode, NbtNode, NbtPathNode, NbtResourceNode, ParticleNode, } from '../node/index.js';
|
|
10
|
+
const entry = (node, ctx) => {
|
|
11
|
+
const parts = dissectUri(ctx.doc.uri, ctx);
|
|
12
|
+
if (parts?.ok === false) {
|
|
13
|
+
reportDissectError(parts.path, parts.expected, ctx);
|
|
14
|
+
}
|
|
15
|
+
core.checker.dispatchSync(node, ctx);
|
|
16
|
+
};
|
|
8
17
|
export const command = (node, ctx) => {
|
|
9
18
|
if (node.slash && node.parent && mcf.McfunctionNode.is(node.parent)) {
|
|
10
19
|
ctx.err.report(localize('unexpected-leading-slash'), node.slash);
|
|
11
20
|
}
|
|
12
21
|
rootCommand(node.children, 0, ctx);
|
|
13
22
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
function getEarlierNode(nodes, before, name) {
|
|
24
|
+
if (name === undefined) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
for (let i = before - 1; i > 0; i -= 1) {
|
|
28
|
+
if (nodes[i].path[nodes[i].path.length - 1] === name) {
|
|
29
|
+
return nodes[i].children[0];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
20
34
|
const rootCommand = (nodes, index, ctx) => {
|
|
21
|
-
for (
|
|
35
|
+
for (let i = 0; i < nodes.length; i += 1) {
|
|
36
|
+
const node = nodes[i].children[0];
|
|
22
37
|
if (BlockNode.is(node)) {
|
|
23
38
|
block(node, ctx);
|
|
24
39
|
}
|
|
25
40
|
else if (EntityNode.is(node)) {
|
|
26
41
|
entity(node, ctx);
|
|
27
42
|
}
|
|
28
|
-
else if (
|
|
29
|
-
|
|
43
|
+
else if (ItemPredicateNode.is(node)) {
|
|
44
|
+
itemPredicate(node, ctx);
|
|
45
|
+
}
|
|
46
|
+
else if (ItemStackNode.is(node)) {
|
|
47
|
+
itemStack(node, ctx);
|
|
30
48
|
}
|
|
31
49
|
else if (ParticleNode.is(node)) {
|
|
32
50
|
particle(node, ctx);
|
|
33
51
|
}
|
|
34
|
-
else if (
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (getName(nodes, index) === 'data') {
|
|
39
|
-
if (getName(nodes, index + 1) === 'get') {
|
|
40
|
-
nbtPath(nodes, index + 2, ctx);
|
|
41
|
-
}
|
|
42
|
-
else if (getName(nodes, index + 1) === 'merge') {
|
|
43
|
-
dataMergeTarget(nodes, index + 2, ctx);
|
|
52
|
+
else if (NbtResourceNode.is(node)) {
|
|
53
|
+
nbtResource(node, ctx);
|
|
44
54
|
}
|
|
45
|
-
else if (
|
|
46
|
-
|
|
47
|
-
const targetPath = getNode(nodes, index + 4);
|
|
48
|
-
// if (nbt.NbtPathNode.is(targetPath)) {
|
|
49
|
-
// const operationNode = getNode(nodes, index + 5)
|
|
50
|
-
// const operation = getName(nodes, index + 5) as 'append' | 'insert' | 'merge' | 'prepend' | 'set' | undefined
|
|
51
|
-
// const sourceTypeIndex = operation === 'insert' ? index + 7 : index + 6
|
|
52
|
-
// let targetMcdocType: mcdoc.McdocType | undefined = targetPath.targetType ? mcdoc.simplifyType(targetPath.targetType) : undefined
|
|
53
|
-
// const isType = (type: mcdoc.McdocType['kind']) => !targetMcdocType || targetMcdocType.kind === type || (targetMcdocType.type === 'union' && targetMcdocType.members.some(m => m.type === type))
|
|
54
|
-
// if (operation === 'merge') {
|
|
55
|
-
// if (!(isType('compound') || isType('index'))) {
|
|
56
|
-
// ctx.err.report(
|
|
57
|
-
// localize('mcfunction.checker.command.data-modify-unapplicable-operation', localeQuote(operation), localize('nbt.node.compound'), localeQuote(mcdoc.McdocType.toString(targetMcdocType))),
|
|
58
|
-
// core.Range.span(targetPath, operationNode!),
|
|
59
|
-
// core.ErrorSeverity.Warning
|
|
60
|
-
// )
|
|
61
|
-
// targetMcdocType = undefined
|
|
62
|
-
// }
|
|
63
|
-
// } else if (operation === 'append' || operation === 'insert' || operation === 'prepend') {
|
|
64
|
-
// if (isType('list') || isType('byte_array') || isType('int_array') || isType('long_array')) {
|
|
65
|
-
// if (targetMcdocType?.type === 'list') {
|
|
66
|
-
// targetMcdocType = targetMcdocType.item
|
|
67
|
-
// } else if (targetMcdocType?.type === 'byte_array') {
|
|
68
|
-
// targetMcdocType = { type: 'byte', valueRange: targetMcdocType.valueRange }
|
|
69
|
-
// } else if (targetMcdocType?.type === 'int_array') {
|
|
70
|
-
// targetMcdocType = { type: 'int', valueRange: targetMcdocType.valueRange }
|
|
71
|
-
// } else if (targetMcdocType?.type === 'long_array') {
|
|
72
|
-
// targetMcdocType = { type: 'long', valueRange: targetMcdocType.valueRange }
|
|
73
|
-
// }
|
|
74
|
-
// } else {
|
|
75
|
-
// ctx.err.report(
|
|
76
|
-
// localize('mcfunction.checker.command.data-modify-unapplicable-operation', localeQuote(operation), localize('nbt.node.list'), localeQuote(mcdoc.McdocType.toString(targetMcdocType))),
|
|
77
|
-
// core.Range.span(targetPath, operationNode!),
|
|
78
|
-
// core.ErrorSeverity.Warning
|
|
79
|
-
// )
|
|
80
|
-
// targetMcdocType = undefined
|
|
81
|
-
// }
|
|
82
|
-
// }
|
|
83
|
-
// if (targetMcdocType) {
|
|
84
|
-
// if (getName(nodes, sourceTypeIndex) === 'from') {
|
|
85
|
-
// // `from <$nbtPath$>`
|
|
86
|
-
// nbtPath(nodes, sourceTypeIndex + 1, ctx)
|
|
87
|
-
// const sourcePath = getNode(nodes, sourceTypeIndex + 3)
|
|
88
|
-
// if (nbt.NbtPathNode.is(sourcePath)) {
|
|
89
|
-
// const { errorMessage } = mcdoc.checkAssignability({ source: sourcePath.targetType, target: targetMcdocType })
|
|
90
|
-
// if (errorMessage) {
|
|
91
|
-
// ctx.err.report(errorMessage, core.Range.span(targetPath, sourcePath), core.ErrorSeverity.Warning)
|
|
92
|
-
// }
|
|
93
|
-
// }
|
|
94
|
-
// } else if (getName(nodes, sourceTypeIndex) === 'value') {
|
|
95
|
-
// // `value <value: nbt_tag>`
|
|
96
|
-
// const valueNode = getNode(nodes, sourceTypeIndex + 1)
|
|
97
|
-
// if (nbt.NbtNode.is(valueNode)) {
|
|
98
|
-
// nbt.checker.fieldValue(targetMcdocType, { allowUnknownKey: true })(valueNode, ctx)
|
|
99
|
-
// }
|
|
100
|
-
// }
|
|
101
|
-
// }
|
|
102
|
-
// }
|
|
55
|
+
else if (json.TypedJsonNode.is(node)) {
|
|
56
|
+
json.checker.typed(node, ctx);
|
|
103
57
|
}
|
|
104
|
-
else if (
|
|
105
|
-
|
|
58
|
+
else if (NbtNode.is(node) && node.properties) {
|
|
59
|
+
const dispatchedBy = getEarlierNode(nodes, i, node.properties.dispatchedBy);
|
|
60
|
+
const indexedBy = getEarlierNode(nodes, i, node.properties.indexedBy);
|
|
61
|
+
nbtChecker(dispatchedBy, indexedBy)(node, ctx);
|
|
106
62
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if ((getName(nodes, i) === 'if' || getName(nodes, i) === 'unless') &&
|
|
111
|
-
getName(nodes, i + 1) === 'data') {
|
|
112
|
-
// `if|unless data <$nbtPath$>`
|
|
113
|
-
nbtPath(nodes, i + 2, ctx);
|
|
114
|
-
i += 2;
|
|
115
|
-
}
|
|
116
|
-
else if (getName(nodes, i) === 'run') {
|
|
117
|
-
rootCommand(nodes, i + 1, ctx);
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
63
|
+
else if (NbtPathNode.is(node) && node.properties) {
|
|
64
|
+
const dispatchedBy = getEarlierNode(nodes, i, node.properties.dispatchedBy);
|
|
65
|
+
nbtPathChecker(dispatchedBy)(node, ctx);
|
|
120
66
|
}
|
|
121
67
|
}
|
|
122
|
-
else if (getName(nodes, index) === 'summon') {
|
|
123
|
-
summonNbt(nodes, index + 1, ctx);
|
|
124
|
-
}
|
|
125
68
|
};
|
|
126
69
|
// #region Checkers for argument nodes
|
|
127
70
|
const block = (node, ctx) => {
|
|
128
71
|
if (!node.nbt) {
|
|
129
72
|
return;
|
|
130
73
|
}
|
|
131
|
-
|
|
74
|
+
const type = core.ResourceLocationNode.toString(node.id, 'full');
|
|
75
|
+
nbt.checker.index('minecraft:block', type, { isPredicate: node.isPredicate })(node.nbt, ctx);
|
|
132
76
|
};
|
|
133
77
|
const entity = (node, ctx) => {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
78
|
+
for (const pair of node.selector?.arguments?.children ?? []) {
|
|
79
|
+
if (pair.key?.value !== 'nbt' || !pair.value) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const types = getTypesFromEntity(node, ctx);
|
|
83
|
+
if (!nbt.NbtCompoundNode.is(pair.value.value)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
nbt.checker.index('minecraft:entity', types, { isPredicate: true })(pair.value.value, ctx);
|
|
137
87
|
}
|
|
138
|
-
const types = getTypesFromEntity(node, ctx);
|
|
139
|
-
const nbtValue = nbtPair.value;
|
|
140
|
-
nbt.checker.index('entity_type', types)(nbtValue, ctx);
|
|
141
88
|
};
|
|
142
|
-
const
|
|
143
|
-
if (
|
|
89
|
+
const itemPredicate = (node, ctx) => {
|
|
90
|
+
if (node.nbt) {
|
|
91
|
+
const type = core.ResourceLocationNode.toString(node.id, 'full');
|
|
92
|
+
nbt.checker.index('minecraft:item', type, { isPredicate: true })(node.nbt, ctx);
|
|
93
|
+
}
|
|
94
|
+
if (!node.tests?.children) {
|
|
144
95
|
return;
|
|
145
96
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
97
|
+
const anyOfTest = node.tests.children[0];
|
|
98
|
+
for (const allOfTest of anyOfTest.children) {
|
|
99
|
+
for (const test of allOfTest.children) {
|
|
100
|
+
const key = core.ResourceLocationNode.toString(test.key, 'full');
|
|
101
|
+
// count is a special case that's only valid in item predicate arguments, not json
|
|
102
|
+
// note: basically all errors checked here are otherwise accepted by vanilla, but it's good to report them
|
|
103
|
+
if (key === 'minecraft:count' && !ComponentTestExistsNode.is(test) && test.value) {
|
|
104
|
+
const validInt = { kind: 'int', valueRange: { kind: 0b00, min: 0 } };
|
|
105
|
+
const type = {
|
|
106
|
+
kind: 'union',
|
|
107
|
+
members: [
|
|
108
|
+
validInt,
|
|
109
|
+
{
|
|
110
|
+
kind: 'struct',
|
|
111
|
+
fields: [
|
|
112
|
+
{ kind: 'pair', key: 'min', optional: true, type: validInt },
|
|
113
|
+
{ kind: 'pair', key: 'max', optional: true, type: validInt },
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
nbt.checker.typeDefinition(type)(test.value, ctx);
|
|
165
119
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
case 'entity': {
|
|
169
|
-
const entityNode = getNode(nodes, index + 1);
|
|
170
|
-
const nbtNode = getNode(nodes, index + 2);
|
|
171
|
-
if (EntityNode.is(entityNode) && nbt.NbtCompoundNode.is(nbtNode)) {
|
|
172
|
-
const types = getTypesFromEntity(entityNode, ctx);
|
|
173
|
-
nbt.checker.index('entity_type', types)(nbtNode, ctx);
|
|
120
|
+
else if (ComponentTestExactNode.is(test) && test.value) {
|
|
121
|
+
nbt.checker.index('minecraft:data_component', key)(test.value, ctx);
|
|
174
122
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
case 'storage': {
|
|
178
|
-
const idNode = getNode(nodes, index + 1);
|
|
179
|
-
const nbtNode = getNode(nodes, index + 2);
|
|
180
|
-
if (core.ResourceLocationNode.is(idNode) &&
|
|
181
|
-
nbt.NbtCompoundNode.is(nbtNode)) {
|
|
182
|
-
nbt.checker.index('storage', core.ResourceLocationNode.toString(idNode, 'full'))(nbtNode, ctx);
|
|
123
|
+
else if (ComponentTestSubpredicateNode.is(test) && test.value) {
|
|
124
|
+
nbt.checker.index('minecraft:item_sub_predicate', key)(test.value, ctx);
|
|
183
125
|
}
|
|
184
|
-
break;
|
|
185
126
|
}
|
|
186
127
|
}
|
|
187
128
|
};
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
129
|
+
const itemStack = (node, ctx) => {
|
|
130
|
+
const itemId = core.ResourceLocationNode.toString(node.id, 'full');
|
|
131
|
+
if (node.nbt) {
|
|
132
|
+
nbt.checker.index('minecraft:item', itemId)(node.nbt, ctx);
|
|
133
|
+
}
|
|
134
|
+
if (!node.components) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const groupedComponents = new Map();
|
|
138
|
+
for (const pair of node.components.children) {
|
|
139
|
+
if (!pair.key) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const componentId = core.ResourceLocationNode.toString(pair.key, 'full');
|
|
143
|
+
if (!groupedComponents.has(componentId)) {
|
|
144
|
+
groupedComponents.set(componentId, []);
|
|
145
|
+
}
|
|
146
|
+
groupedComponents.get(componentId).push(pair.key);
|
|
147
|
+
if (pair.value) {
|
|
148
|
+
nbt.checker.index('minecraft:data_component', componentId)(pair.value, ctx);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const [_, group] of groupedComponents) {
|
|
152
|
+
if (group.length > 1) {
|
|
153
|
+
for (const node of group) {
|
|
154
|
+
ctx.err.report(localize('mcfunction.parser.duplicate-components'), node.range, 2 /* core.ErrorSeverity.Warning */);
|
|
200
155
|
}
|
|
201
|
-
break;
|
|
202
156
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const nbtResource = (node, ctx) => {
|
|
160
|
+
const type = {
|
|
161
|
+
kind: 'dispatcher',
|
|
162
|
+
registry: 'minecraft:resource',
|
|
163
|
+
parallelIndices: [{ kind: 'static', value: core.ResourceLocation.lengthen(node.category) }],
|
|
164
|
+
};
|
|
165
|
+
nbt.checker.typeDefinition(type)(node.children[0], ctx);
|
|
166
|
+
};
|
|
167
|
+
function nbtChecker(dispatchedBy, indexedBy) {
|
|
168
|
+
return (node, ctx) => {
|
|
169
|
+
if (!node.properties) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const tag = node.children[0];
|
|
173
|
+
if (indexedBy) {
|
|
174
|
+
if (NbtPathNode.is(indexedBy)) {
|
|
175
|
+
const indexedByTypedef = indexedBy.children[0].endTypeDef;
|
|
176
|
+
const typeDef = indexedByTypedef && node.properties.isListIndex
|
|
177
|
+
? getListLikeChild(indexedByTypedef)
|
|
178
|
+
: indexedByTypedef;
|
|
179
|
+
if (typeDef) {
|
|
180
|
+
nbt.checker.typeDefinition(typeDef, node.properties)(tag, ctx);
|
|
181
|
+
}
|
|
209
182
|
}
|
|
210
|
-
|
|
183
|
+
return;
|
|
211
184
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
185
|
+
switch (node.properties.dispatcher) {
|
|
186
|
+
case 'minecraft:entity':
|
|
187
|
+
if (nbt.NbtCompoundNode.is(tag)) {
|
|
188
|
+
const types = (EntityNode.is(dispatchedBy) || core.ResourceLocationNode.is(dispatchedBy))
|
|
189
|
+
? getTypesFromEntity(dispatchedBy, ctx)
|
|
190
|
+
: undefined;
|
|
191
|
+
nbt.checker.index('minecraft:entity', types, {
|
|
192
|
+
isPredicate: node.properties.isPredicate,
|
|
193
|
+
isMerge: node.properties.isMerge,
|
|
194
|
+
})(tag, ctx);
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
case 'minecraft:block':
|
|
198
|
+
if (nbt.NbtCompoundNode.is(tag)) {
|
|
199
|
+
nbt.checker.index('minecraft:block', undefined, {
|
|
200
|
+
isPredicate: node.properties.isPredicate,
|
|
201
|
+
isMerge: node.properties.isMerge,
|
|
202
|
+
})(tag, ctx);
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
case 'minecraft:storage':
|
|
206
|
+
if (nbt.NbtCompoundNode.is(tag)) {
|
|
207
|
+
const storage = core.ResourceLocationNode.is(dispatchedBy)
|
|
208
|
+
? core.ResourceLocationNode.toString(dispatchedBy)
|
|
209
|
+
: undefined;
|
|
210
|
+
nbt.checker.index('minecraft:storage', storage, {
|
|
211
|
+
isPredicate: node.properties.isPredicate,
|
|
212
|
+
isMerge: node.properties.isMerge,
|
|
213
|
+
})(tag, ctx);
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function getListLikeChild(typeDef) {
|
|
220
|
+
switch (typeDef.kind) {
|
|
221
|
+
case 'list':
|
|
222
|
+
return typeDef.item;
|
|
223
|
+
case 'byte_array':
|
|
224
|
+
return { kind: 'byte' };
|
|
225
|
+
case 'int_array':
|
|
226
|
+
return { kind: 'int' };
|
|
227
|
+
case 'long_array':
|
|
228
|
+
return { kind: 'long' };
|
|
229
|
+
case 'union':
|
|
230
|
+
const members = typeDef.members
|
|
231
|
+
.map(m => getListLikeChild(m))
|
|
232
|
+
.filter((m) => m !== undefined);
|
|
233
|
+
if (members.length === 0) {
|
|
234
|
+
return undefined;
|
|
217
235
|
}
|
|
218
|
-
|
|
236
|
+
if (members.length === 1) {
|
|
237
|
+
return members[0];
|
|
238
|
+
}
|
|
239
|
+
return { kind: 'union', members };
|
|
240
|
+
default:
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function nbtPathChecker(dispatchedBy) {
|
|
245
|
+
return (node, ctx) => {
|
|
246
|
+
if (!node.properties) {
|
|
247
|
+
return;
|
|
219
248
|
}
|
|
249
|
+
const path = node.children[0];
|
|
250
|
+
switch (node.properties.dispatcher) {
|
|
251
|
+
case 'minecraft:entity':
|
|
252
|
+
const types = (EntityNode.is(dispatchedBy) || core.ResourceLocationNode.is(dispatchedBy))
|
|
253
|
+
? getTypesFromEntity(dispatchedBy, ctx)
|
|
254
|
+
: undefined;
|
|
255
|
+
nbt.checker.path('minecraft:entity', types)(path, ctx);
|
|
256
|
+
break;
|
|
257
|
+
case 'minecraft:block':
|
|
258
|
+
nbt.checker.path('minecraft:block', undefined)(path, ctx);
|
|
259
|
+
break;
|
|
260
|
+
case 'minecraft:storage':
|
|
261
|
+
const storage = core.ResourceLocationNode.is(dispatchedBy)
|
|
262
|
+
? core.ResourceLocationNode.toString(dispatchedBy)
|
|
263
|
+
: undefined;
|
|
264
|
+
nbt.checker.path('minecraft:storage', storage)(path, ctx);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
const particle = (node, ctx) => {
|
|
270
|
+
const id = core.ResourceLocationNode.toString(node.id, 'short');
|
|
271
|
+
const release = ctx.project['loadedVersion'];
|
|
272
|
+
if (release && ReleaseVersion.cmp(release, '1.20.5') < 0) {
|
|
273
|
+
return;
|
|
220
274
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
275
|
+
const options = node.children?.find(nbt.NbtCompoundNode.is);
|
|
276
|
+
if (ParticleNode.requiresOptions(id)) {
|
|
277
|
+
if (options) {
|
|
278
|
+
nbt.checker.index('minecraft:particle', core.ResourceLocation.lengthen(id))(options, ctx);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
ctx.err.report(localize('expected', localize('nbt.node.compound')), core.Range.create(node.id.range.end, node.id.range.end + 1));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else if (options) {
|
|
285
|
+
ctx.err.report(localize('expected', localize('nothing')), options);
|
|
231
286
|
}
|
|
232
287
|
};
|
|
233
288
|
// #endregion
|
|
234
|
-
|
|
235
|
-
if (
|
|
289
|
+
function getTypesFromEntity(entity, ctx) {
|
|
290
|
+
if (core.ResourceLocationNode.is(entity)) {
|
|
291
|
+
const value = core.ResourceLocationNode.toString(entity, 'full', true);
|
|
292
|
+
if (value.startsWith(core.ResourceLocation.TagPrefix)) {
|
|
293
|
+
return getTagValues('tag/entity_type', value.slice(1), ctx);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
return [value];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else if (entity.playerName !== undefined || entity.selector?.playersOnly) {
|
|
236
300
|
return ['minecraft:player'];
|
|
237
301
|
}
|
|
238
302
|
else if (entity.selector) {
|
|
@@ -240,7 +304,7 @@ export const getTypesFromEntity = (entity, ctx) => {
|
|
|
240
304
|
if (!argumentsNode) {
|
|
241
305
|
return undefined;
|
|
242
306
|
}
|
|
243
|
-
let types =
|
|
307
|
+
let types = undefined;
|
|
244
308
|
for (const pairNode of argumentsNode.children) {
|
|
245
309
|
if (pairNode.key?.value !== 'type') {
|
|
246
310
|
continue;
|
|
@@ -252,7 +316,12 @@ export const getTypesFromEntity = (entity, ctx) => {
|
|
|
252
316
|
const value = core.ResourceLocationNode.toString(valueNode.value, 'full', true);
|
|
253
317
|
if (value.startsWith(core.ResourceLocation.TagPrefix)) {
|
|
254
318
|
const tagValues = getTagValues('tag/entity_type', value.slice(1), ctx);
|
|
255
|
-
types
|
|
319
|
+
if (types === undefined) {
|
|
320
|
+
types = tagValues.map(core.ResourceLocation.lengthen);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
types = types.filter((t) => tagValues.includes(t));
|
|
324
|
+
}
|
|
256
325
|
}
|
|
257
326
|
else {
|
|
258
327
|
types = [value];
|
|
@@ -261,12 +330,14 @@ export const getTypesFromEntity = (entity, ctx) => {
|
|
|
261
330
|
return types;
|
|
262
331
|
}
|
|
263
332
|
return undefined;
|
|
264
|
-
}
|
|
333
|
+
}
|
|
265
334
|
export function register(meta) {
|
|
335
|
+
meta.registerChecker('mcfunction:entry', entry);
|
|
266
336
|
meta.registerChecker('mcfunction:command', command);
|
|
267
337
|
meta.registerChecker('mcfunction:block', block);
|
|
268
338
|
meta.registerChecker('mcfunction:entity', entity);
|
|
269
|
-
meta.registerChecker('mcfunction:
|
|
339
|
+
meta.registerChecker('mcfunction:item_stack', itemStack);
|
|
340
|
+
meta.registerChecker('mcfunction:item_predicate', itemPredicate);
|
|
270
341
|
meta.registerChecker('mcfunction:particle', particle);
|
|
271
342
|
}
|
|
272
343
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
1
2
|
export declare const ColorArgumentValues: string[];
|
|
2
3
|
export declare const EntityAnchorArgumentValues: string[];
|
|
3
4
|
export declare const GamemodeArgumentValues: string[];
|
|
4
|
-
export declare
|
|
5
|
+
export declare function getItemSlotArgumentValues(ctx: core.ContextBase): string[];
|
|
6
|
+
export declare function getItemSlotsArgumentValues(ctx: core.ContextBase): string[];
|
|
5
7
|
export declare const OperationArgumentValues: string[];
|
|
6
|
-
export declare
|
|
8
|
+
export declare function getScoreboardSlotArgumentValues(ctx: core.ContextBase): string[];
|
|
7
9
|
export declare const SwizzleArgumentValues: string[];
|
|
8
10
|
export declare const HeightmapValues: string[];
|
|
9
11
|
export declare const RotationValues: string[];
|
|
@@ -1,47 +1,60 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
|
+
import { ReleaseVersion } from '../../dependency/index.js';
|
|
2
3
|
export const ColorArgumentValues = [...core.Color.ColorNames, 'reset'];
|
|
3
4
|
export const EntityAnchorArgumentValues = ['feet', 'eyes'];
|
|
4
|
-
export const GamemodeArgumentValues = [
|
|
5
|
-
|
|
6
|
-
'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
5
|
+
export const GamemodeArgumentValues = ['adventure', 'survival', 'creative', 'spectator'];
|
|
6
|
+
export function getItemSlotArgumentValues(ctx) {
|
|
7
|
+
const release = ctx.project['loadedVersion'];
|
|
8
|
+
const output = [
|
|
9
|
+
...[...Array(54).keys()].map((n) => `container.${n}`),
|
|
10
|
+
...[...Array(27).keys()].map((n) => `enderchest.${n}`),
|
|
11
|
+
...[...Array(15).keys()].map((n) => `horse.${n}`),
|
|
12
|
+
...[...Array(9).keys()].map((n) => `hotbar.${n}`),
|
|
13
|
+
...[...Array(27).keys()].map((n) => `inventory.${n}`),
|
|
14
|
+
...[...Array(8).keys()].map((n) => `villager.${n}`),
|
|
15
|
+
'armor.chest',
|
|
16
|
+
'armor.feet',
|
|
17
|
+
'armor.head',
|
|
18
|
+
'armor.legs',
|
|
19
|
+
'horse.chest',
|
|
20
|
+
'horse.saddle',
|
|
21
|
+
'weapon',
|
|
22
|
+
'weapon.mainhand',
|
|
23
|
+
'weapon.offhand',
|
|
24
|
+
];
|
|
25
|
+
if (ReleaseVersion.cmp(release, '1.20.5') >= 0) {
|
|
26
|
+
output.push(...[...Array(4).keys()].map((n) => `player.crafting.${n}`), 'armor.body', 'contents', 'player.cursor');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
output.push('horse.armor');
|
|
30
|
+
}
|
|
31
|
+
return output;
|
|
32
|
+
}
|
|
33
|
+
// Only exists since 1.20.5
|
|
34
|
+
export function getItemSlotsArgumentValues(ctx) {
|
|
35
|
+
return [
|
|
36
|
+
...getItemSlotArgumentValues(ctx),
|
|
37
|
+
'armor.*',
|
|
38
|
+
'container.*',
|
|
39
|
+
'enderchest.*',
|
|
40
|
+
'horse.*',
|
|
41
|
+
'hotbar.*',
|
|
42
|
+
'inventory.*',
|
|
43
|
+
'player.crafting.*',
|
|
44
|
+
'villager.*',
|
|
45
|
+
'weapon.*',
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
export const OperationArgumentValues = ['=', '+=', '-=', '*=', '/=', '%=', '<', '>', '><'];
|
|
49
|
+
export function getScoreboardSlotArgumentValues(ctx) {
|
|
50
|
+
const release = ctx.project['loadedVersion'];
|
|
51
|
+
return [
|
|
52
|
+
ReleaseVersion.cmp(release, '1.20.2') < 0 ? 'belowName' : 'below_name',
|
|
53
|
+
'list',
|
|
54
|
+
'sidebar',
|
|
55
|
+
...core.Color.ColorNames.map((n) => `sidebar.team.${n}`),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
45
58
|
export const SwizzleArgumentValues = [
|
|
46
59
|
'x',
|
|
47
60
|
'xy',
|
|
@@ -67,15 +80,6 @@ export const HeightmapValues = [
|
|
|
67
80
|
'world_surface',
|
|
68
81
|
'world_surface_wg',
|
|
69
82
|
];
|
|
70
|
-
export const RotationValues = [
|
|
71
|
-
|
|
72
|
-
'clockwise_90',
|
|
73
|
-
'180',
|
|
74
|
-
'counterclockwise_90',
|
|
75
|
-
];
|
|
76
|
-
export const MirrorValues = [
|
|
77
|
-
'none',
|
|
78
|
-
'left_right',
|
|
79
|
-
'front_back',
|
|
80
|
-
];
|
|
83
|
+
export const RotationValues = ['none', 'clockwise_90', '180', 'counterclockwise_90'];
|
|
84
|
+
export const MirrorValues = ['none', 'left_right', 'front_back'];
|
|
81
85
|
//# sourceMappingURL=index.js.map
|