@spyglassmc/java-edition 0.3.18 → 0.3.19
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 +2 -1
- package/lib/binder/index.js +63 -26
- package/lib/dependency/common.d.ts +10 -0
- package/lib/dependency/common.js +7 -0
- package/lib/dependency/index.d.ts +8 -0
- package/lib/dependency/index.js +23 -2
- package/lib/dependency/mcmeta.d.ts +4 -2
- package/lib/dependency/mcmeta.js +80 -19
- package/lib/index.js +50 -80
- package/lib/mcdocAttributes.d.ts +6 -0
- package/lib/mcdocAttributes.js +89 -0
- package/lib/mcfunction/checker/index.js +6 -6
- package/lib/mcfunction/completer/argument.js +27 -14
- package/lib/mcfunction/mcdocAttributes.js +1 -1
- package/lib/mcfunction/node/argument.d.ts +23 -4
- package/lib/mcfunction/node/argument.js +14 -0
- package/lib/mcfunction/parser/argument.js +77 -18
- package/lib/mcfunction/tree/patch.js +31 -4
- package/package.json +7 -7
package/lib/binder/index.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ export declare function dissectUri(uri: string, ctx: UriBinderContext): {
|
|
|
5
5
|
identifier: string;
|
|
6
6
|
expected: string | undefined;
|
|
7
7
|
path: string;
|
|
8
|
-
category: "function" | "advancement" | "banner_pattern" | "chat_type" | "damage_type" | "dimension" | "dimension_type" | "enchantment" | "enchantment_provider" | "instrument" | "item_modifier" | "jukebox_song" | "loot_table" | "painting_variant" | "predicate" | "recipe" | "structure" | "trial_spawner" | "trim_material" | "trim_pattern" | "wolf_variant" | "tag/function" | "tag/activity" | "tag/armor_material" | "tag/attribute" | "tag/block" | "tag/block_entity_type" | "tag/block_predicate_type" | "tag/block_type" | "tag/cat_variant" | "tag/chunk_status" | "tag/command_argument_type" | "tag/creative_mode_tab" | "tag/custom_stat" | "tag/data_component_type" | "tag/decorated_pot_pattern" | "tag/enchantment_effect_component_type" | "tag/enchantment_entity_effect_type" | "tag/enchantment_level_based_value_type" | "tag/enchantment_location_based_effect_type" | "tag/enchantment_provider_type" | "tag/enchantment_value_effect_type" | "tag/entity_sub_predicate_type" | "tag/entity_type" | "tag/float_provider_type" | "tag/fluid" | "tag/frog_variant" | "tag/game_event" | "tag/height_provider_type" | "tag/instrument" | "tag/int_provider_type" | "tag/item" | "tag/item_sub_predicate_type" | "tag/loot_condition_type" | "tag/loot_function_type" | "tag/loot_nbt_provider_type" | "tag/loot_number_provider_type" | "tag/loot_pool_entry_type" | "tag/loot_score_provider_type" | "tag/map_decoration_type" | "tag/memory_module_type" | "tag/menu" | "tag/mob_effect" | "tag/motive" | "tag/number_format_type" | "tag/particle_type" | "tag/point_of_interest_type" | "tag/pos_rule_test" | "tag/position_source_type" | "tag/potion" | "tag/recipe_serializer" | "tag/recipe_type" | "tag/rule_block_entity_modifier" | "tag/rule_test" | "tag/schedule" | "tag/sensor_type" | "tag/sound_event" | "tag/stat_type" | "tag/trigger_type" | "tag/villager_profession" | "tag/villager_type" | "tag/worldgen/biome_source" | "tag/worldgen/block_placer_type" | "tag/worldgen/block_state_provider_type" | "tag/worldgen/carver" | "tag/worldgen/chunk_generator" | "tag/worldgen/decorator" | "tag/worldgen/density_function_type" | "tag/worldgen/feature" | "tag/worldgen/feature_size_type" | "tag/worldgen/foliage_placer_type" | "tag/worldgen/material_condition" | "tag/worldgen/material_rule" | "tag/worldgen/placement_modifier_type" | "tag/worldgen/pool_alias_binding" | "tag/worldgen/root_placer_type" | "tag/worldgen/structure_feature" | "tag/worldgen/structure_piece" | "tag/worldgen/structure_placement" | "tag/worldgen/structure_pool_element" | "tag/worldgen/structure_processor" | "tag/worldgen/structure_type" | "tag/worldgen/surface_builder" | "tag/worldgen/tree_decorator_type" | "tag/worldgen/trunk_placer_type" | "tag/advancement" | "tag/banner_pattern" | "tag/chat_type" | "tag/damage_type" | "tag/dimension" | "tag/dimension_type" | "tag/enchantment" | "tag/enchantment_provider" | "tag/item_modifier" | "tag/jukebox_song" | "tag/loot_table" | "tag/painting_variant" | "tag/predicate" | "tag/recipe" | "tag/structure" | "tag/trial_spawner" | "tag/trim_material" | "tag/trim_pattern" | "tag/wolf_variant" | "tag/worldgen/biome" | "tag/worldgen/configured_carver" | "tag/worldgen/configured_feature" | "tag/worldgen/configured_structure_feature" | "tag/worldgen/configured_surface_builder" | "tag/worldgen/density_function" | "tag/worldgen/flat_level_generator_preset" | "tag/worldgen/multi_noise_biome_source_parameter_list" | "tag/worldgen/noise" | "tag/worldgen/noise_settings" | "tag/worldgen/placed_feature" | "tag/worldgen/processor_list" | "tag/worldgen/structure" | "tag/worldgen/structure_set" | "tag/worldgen/template_pool" | "tag/worldgen/world_preset" | "worldgen/biome" | "worldgen/configured_carver" | "worldgen/configured_feature" | "worldgen/configured_structure_feature" | "worldgen/configured_surface_builder" | "worldgen/density_function" | "worldgen/flat_level_generator_preset" | "worldgen/multi_noise_biome_source_parameter_list" | "worldgen/noise" | "worldgen/noise_settings" | "worldgen/placed_feature" | "worldgen/processor_list" | "worldgen/structure" | "worldgen/structure_set" | "worldgen/template_pool" | "worldgen/world_preset";
|
|
8
|
+
category: "function" | "advancement" | "banner_pattern" | "chat_type" | "damage_type" | "dimension" | "dimension_type" | "enchantment" | "enchantment_provider" | "instrument" | "item_modifier" | "jukebox_song" | "loot_table" | "painting_variant" | "predicate" | "recipe" | "structure" | "trial_spawner" | "trim_material" | "trim_pattern" | "wolf_variant" | "tag/function" | "tag/activity" | "tag/armor_material" | "tag/attribute" | "tag/block" | "tag/block_entity_type" | "tag/block_predicate_type" | "tag/block_type" | "tag/cat_variant" | "tag/chunk_status" | "tag/command_argument_type" | "tag/consume_effect_type" | "tag/creative_mode_tab" | "tag/custom_stat" | "tag/data_component_type" | "tag/decorated_pot_pattern" | "tag/decorated_pot_patterns" | "tag/enchantment_effect_component_type" | "tag/enchantment_entity_effect_type" | "tag/enchantment_level_based_value_type" | "tag/enchantment_location_based_effect_type" | "tag/enchantment_provider_type" | "tag/enchantment_value_effect_type" | "tag/entity_sub_predicate_type" | "tag/entity_type" | "tag/float_provider_type" | "tag/fluid" | "tag/frog_variant" | "tag/game_event" | "tag/height_provider_type" | "tag/instrument" | "tag/int_provider_type" | "tag/item" | "tag/item_sub_predicate_type" | "tag/loot_condition_type" | "tag/loot_function_type" | "tag/loot_nbt_provider_type" | "tag/loot_number_provider_type" | "tag/loot_pool_entry_type" | "tag/loot_score_provider_type" | "tag/map_decoration_type" | "tag/memory_module_type" | "tag/menu" | "tag/mob_effect" | "tag/motive" | "tag/number_format_type" | "tag/particle_type" | "tag/point_of_interest_type" | "tag/pos_rule_test" | "tag/position_source_type" | "tag/potion" | "tag/recipe_book_category" | "tag/recipe_display" | "tag/recipe_serializer" | "tag/recipe_type" | "tag/rule_block_entity_modifier" | "tag/rule_test" | "tag/schedule" | "tag/sensor_type" | "tag/slot_display" | "tag/sound_event" | "tag/stat_type" | "tag/trigger_type" | "tag/villager_profession" | "tag/villager_type" | "tag/worldgen/biome_source" | "tag/worldgen/block_placer_type" | "tag/worldgen/block_state_provider_type" | "tag/worldgen/carver" | "tag/worldgen/chunk_generator" | "tag/worldgen/decorator" | "tag/worldgen/density_function_type" | "tag/worldgen/feature" | "tag/worldgen/feature_size_type" | "tag/worldgen/foliage_placer_type" | "tag/worldgen/material_condition" | "tag/worldgen/material_rule" | "tag/worldgen/placement_modifier_type" | "tag/worldgen/pool_alias_binding" | "tag/worldgen/root_placer_type" | "tag/worldgen/structure_feature" | "tag/worldgen/structure_piece" | "tag/worldgen/structure_placement" | "tag/worldgen/structure_pool_element" | "tag/worldgen/structure_processor" | "tag/worldgen/structure_type" | "tag/worldgen/surface_builder" | "tag/worldgen/tree_decorator_type" | "tag/worldgen/trunk_placer_type" | "tag/advancement" | "tag/banner_pattern" | "tag/chat_type" | "tag/damage_type" | "tag/dimension" | "tag/dimension_type" | "tag/enchantment" | "tag/enchantment_provider" | "tag/item_modifier" | "tag/jukebox_song" | "tag/loot_table" | "tag/painting_variant" | "tag/predicate" | "tag/recipe" | "tag/structure" | "tag/trial_spawner" | "tag/trim_material" | "tag/trim_pattern" | "tag/wolf_variant" | "tag/worldgen/biome" | "tag/worldgen/configured_carver" | "tag/worldgen/configured_feature" | "tag/worldgen/configured_structure_feature" | "tag/worldgen/configured_surface_builder" | "tag/worldgen/density_function" | "tag/worldgen/flat_level_generator_preset" | "tag/worldgen/multi_noise_biome_source_parameter_list" | "tag/worldgen/noise" | "tag/worldgen/noise_settings" | "tag/worldgen/placed_feature" | "tag/worldgen/processor_list" | "tag/worldgen/structure" | "tag/worldgen/structure_set" | "tag/worldgen/template_pool" | "tag/worldgen/world_preset" | "worldgen/biome" | "worldgen/configured_carver" | "worldgen/configured_feature" | "worldgen/configured_structure_feature" | "worldgen/configured_surface_builder" | "worldgen/density_function" | "worldgen/flat_level_generator_preset" | "worldgen/multi_noise_biome_source_parameter_list" | "worldgen/noise" | "worldgen/noise_settings" | "worldgen/placed_feature" | "worldgen/processor_list" | "worldgen/structure" | "worldgen/structure_set" | "worldgen/template_pool" | "worldgen/world_preset" | "atlas" | "block_definition" | "equipment" | "font" | "font/ttf" | "font/otf" | "font/unihex" | "item_definition" | "lang" | "model" | "particle" | "post_effect" | "shader" | "shader/fragment" | "shader/vertex" | "sound" | "texture";
|
|
9
9
|
ext: `.${string}`;
|
|
10
|
+
pack: "assets" | "data";
|
|
10
11
|
since?: `1.${number}` | undefined;
|
|
11
12
|
until?: `1.${number}` | undefined;
|
|
12
13
|
ok: boolean;
|
package/lib/binder/index.js
CHANGED
|
@@ -3,12 +3,17 @@ import { localeQuote, localize } from '@spyglassmc/locales';
|
|
|
3
3
|
import { ReleaseVersion } from '../dependency/index.js';
|
|
4
4
|
const Resources = new Map();
|
|
5
5
|
function resource(path, resource = {}) {
|
|
6
|
-
Resources.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const previous = Resources.get(path) ?? [];
|
|
7
|
+
Resources.set(path, [
|
|
8
|
+
...previous,
|
|
9
|
+
{
|
|
10
|
+
path,
|
|
11
|
+
category: resource.category ?? path,
|
|
12
|
+
ext: resource.ext ?? '.json',
|
|
13
|
+
pack: resource.pack ?? 'data',
|
|
14
|
+
...resource,
|
|
15
|
+
},
|
|
16
|
+
]);
|
|
12
17
|
}
|
|
13
18
|
// Pre-1.21 data pack plurals
|
|
14
19
|
resource('advancements', { category: 'advancement', until: '1.21' });
|
|
@@ -88,11 +93,36 @@ for (const registry of TaggableResourceLocationCategories) {
|
|
|
88
93
|
}
|
|
89
94
|
resource(`tags/${registry}`, { category: `tag/${registry}`, since: '1.18' });
|
|
90
95
|
}
|
|
96
|
+
// Resource pack
|
|
97
|
+
resource('atlases', { pack: 'assets', category: 'atlas', since: '1.19.3' });
|
|
98
|
+
resource('blockstates', { pack: 'assets', category: 'block_definition' });
|
|
99
|
+
resource('equipment', { pack: 'assets', category: 'equipment', since: '1.21.4' });
|
|
100
|
+
resource('font', { pack: 'assets', category: 'font', since: '1.16' });
|
|
101
|
+
resource('font', { pack: 'assets', category: 'font/ttf', since: '1.16', ext: '.ttf' });
|
|
102
|
+
resource('font', { pack: 'assets', category: 'font/otf', since: '1.16', ext: '.otf' });
|
|
103
|
+
resource('font', { pack: 'assets', category: 'font/unihex', since: '1.20', ext: '.zip' });
|
|
104
|
+
resource('items', { pack: 'assets', category: 'item_definition', since: '1.21.4' });
|
|
105
|
+
resource('lang', { pack: 'assets', category: 'lang' });
|
|
106
|
+
resource('models', { pack: 'assets', category: 'model' });
|
|
107
|
+
resource('models/equipment', {
|
|
108
|
+
pack: 'assets',
|
|
109
|
+
category: 'equipment',
|
|
110
|
+
since: '1.21.2',
|
|
111
|
+
until: '1.21.4',
|
|
112
|
+
});
|
|
113
|
+
resource('particles', { pack: 'assets', category: 'particle' });
|
|
114
|
+
resource('post_effect', { pack: 'assets', since: '1.21.2' });
|
|
115
|
+
resource('shaders/post', { pack: 'assets', category: 'post_effect', until: '1.21.2' });
|
|
116
|
+
resource('shaders', { pack: 'assets', category: 'shader' });
|
|
117
|
+
resource('shaders', { pack: 'assets', category: 'shader/fragment', ext: '.fsh' });
|
|
118
|
+
resource('shaders', { pack: 'assets', category: 'shader/vertex', ext: '.vsh' });
|
|
119
|
+
resource('sounds', { pack: 'assets', category: 'sound', ext: '.ogg' });
|
|
120
|
+
resource('textures', { pack: 'assets', category: 'texture', ext: '.png' });
|
|
91
121
|
export function* getRels(uri, rootUris) {
|
|
92
122
|
yield* fileUtil.getRels(uri, rootUris);
|
|
93
123
|
const parts = uri.split('/');
|
|
94
124
|
for (let i = parts.length - 2; i >= 0; i--) {
|
|
95
|
-
if (parts[i] === 'data'
|
|
125
|
+
if (parts[i] === 'data' || parts[i] === 'assets') {
|
|
96
126
|
yield parts.slice(i).join('/');
|
|
97
127
|
}
|
|
98
128
|
}
|
|
@@ -110,30 +140,38 @@ export function dissectUri(uri, ctx) {
|
|
|
110
140
|
continue;
|
|
111
141
|
}
|
|
112
142
|
const [pack, namespace, ...rest] = parts;
|
|
113
|
-
if (pack !== 'data') {
|
|
114
|
-
continue;
|
|
143
|
+
if (pack !== 'data' && pack !== 'assets') {
|
|
144
|
+
continue;
|
|
115
145
|
}
|
|
116
|
-
|
|
117
|
-
let matchIndex = 0;
|
|
146
|
+
const candidateResources = [];
|
|
118
147
|
for (let i = 1; i < rest.length; i += 1) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
const resources = Resources.get(rest.slice(0, i).join('/'));
|
|
149
|
+
for (const res of resources ?? []) {
|
|
150
|
+
if (res.pack !== pack) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
let identifier = rest.slice(i).join('/');
|
|
154
|
+
if (!identifier.endsWith(res.ext)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
identifier = identifier.slice(0, -res.ext.length);
|
|
158
|
+
candidateResources.push([res, identifier]);
|
|
123
159
|
}
|
|
124
160
|
}
|
|
125
|
-
if (
|
|
161
|
+
if (candidateResources.length === 0) {
|
|
126
162
|
continue;
|
|
127
163
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
164
|
+
// Finding the last, because that will be the deepest match
|
|
165
|
+
let res = candidateResources.findLast(([res]) => matchVersion(release, res.since, res.until));
|
|
166
|
+
if (res !== undefined) {
|
|
167
|
+
return { ok: true, ...res[0], namespace, identifier: res[1], expected: undefined };
|
|
131
168
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
// Try to find the expected path that matches the current version
|
|
170
|
+
res = candidateResources[candidateResources.length - 1];
|
|
171
|
+
let expected = undefined;
|
|
172
|
+
for (const [path, others] of Resources) {
|
|
173
|
+
for (const other of others) {
|
|
174
|
+
if (other.category !== res[0].category) {
|
|
137
175
|
continue;
|
|
138
176
|
}
|
|
139
177
|
if (matchVersion(release, other.since, other.until)) {
|
|
@@ -141,9 +179,8 @@ export function dissectUri(uri, ctx) {
|
|
|
141
179
|
break;
|
|
142
180
|
}
|
|
143
181
|
}
|
|
144
|
-
return { ok: false, ...resource, namespace, identifier, expected };
|
|
145
182
|
}
|
|
146
|
-
return { ok:
|
|
183
|
+
return { ok: false, ...res[0], namespace, identifier: res[1], expected };
|
|
147
184
|
}
|
|
148
185
|
return undefined;
|
|
149
186
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type * as core from '@spyglassmc/core';
|
|
1
2
|
export type ReleaseVersion = `1.${number}`;
|
|
2
3
|
export declare namespace ReleaseVersion {
|
|
3
4
|
/**
|
|
@@ -13,11 +14,13 @@ export declare namespace ReleaseVersion {
|
|
|
13
14
|
*/
|
|
14
15
|
function isBetween(version: ReleaseVersion, since: ReleaseVersion, until: ReleaseVersion): boolean;
|
|
15
16
|
}
|
|
17
|
+
export type VersionInfoReason = 'auto' | 'config' | 'fallback';
|
|
16
18
|
export interface VersionInfo {
|
|
17
19
|
release: ReleaseVersion;
|
|
18
20
|
id: string;
|
|
19
21
|
name: string;
|
|
20
22
|
isLatest: boolean;
|
|
23
|
+
reason: VersionInfoReason;
|
|
21
24
|
}
|
|
22
25
|
export interface PackMcmeta {
|
|
23
26
|
pack: {
|
|
@@ -26,5 +29,12 @@ export interface PackMcmeta {
|
|
|
26
29
|
}
|
|
27
30
|
export declare namespace PackMcmeta {
|
|
28
31
|
function assert(data: any): asserts data is PackMcmeta;
|
|
32
|
+
function getType(packRoot: string, externals: core.Externals): Promise<"assets" | "data">;
|
|
33
|
+
}
|
|
34
|
+
export interface PackInfo {
|
|
35
|
+
type: 'data' | 'assets';
|
|
36
|
+
packRoot: string;
|
|
37
|
+
packMcmeta: PackMcmeta | undefined;
|
|
38
|
+
versionInfo: VersionInfo;
|
|
29
39
|
}
|
|
30
40
|
//# sourceMappingURL=common.d.ts.map
|
package/lib/dependency/common.js
CHANGED
|
@@ -28,5 +28,12 @@ export var PackMcmeta;
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
PackMcmeta.assert = assert;
|
|
31
|
+
async function getType(packRoot, externals) {
|
|
32
|
+
const dir = await externals.fs.readdir(packRoot);
|
|
33
|
+
const isResourcePack = dir.some(e => e.isDirectory() && e.name === 'assets')
|
|
34
|
+
&& !dir.some(e => e.isDirectory() && e.name === 'data');
|
|
35
|
+
return isResourcePack ? 'assets' : 'data';
|
|
36
|
+
}
|
|
37
|
+
PackMcmeta.getType = getType;
|
|
31
38
|
})(PackMcmeta || (PackMcmeta = {}));
|
|
32
39
|
//# sourceMappingURL=common.js.map
|
|
@@ -25,6 +25,14 @@ export declare function getMcmetaSummary(externals: core.Externals, downloader:
|
|
|
25
25
|
* - `uri`: URI to the `.tar.gz` file.
|
|
26
26
|
*/
|
|
27
27
|
export declare function getVanillaDatapack(downloader: core.Downloader, version: string, isLatest: boolean): Promise<core.Dependency>;
|
|
28
|
+
/**
|
|
29
|
+
* @throws Network/file system errors.
|
|
30
|
+
*
|
|
31
|
+
* @returns
|
|
32
|
+
* - `startDepth`: The amount of level to skip when unzipping the tarball.
|
|
33
|
+
* - `uri`: URI to the `.tar.gz` file.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getVanillaResourcepack(downloader: core.Downloader, version: string, isLatest: boolean): Promise<core.Dependency>;
|
|
28
36
|
/**
|
|
29
37
|
* @throws Network/file system errors.
|
|
30
38
|
*
|
package/lib/dependency/index.js
CHANGED
|
@@ -107,11 +107,11 @@ function getCacheOptionsBasedOnGitHubCommitSha(owner, repo, ref) {
|
|
|
107
107
|
*
|
|
108
108
|
* @returns The URI to the `.tar.gz` file.
|
|
109
109
|
*/
|
|
110
|
-
async function downloadGitHubRepo({ defaultBranch, downloader, getTag, repo, isLatest, owner, version }) {
|
|
110
|
+
async function downloadGitHubRepo({ defaultBranch, downloader, getTag, repo, isLatest, owner, version, suffix }) {
|
|
111
111
|
const ref = getGitRef({ defaultBranch, getTag, isLatest, version });
|
|
112
112
|
const out = {};
|
|
113
113
|
await downloader.download({
|
|
114
|
-
id: `mc-je/${version}/${repo}.tar.gz`,
|
|
114
|
+
id: `mc-je/${version}/${repo}${suffix ?? ''}.tar.gz`,
|
|
115
115
|
uri: `https://api.github.com/repos/${owner}/${repo}/tarball/${ref}`,
|
|
116
116
|
transformer: (b) => b,
|
|
117
117
|
cache: getCacheOptionsBasedOnGitHubCommitSha(owner, repo, ref),
|
|
@@ -140,6 +140,27 @@ export async function getVanillaDatapack(downloader, version, isLatest) {
|
|
|
140
140
|
});
|
|
141
141
|
return { info: { startDepth: 1 }, uri };
|
|
142
142
|
}
|
|
143
|
+
/* istanbul ignore next */
|
|
144
|
+
/**
|
|
145
|
+
* @throws Network/file system errors.
|
|
146
|
+
*
|
|
147
|
+
* @returns
|
|
148
|
+
* - `startDepth`: The amount of level to skip when unzipping the tarball.
|
|
149
|
+
* - `uri`: URI to the `.tar.gz` file.
|
|
150
|
+
*/
|
|
151
|
+
export async function getVanillaResourcepack(downloader, version, isLatest) {
|
|
152
|
+
const uri = await downloadGitHubRepo({
|
|
153
|
+
defaultBranch: 'assets-tiny',
|
|
154
|
+
downloader,
|
|
155
|
+
getTag: (v) => `${v}-assets-tiny`,
|
|
156
|
+
owner: 'misode',
|
|
157
|
+
repo: 'mcmeta',
|
|
158
|
+
isLatest,
|
|
159
|
+
version,
|
|
160
|
+
suffix: '-assets',
|
|
161
|
+
});
|
|
162
|
+
return { info: { startDepth: 1 }, uri };
|
|
163
|
+
}
|
|
143
164
|
/**
|
|
144
165
|
* @throws Network/file system errors.
|
|
145
166
|
*
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
2
|
import type { PackMcmeta, VersionInfo } from './common.js';
|
|
3
|
+
import { ReleaseVersion } from './common.js';
|
|
4
|
+
export declare const NEXT_RELEASE_VERSION = "1.21.4";
|
|
3
5
|
/**
|
|
4
6
|
* @param inputVersion {@link core.Config.env.gameVersion}
|
|
5
7
|
*/
|
|
6
|
-
export declare function resolveConfiguredVersion(inputVersion: string, versions: McmetaVersions,
|
|
8
|
+
export declare function resolveConfiguredVersion(inputVersion: string, versions: McmetaVersions, packMcmeta: PackMcmeta | undefined, packType: 'assets' | 'data' | undefined): VersionInfo;
|
|
7
9
|
export declare function getMcmetaSummaryUris(version: string, isLatest: boolean, source: string): {
|
|
8
10
|
blocks: core.RemoteUriString;
|
|
9
11
|
commands: core.RemoteUriString;
|
|
10
12
|
registries: core.RemoteUriString;
|
|
11
13
|
};
|
|
12
|
-
export declare function symbolRegistrar(summary: McmetaSummary): core.SymbolRegistrar;
|
|
14
|
+
export declare function symbolRegistrar(summary: McmetaSummary, release: ReleaseVersion): core.SymbolRegistrar;
|
|
13
15
|
export declare const Fluids: McmetaStates;
|
|
14
16
|
export interface McmetaVersion {
|
|
15
17
|
id: string;
|
package/lib/dependency/mcmeta.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
|
+
import { ReleaseVersion } from './common.js';
|
|
3
|
+
// DOCS: Update this when a new snapshot cycle begins
|
|
4
|
+
export const NEXT_RELEASE_VERSION = '1.21.4';
|
|
2
5
|
/**
|
|
3
6
|
* @param inputVersion {@link core.Config.env.gameVersion}
|
|
4
7
|
*/
|
|
5
|
-
export
|
|
8
|
+
export function resolveConfiguredVersion(inputVersion, versions, packMcmeta, packType) {
|
|
6
9
|
function findReleaseTarget(version) {
|
|
7
10
|
if (version.release_target) {
|
|
8
11
|
return version.release_target;
|
|
@@ -16,16 +19,16 @@ export async function resolveConfiguredVersion(inputVersion, versions, getPackMc
|
|
|
16
19
|
return versions[i].id;
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
|
-
|
|
20
|
-
return '1.21.4';
|
|
22
|
+
return NEXT_RELEASE_VERSION;
|
|
21
23
|
}
|
|
22
|
-
function toVersionInfo(version) {
|
|
24
|
+
function toVersionInfo(version, reason) {
|
|
23
25
|
version = version ?? versions[0];
|
|
24
26
|
return {
|
|
25
27
|
id: version.id,
|
|
26
28
|
name: version.name,
|
|
27
29
|
release: findReleaseTarget(version),
|
|
28
30
|
isLatest: version === versions[0],
|
|
31
|
+
reason,
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
34
|
if (versions.length === 0) {
|
|
@@ -35,39 +38,45 @@ export async function resolveConfiguredVersion(inputVersion, versions, getPackMc
|
|
|
35
38
|
versions = versions.sort((a, b) => b.data_version - a.data_version);
|
|
36
39
|
const latestRelease = versions.find((v) => v.type === 'release');
|
|
37
40
|
if (inputVersion === 'auto') {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
41
|
+
const packFormat = packMcmeta?.pack.pack_format;
|
|
42
|
+
if (packFormat && latestRelease) {
|
|
40
43
|
// If the pack format is larger than the latest release, use the latest snapshot
|
|
41
|
-
if (
|
|
42
|
-
|
|
44
|
+
if (packFormat > (packType === 'assets'
|
|
45
|
+
? latestRelease.resource_pack_version
|
|
46
|
+
: latestRelease.data_pack_version)) {
|
|
47
|
+
return toVersionInfo(versions[0], 'auto');
|
|
43
48
|
}
|
|
44
49
|
// Look for versions from recent to oldest, picking the most recent release that matches
|
|
45
50
|
let oldestRelease = undefined;
|
|
46
51
|
for (const version of versions) {
|
|
47
52
|
if (version.type === 'release') {
|
|
48
53
|
// If we already passed the pack format, use the oldest release so far
|
|
49
|
-
if (
|
|
50
|
-
|
|
54
|
+
if (packFormat > (packType === 'assets'
|
|
55
|
+
? version.resource_pack_version
|
|
56
|
+
: version.data_pack_version)) {
|
|
57
|
+
return toVersionInfo(oldestRelease, 'auto');
|
|
51
58
|
}
|
|
52
|
-
if (
|
|
53
|
-
|
|
59
|
+
if (packFormat === (packType === 'assets'
|
|
60
|
+
? version.resource_pack_version
|
|
61
|
+
: version.data_pack_version)) {
|
|
62
|
+
return toVersionInfo(version, 'auto');
|
|
54
63
|
}
|
|
55
64
|
oldestRelease = version;
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
// If the pack format is still lower, use the oldest known release version
|
|
59
|
-
return toVersionInfo(oldestRelease);
|
|
68
|
+
return toVersionInfo(oldestRelease, 'auto');
|
|
60
69
|
}
|
|
61
70
|
// Fall back to the latest release if pack mcmeta is not available
|
|
62
|
-
return toVersionInfo(latestRelease);
|
|
71
|
+
return toVersionInfo(latestRelease, 'fallback');
|
|
63
72
|
}
|
|
64
73
|
else if (inputVersion === 'latest release') {
|
|
65
|
-
return toVersionInfo(latestRelease);
|
|
74
|
+
return toVersionInfo(latestRelease, 'config');
|
|
66
75
|
}
|
|
67
76
|
else if (inputVersion === 'latest snapshot') {
|
|
68
|
-
return toVersionInfo(versions[0]);
|
|
77
|
+
return toVersionInfo(versions[0], 'config');
|
|
69
78
|
}
|
|
70
|
-
return toVersionInfo(versions.find((v) => inputVersion === v.id.toLowerCase() || inputVersion === v.name.toLowerCase()));
|
|
79
|
+
return toVersionInfo(versions.find((v) => inputVersion === v.id.toLowerCase() || inputVersion === v.name.toLowerCase()), 'config');
|
|
71
80
|
}
|
|
72
81
|
const DataSources = {
|
|
73
82
|
fastly: 'https://fastly.jsdelivr.net/gh/${user}/${repo}@${tag}/${path}',
|
|
@@ -90,7 +99,7 @@ export function getMcmetaSummaryUris(version, isLatest, source) {
|
|
|
90
99
|
registries: getUri('registries/data.json.gz'),
|
|
91
100
|
};
|
|
92
101
|
}
|
|
93
|
-
export function symbolRegistrar(summary) {
|
|
102
|
+
export function symbolRegistrar(summary, release) {
|
|
94
103
|
const McmetaSummaryUri = 'mcmeta://summary/registries.json';
|
|
95
104
|
/**
|
|
96
105
|
* Add states of blocks or fluids to the symbol table.
|
|
@@ -121,6 +130,52 @@ export function symbolRegistrar(summary) {
|
|
|
121
130
|
});
|
|
122
131
|
});
|
|
123
132
|
}
|
|
133
|
+
symbols.query(McmetaSummaryUri, 'mcdoc/dispatcher', 'mcdoc:block_states').enter({
|
|
134
|
+
usage: { type: 'declaration' },
|
|
135
|
+
}).onEach(Object.entries(summary.blocks), ([id, [properties]], blockQuery) => {
|
|
136
|
+
const data = {
|
|
137
|
+
typeDef: {
|
|
138
|
+
kind: 'struct',
|
|
139
|
+
fields: Object.entries(properties).map(([propKey, propValues]) => ({
|
|
140
|
+
kind: 'pair',
|
|
141
|
+
key: propKey,
|
|
142
|
+
optional: true,
|
|
143
|
+
type: {
|
|
144
|
+
kind: 'union',
|
|
145
|
+
members: propValues.map(value => ({
|
|
146
|
+
kind: 'literal',
|
|
147
|
+
value: { kind: 'string', value },
|
|
148
|
+
})),
|
|
149
|
+
},
|
|
150
|
+
})),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
blockQuery.member(id, (stateQuery) => {
|
|
154
|
+
stateQuery.enter({
|
|
155
|
+
data: { data },
|
|
156
|
+
usage: { type: 'declaration' },
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
symbols.query(McmetaSummaryUri, 'mcdoc/dispatcher', 'mcdoc:block_state_keys').enter({
|
|
161
|
+
usage: { type: 'declaration' },
|
|
162
|
+
}).onEach(Object.entries(summary.blocks), ([id, [properties]], blockQuery) => {
|
|
163
|
+
const data = {
|
|
164
|
+
typeDef: {
|
|
165
|
+
kind: 'union',
|
|
166
|
+
members: Object.keys(properties).map(propKey => ({
|
|
167
|
+
kind: 'literal',
|
|
168
|
+
value: { kind: 'string', value: propKey },
|
|
169
|
+
})),
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
blockQuery.member(id, (stateQuery) => {
|
|
173
|
+
stateQuery.enter({
|
|
174
|
+
data: { data },
|
|
175
|
+
usage: { type: 'declaration' },
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
});
|
|
124
179
|
}
|
|
125
180
|
function addRegistriesSymbols(registries, symbols) {
|
|
126
181
|
function isCategory(str) {
|
|
@@ -137,7 +192,13 @@ export function symbolRegistrar(summary) {
|
|
|
137
192
|
}
|
|
138
193
|
}
|
|
139
194
|
function addBuiltinSymbols(symbols) {
|
|
140
|
-
|
|
195
|
+
if (ReleaseVersion.cmp(release, '1.21.2') < 0) {
|
|
196
|
+
symbols.query(McmetaSummaryUri, 'loot_table', 'minecraft:empty')
|
|
197
|
+
.enter({ usage: { type: 'declaration' } });
|
|
198
|
+
}
|
|
199
|
+
symbols.query(McmetaSummaryUri, 'model', 'minecraft:builtin/generated')
|
|
200
|
+
.enter({ usage: { type: 'declaration' } });
|
|
201
|
+
symbols.query(McmetaSummaryUri, 'model', 'minecraft:builtin/entity')
|
|
141
202
|
.enter({ usage: { type: 'declaration' } });
|
|
142
203
|
}
|
|
143
204
|
return (symbols) => {
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
2
|
import * as json from '@spyglassmc/json';
|
|
3
|
-
import { localize } from '@spyglassmc/locales';
|
|
4
3
|
import * as mcdoc from '@spyglassmc/mcdoc';
|
|
5
4
|
import * as nbt from '@spyglassmc/nbt';
|
|
6
5
|
import { uriBinder } from './binder/index.js';
|
|
7
|
-
import { getMcmetaSummary, getVanillaDatapack, getVanillaMcdoc, getVersions, PackMcmeta,
|
|
6
|
+
import { getMcmetaSummary, getVanillaDatapack, getVanillaMcdoc, getVanillaResourcepack, getVersions, PackMcmeta, resolveConfiguredVersion, symbolRegistrar, } from './dependency/index.js';
|
|
8
7
|
import * as jeJson from './json/index.js';
|
|
8
|
+
import { registerMcdocAttributes, registerPackFormatAttribute } from './mcdocAttributes.js';
|
|
9
9
|
import * as jeMcf from './mcfunction/index.js';
|
|
10
10
|
export * as binder from './binder/index.js';
|
|
11
11
|
export * as dependency from './dependency/index.js';
|
|
@@ -27,26 +27,28 @@ export const initialize = async (ctx) => {
|
|
|
27
27
|
}
|
|
28
28
|
return undefined;
|
|
29
29
|
}
|
|
30
|
-
async function
|
|
31
|
-
const
|
|
30
|
+
async function findPackMcmetas(versions) {
|
|
31
|
+
const searchedUris = new Set();
|
|
32
|
+
const packs = [];
|
|
32
33
|
for (let depth = 0; depth <= 2; depth += 1) {
|
|
33
34
|
for (const projectRoot of projectRoots) {
|
|
34
35
|
const files = await core.fileUtil.getAllFiles(externals, projectRoot, depth + 1);
|
|
35
36
|
for (const uri of files.filter(uri => uri.endsWith('/pack.mcmeta'))) {
|
|
36
|
-
if (
|
|
37
|
+
if (searchedUris.has(uri)) {
|
|
37
38
|
continue;
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
searchedUris.add(uri);
|
|
41
|
+
const packRoot = core.fileUtil.dirname(uri);
|
|
42
|
+
const [packMcmeta, type] = await Promise.all([
|
|
43
|
+
readPackMcmeta(uri),
|
|
44
|
+
PackMcmeta.getType(packRoot, externals),
|
|
45
|
+
]);
|
|
46
|
+
const versionInfo = resolveConfiguredVersion(config.env.gameVersion, versions, packMcmeta, type);
|
|
47
|
+
packs.push({ type, packRoot, packMcmeta, versionInfo });
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
return undefined;
|
|
51
|
+
return packs;
|
|
50
52
|
}
|
|
51
53
|
meta.registerUriBinder(uriBinder);
|
|
52
54
|
const versions = await getVersions(ctx.externals, ctx.downloader);
|
|
@@ -54,9 +56,32 @@ export const initialize = async (ctx) => {
|
|
|
54
56
|
ctx.logger.error('[je-initialize] Failed loading game version list. Expect everything to be broken.');
|
|
55
57
|
return;
|
|
56
58
|
}
|
|
57
|
-
const
|
|
59
|
+
const packs = await findPackMcmetas(versions);
|
|
60
|
+
function selectVersionInfo(packs, versions) {
|
|
61
|
+
// Select the first valid pack.mcmeta, prioritizing data packs
|
|
62
|
+
const pack = packs.find(p => p.packMcmeta !== undefined && p.type === 'data')
|
|
63
|
+
?? packs.find(p => p.packMcmeta !== undefined && p.type === 'assets');
|
|
64
|
+
const version = pack === undefined
|
|
65
|
+
? resolveConfiguredVersion(config.env.gameVersion, versions, undefined, undefined)
|
|
66
|
+
: pack.versionInfo;
|
|
67
|
+
const packMessage = pack === undefined
|
|
68
|
+
? 'Failed finding a valid pack.mcmeta'
|
|
69
|
+
: `Found a valid pack.mcmeta ${pack.packRoot}/pack.mcmeta`;
|
|
70
|
+
const reasonMessage = pack && version.reason === 'auto'
|
|
71
|
+
? `using ${pack.type} pack format ${pack.packMcmeta?.pack.pack_format} to select`
|
|
72
|
+
: version.reason === 'config'
|
|
73
|
+
? `but using config override "${config.env.gameVersion}" to select`
|
|
74
|
+
: version.reason === 'fallback'
|
|
75
|
+
? 'using fallback'
|
|
76
|
+
: 'impossible'; // should never occur
|
|
77
|
+
const versionMessage = `version ${version.release}${version.id === version.release ? '' : ` (${version.id})`}`;
|
|
78
|
+
ctx.logger.info(`[je.initialize] ${packMessage}, ${reasonMessage} ${versionMessage}`);
|
|
79
|
+
return version;
|
|
80
|
+
}
|
|
81
|
+
const version = selectVersionInfo(packs, versions);
|
|
58
82
|
const release = version.release;
|
|
59
83
|
meta.registerDependencyProvider('@vanilla-datapack', () => getVanillaDatapack(downloader, version.id, version.isLatest));
|
|
84
|
+
meta.registerDependencyProvider('@vanilla-resourcepack', () => getVanillaResourcepack(downloader, version.id, version.isLatest));
|
|
60
85
|
meta.registerDependencyProvider('@vanilla-mcdoc', () => getVanillaMcdoc(downloader));
|
|
61
86
|
const summary = await getMcmetaSummary(ctx.externals, downloader, logger, version.id, version.isLatest, config.env.dataSource, config.env.mcmetaSummaryOverrides);
|
|
62
87
|
if (!summary.blocks || !summary.commands || !summary.fluids || !summary.registries) {
|
|
@@ -64,8 +89,8 @@ export const initialize = async (ctx) => {
|
|
|
64
89
|
return;
|
|
65
90
|
}
|
|
66
91
|
meta.registerSymbolRegistrar('mcmeta-summary', {
|
|
67
|
-
checksum: summary.checksum
|
|
68
|
-
registrar: symbolRegistrar(summary),
|
|
92
|
+
checksum: `${summary.checksum}_v2`,
|
|
93
|
+
registrar: symbolRegistrar(summary, release),
|
|
69
94
|
});
|
|
70
95
|
meta.registerLinter('nameOfNbtKey', {
|
|
71
96
|
configValidator: core.linter.configValidator.nameConvention,
|
|
@@ -82,70 +107,15 @@ export const initialize = async (ctx) => {
|
|
|
82
107
|
&& mcdoc.StructKeyNode.is(n)
|
|
83
108
|
&& !n.symbol?.path[0]?.startsWith('::minecraft')),
|
|
84
109
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
});
|
|
94
|
-
mcdoc.runtime.registerAttribute(meta, 'until', mcdoc.runtime.attribute.validator.string, {
|
|
95
|
-
filterElement: (config, ctx) => {
|
|
96
|
-
if (!config.startsWith('1.')) {
|
|
97
|
-
ctx.logger.warn(`Invalid mcdoc attribute for "until": ${config}`);
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
return ReleaseVersion.cmp(release, config) < 0;
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
mcdoc.runtime.registerAttribute(meta, 'deprecated', mcdoc.runtime.attribute.validator.optional(mcdoc.runtime.attribute.validator.string), {
|
|
104
|
-
mapField: (config, field, ctx) => {
|
|
105
|
-
if (config === undefined) {
|
|
106
|
-
return { ...field, deprecated: true };
|
|
107
|
-
}
|
|
108
|
-
if (!config.startsWith('1.')) {
|
|
109
|
-
ctx.logger.warn(`Invalid mcdoc attribute for "deprecated": ${config}`);
|
|
110
|
-
return field;
|
|
111
|
-
}
|
|
112
|
-
if (ReleaseVersion.cmp(release, config) >= 0) {
|
|
113
|
-
return { ...field, deprecated: true };
|
|
114
|
-
}
|
|
115
|
-
return field;
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
const packFormats = new Map();
|
|
119
|
-
for (const version of versions) {
|
|
120
|
-
if (version.type === 'release' && !packFormats.has(version.data_pack_version)) {
|
|
121
|
-
packFormats.set(version.data_pack_version, version);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
mcdoc.runtime.registerAttribute(meta, 'pack_format', () => undefined, {
|
|
125
|
-
checker: (_, typeDef) => {
|
|
126
|
-
if (typeDef.kind !== 'literal' || typeof typeDef.value.value !== 'number') {
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
const target = typeDef.value.value;
|
|
130
|
-
return (node, ctx) => {
|
|
131
|
-
const targetVersion = packFormats.get(target);
|
|
132
|
-
if (!targetVersion) {
|
|
133
|
-
ctx.err.report(localize('java-edition.pack-format.unsupported', target), node, 2 /* core.ErrorSeverity.Warning */);
|
|
134
|
-
}
|
|
135
|
-
else if (targetVersion.id !== release) {
|
|
136
|
-
ctx.err.report(localize('java-edition.pack-format.not-loaded', target, release), node, 2 /* core.ErrorSeverity.Warning */);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
},
|
|
140
|
-
numericCompleter: (_, ctx) => {
|
|
141
|
-
return [...packFormats.values()].map((v, i) => ({
|
|
142
|
-
range: core.Range.create(ctx.offset),
|
|
143
|
-
label: `${v.data_pack_version}`,
|
|
144
|
-
labelSuffix: ` (${v.id})`,
|
|
145
|
-
sortText: `${i}`.padStart(4, '0'),
|
|
146
|
-
}));
|
|
147
|
-
},
|
|
148
|
-
});
|
|
110
|
+
registerMcdocAttributes(meta, release);
|
|
111
|
+
registerPackFormatAttribute(meta, release, versions, packs);
|
|
112
|
+
meta.registerLanguage('zip', { extensions: ['.zip'] });
|
|
113
|
+
meta.registerLanguage('png', { extensions: ['.png'] });
|
|
114
|
+
meta.registerLanguage('ogg', { extensions: ['.ogg'] });
|
|
115
|
+
meta.registerLanguage('ttf', { extensions: ['.ttf'] });
|
|
116
|
+
meta.registerLanguage('otf', { extensions: ['.otf'] });
|
|
117
|
+
meta.registerLanguage('fsh', { extensions: ['.fsh'] });
|
|
118
|
+
meta.registerLanguage('vsh', { extensions: ['.vsh'] });
|
|
149
119
|
json.initialize(ctx);
|
|
150
120
|
jeJson.initialize(ctx);
|
|
151
121
|
jeMcf.initialize(ctx, summary.commands, release);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import type { McmetaVersions, PackInfo } from './dependency';
|
|
3
|
+
import { ReleaseVersion } from './dependency';
|
|
4
|
+
export declare function registerMcdocAttributes(meta: core.MetaRegistry, release: ReleaseVersion): void;
|
|
5
|
+
export declare function registerPackFormatAttribute(meta: core.MetaRegistry, release: ReleaseVersion, versions: McmetaVersions, packs: PackInfo[]): void;
|
|
6
|
+
//# sourceMappingURL=mcdocAttributes.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import { localize } from '@spyglassmc/locales';
|
|
3
|
+
import * as mcdoc from '@spyglassmc/mcdoc';
|
|
4
|
+
import { NEXT_RELEASE_VERSION, ReleaseVersion } from './dependency';
|
|
5
|
+
export function registerMcdocAttributes(meta, release) {
|
|
6
|
+
mcdoc.runtime.registerAttribute(meta, 'since', mcdoc.runtime.attribute.validator.string, {
|
|
7
|
+
filterElement: (config, ctx) => {
|
|
8
|
+
if (!config.startsWith('1.')) {
|
|
9
|
+
ctx.logger.warn(`Invalid mcdoc attribute for "since": ${config}`);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return ReleaseVersion.cmp(release, config) >= 0;
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
mcdoc.runtime.registerAttribute(meta, 'until', mcdoc.runtime.attribute.validator.string, {
|
|
16
|
+
filterElement: (config, ctx) => {
|
|
17
|
+
if (!config.startsWith('1.')) {
|
|
18
|
+
ctx.logger.warn(`Invalid mcdoc attribute for "until": ${config}`);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return ReleaseVersion.cmp(release, config) < 0;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
mcdoc.runtime.registerAttribute(meta, 'deprecated', mcdoc.runtime.attribute.validator.optional(mcdoc.runtime.attribute.validator.string), {
|
|
25
|
+
mapField: (config, field, ctx) => {
|
|
26
|
+
if (config === undefined) {
|
|
27
|
+
return { ...field, deprecated: true };
|
|
28
|
+
}
|
|
29
|
+
if (!config.startsWith('1.')) {
|
|
30
|
+
ctx.logger.warn(`Invalid mcdoc attribute for "deprecated": ${config}`);
|
|
31
|
+
return field;
|
|
32
|
+
}
|
|
33
|
+
if (ReleaseVersion.cmp(release, config) >= 0) {
|
|
34
|
+
return { ...field, deprecated: true };
|
|
35
|
+
}
|
|
36
|
+
return field;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export function registerPackFormatAttribute(meta, release, versions, packs) {
|
|
41
|
+
const dataFormats = new Map();
|
|
42
|
+
const assetsFormats = new Map();
|
|
43
|
+
if (versions[0]?.type !== 'release') {
|
|
44
|
+
dataFormats.set(versions[0].data_pack_version, [NEXT_RELEASE_VERSION]);
|
|
45
|
+
assetsFormats.set(versions[0].resource_pack_version, [NEXT_RELEASE_VERSION]);
|
|
46
|
+
}
|
|
47
|
+
for (const version of versions) {
|
|
48
|
+
if (version.type === 'release') {
|
|
49
|
+
dataFormats.set(version.data_pack_version, [
|
|
50
|
+
...dataFormats.get(version.data_pack_version) ?? [],
|
|
51
|
+
version.id,
|
|
52
|
+
]);
|
|
53
|
+
assetsFormats.set(version.resource_pack_version, [
|
|
54
|
+
...assetsFormats.get(version.resource_pack_version) ?? [],
|
|
55
|
+
version.id,
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function getFormats(packMcmetaUri) {
|
|
60
|
+
const thisPack = packs.find(p => core.fileUtil.isSubUriOf(packMcmetaUri, p.packRoot));
|
|
61
|
+
return thisPack?.type === 'assets' ? assetsFormats : dataFormats;
|
|
62
|
+
}
|
|
63
|
+
mcdoc.runtime.registerAttribute(meta, 'pack_format', () => undefined, {
|
|
64
|
+
checker: (_, typeDef) => {
|
|
65
|
+
if (typeDef.kind !== 'literal' || typeof typeDef.value.value !== 'number') {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const target = typeDef.value.value;
|
|
69
|
+
return (node, ctx) => {
|
|
70
|
+
const targetVersions = getFormats(ctx.doc.uri).get(target);
|
|
71
|
+
if (!targetVersions) {
|
|
72
|
+
ctx.err.report(localize('java-edition.pack-format.unsupported', target), node, 2 /* core.ErrorSeverity.Warning */);
|
|
73
|
+
}
|
|
74
|
+
else if (!targetVersions.some(v => v === release)) {
|
|
75
|
+
ctx.err.report(localize('java-edition.pack-format.not-loaded', target, release), node, 2 /* core.ErrorSeverity.Warning */);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
numericCompleter: (_, ctx) => {
|
|
80
|
+
return [...getFormats(ctx.doc.uri).entries()].map(([k, v], i) => ({
|
|
81
|
+
range: core.Range.create(ctx.offset),
|
|
82
|
+
label: `${k}`,
|
|
83
|
+
labelSuffix: ` (${v[0]})`,
|
|
84
|
+
sortText: `${i}`.padStart(4, '0'),
|
|
85
|
+
}));
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=mcdocAttributes.js.map
|
|
@@ -131,17 +131,17 @@ const itemStack = (node, ctx) => {
|
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
const groupedComponents = new Map();
|
|
134
|
-
for (const
|
|
135
|
-
if (!
|
|
134
|
+
for (const child of node.components.children) {
|
|
135
|
+
if (!child.key) {
|
|
136
136
|
continue;
|
|
137
137
|
}
|
|
138
|
-
const componentId = core.ResourceLocationNode.toString(
|
|
138
|
+
const componentId = core.ResourceLocationNode.toString(child.key, 'full');
|
|
139
139
|
if (!groupedComponents.has(componentId)) {
|
|
140
140
|
groupedComponents.set(componentId, []);
|
|
141
141
|
}
|
|
142
|
-
groupedComponents.get(componentId).push(
|
|
143
|
-
if (
|
|
144
|
-
nbt.checker.index('minecraft:data_component', componentId)(
|
|
142
|
+
groupedComponents.get(componentId).push(child.key);
|
|
143
|
+
if (child.type === 'mcfunction:component' && child.value) {
|
|
144
|
+
nbt.checker.index('minecraft:data_component', componentId)(child.value, ctx);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
for (const [_, group] of groupedComponents) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AstNode, BooleanNode, BrigadierStringOptions, completer, CompletionItem, FloatNode, getStates, InsertTextBuilder, IntegerNode, LiteralNode, Range, ResourceLocation, ResourceLocationNode, StringNode, SymbolNode, } from '@spyglassmc/core';
|
|
1
|
+
import { AstNode, binarySearch, BooleanNode, BrigadierStringOptions, completer, CompletionItem, FloatNode, getStates, InsertTextBuilder, IntegerNode, LiteralNode, Range, ResourceLocation, ResourceLocationNode, StringNode, SymbolNode, } from '@spyglassmc/core';
|
|
2
2
|
import * as json from '@spyglassmc/json';
|
|
3
3
|
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
4
4
|
import { getTagValues } from '../../common/index.js';
|
|
@@ -183,19 +183,32 @@ const blockStates = (node, ctx) => {
|
|
|
183
183
|
})(node, ctx);
|
|
184
184
|
};
|
|
185
185
|
const componentList = (node, ctx) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
186
|
+
if (!Range.contains(Range.translate(node, 1, -1), ctx.offset, true)) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
const completeKey = (key) => {
|
|
190
|
+
const id = key
|
|
191
|
+
?? ResourceLocationNode.mock(key ?? ctx.offset, { category: 'data_component_type' });
|
|
192
|
+
return completer.resourceLocation(id, ctx);
|
|
193
|
+
};
|
|
194
|
+
const index = binarySearch(node.children, ctx.offset, (n, o) => Range.compareOffset(n.range, o, true));
|
|
195
|
+
const child = index >= 0 ? node.children[index] : undefined;
|
|
196
|
+
if (!child) {
|
|
197
|
+
return [
|
|
198
|
+
...completer.literal(LiteralNode.mock(ctx.offset, { pool: ['!'] }), ctx),
|
|
199
|
+
...completeKey(undefined),
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
if (child.type === 'mcfunction:component_removal') {
|
|
203
|
+
return completeKey(child.key);
|
|
204
|
+
}
|
|
205
|
+
if ((child.key && Range.contains(child.key, ctx.offset, true))) {
|
|
206
|
+
return completeKey(child.key);
|
|
207
|
+
}
|
|
208
|
+
if (child.value && Range.contains(child.value, ctx.offset, true)) {
|
|
209
|
+
return completer.dispatch(child.value, ctx);
|
|
210
|
+
}
|
|
211
|
+
return [];
|
|
199
212
|
};
|
|
200
213
|
const componentTests = (node, ctx) => {
|
|
201
214
|
// TODO: improve this completer
|
|
@@ -57,7 +57,7 @@ export function registerMcdocAttributes(meta, rootTreeNode) {
|
|
|
57
57
|
stringMocker: (_, __, ctx) => ScoreHolderNode.mock(ctx.offset),
|
|
58
58
|
});
|
|
59
59
|
mcdoc.runtime.registerAttribute(meta, 'tag', () => undefined, {
|
|
60
|
-
stringParser: () => parser.tag('
|
|
60
|
+
stringParser: () => parser.tag('reference'),
|
|
61
61
|
stringMocker: (_, __, ctx) => core.SymbolNode.mock(ctx.offset, { category: 'tag' }),
|
|
62
62
|
});
|
|
63
63
|
mcdoc.runtime.registerAttribute(meta, 'block_predicate', () => undefined, {
|
|
@@ -86,7 +86,7 @@ export interface EntitySelectorNode extends core.AstNode {
|
|
|
86
86
|
export declare namespace EntitySelectorNode {
|
|
87
87
|
function is<T extends core.DeepReadonly<core.AstNode> | undefined>(node: T): node is core.InheritReadonly<EntitySelectorNode, T>;
|
|
88
88
|
function mock(range: core.RangeLike, options: core.LiteralOptions): EntitySelectorNode;
|
|
89
|
-
const ArgumentKeys: Set<"tag" | "team" | "predicate" | "type" | "level" | "
|
|
89
|
+
const ArgumentKeys: Set<"tag" | "team" | "predicate" | "type" | "level" | "sort" | "advancements" | "nbt" | "distance" | "gamemode" | "limit" | "name" | "scores" | "x" | "y" | "z" | "dx" | "dy" | "dz" | "x_rotation" | "y_rotation">;
|
|
90
90
|
type ArgumentKey = typeof ArgumentKeys extends Set<infer T> ? T : undefined;
|
|
91
91
|
const enum Result {
|
|
92
92
|
Ok = 0,
|
|
@@ -123,11 +123,29 @@ export declare namespace ItemStackNode {
|
|
|
123
123
|
}
|
|
124
124
|
export interface ComponentListNode extends core.AstNode {
|
|
125
125
|
type: 'mcfunction:component_list';
|
|
126
|
-
children:
|
|
126
|
+
children: (ComponentNode | ComponentRemovalNode)[];
|
|
127
127
|
}
|
|
128
128
|
export declare namespace ComponentListNode {
|
|
129
129
|
function is(node: core.AstNode): node is ComponentListNode;
|
|
130
130
|
}
|
|
131
|
+
export interface ComponentNode extends core.AstNode {
|
|
132
|
+
type: 'mcfunction:component';
|
|
133
|
+
children: (core.ResourceLocationNode | nbt.NbtNode)[];
|
|
134
|
+
key: core.ResourceLocationNode;
|
|
135
|
+
value?: nbt.NbtNode;
|
|
136
|
+
}
|
|
137
|
+
export declare namespace ComponentNode {
|
|
138
|
+
function is(node: core.AstNode): node is ComponentNode;
|
|
139
|
+
}
|
|
140
|
+
export interface ComponentRemovalNode extends core.AstNode {
|
|
141
|
+
type: 'mcfunction:component_removal';
|
|
142
|
+
children: (core.LiteralNode | core.ResourceLocationNode)[];
|
|
143
|
+
prefix: core.LiteralNode;
|
|
144
|
+
key: core.ResourceLocationNode;
|
|
145
|
+
}
|
|
146
|
+
export declare namespace ComponentRemovalNode {
|
|
147
|
+
function is(node: core.AstNode): node is ComponentRemovalNode;
|
|
148
|
+
}
|
|
131
149
|
export interface ItemPredicateNode extends core.AstNode {
|
|
132
150
|
type: 'mcfunction:item_predicate';
|
|
133
151
|
children: (core.ResourceLocationNode | core.LiteralNode | ComponentTestsNode | nbt.NbtCompoundNode)[];
|
|
@@ -233,7 +251,7 @@ export interface ObjectiveCriteriaNode extends core.AstNode {
|
|
|
233
251
|
}
|
|
234
252
|
export declare namespace ObjectiveCriteriaNode {
|
|
235
253
|
const SimpleValues: string[];
|
|
236
|
-
const ComplexCategories: Map<string, "block" | "fluid" | "instrument" | "activity" | "armor_material" | "attribute" | "block_entity_type" | "block_predicate_type" | "block_type" | "cat_variant" | "chunk_status" | "command_argument_type" | "creative_mode_tab" | "custom_stat" | "data_component_type" | "decorated_pot_pattern" | "enchantment_effect_component_type" | "enchantment_entity_effect_type" | "enchantment_level_based_value_type" | "enchantment_location_based_effect_type" | "enchantment_provider_type" | "enchantment_value_effect_type" | "entity_sub_predicate_type" | "entity_type" | "float_provider_type" | "frog_variant" | "game_event" | "height_provider_type" | "int_provider_type" | "item" | "item_sub_predicate_type" | "loot_condition_type" | "loot_function_type" | "loot_nbt_provider_type" | "loot_number_provider_type" | "loot_pool_entry_type" | "loot_score_provider_type" | "map_decoration_type" | "memory_module_type" | "menu" | "mob_effect" | "motive" | "number_format_type" | "particle_type" | "point_of_interest_type" | "pos_rule_test" | "position_source_type" | "potion" | "recipe_serializer" | "recipe_type" | "rule_block_entity_modifier" | "rule_test" | "schedule" | "sensor_type" | "sound_event" | "stat_type" | "trigger_type" | "villager_profession" | "villager_type" | "worldgen/biome_source" | "worldgen/block_placer_type" | "worldgen/block_state_provider_type" | "worldgen/carver" | "worldgen/chunk_generator" | "worldgen/decorator" | "worldgen/density_function_type" | "worldgen/feature" | "worldgen/feature_size_type" | "worldgen/foliage_placer_type" | "worldgen/material_condition" | "worldgen/material_rule" | "worldgen/placement_modifier_type" | "worldgen/pool_alias_binding" | "worldgen/root_placer_type" | "worldgen/structure_feature" | "worldgen/structure_piece" | "worldgen/structure_placement" | "worldgen/structure_pool_element" | "worldgen/structure_processor" | "worldgen/structure_type" | "worldgen/surface_builder" | "worldgen/tree_decorator_type" | "worldgen/trunk_placer_type">;
|
|
254
|
+
const ComplexCategories: Map<string, "block" | "fluid" | "instrument" | "activity" | "armor_material" | "attribute" | "block_entity_type" | "block_predicate_type" | "block_type" | "cat_variant" | "chunk_status" | "command_argument_type" | "consume_effect_type" | "creative_mode_tab" | "custom_stat" | "data_component_type" | "decorated_pot_pattern" | "decorated_pot_patterns" | "enchantment_effect_component_type" | "enchantment_entity_effect_type" | "enchantment_level_based_value_type" | "enchantment_location_based_effect_type" | "enchantment_provider_type" | "enchantment_value_effect_type" | "entity_sub_predicate_type" | "entity_type" | "float_provider_type" | "frog_variant" | "game_event" | "height_provider_type" | "int_provider_type" | "item" | "item_sub_predicate_type" | "loot_condition_type" | "loot_function_type" | "loot_nbt_provider_type" | "loot_number_provider_type" | "loot_pool_entry_type" | "loot_score_provider_type" | "map_decoration_type" | "memory_module_type" | "menu" | "mob_effect" | "motive" | "number_format_type" | "particle_type" | "point_of_interest_type" | "pos_rule_test" | "position_source_type" | "potion" | "recipe_book_category" | "recipe_display" | "recipe_serializer" | "recipe_type" | "rule_block_entity_modifier" | "rule_test" | "schedule" | "sensor_type" | "slot_display" | "sound_event" | "stat_type" | "trigger_type" | "villager_profession" | "villager_type" | "worldgen/biome_source" | "worldgen/block_placer_type" | "worldgen/block_state_provider_type" | "worldgen/carver" | "worldgen/chunk_generator" | "worldgen/decorator" | "worldgen/density_function_type" | "worldgen/feature" | "worldgen/feature_size_type" | "worldgen/foliage_placer_type" | "worldgen/material_condition" | "worldgen/material_rule" | "worldgen/placement_modifier_type" | "worldgen/pool_alias_binding" | "worldgen/root_placer_type" | "worldgen/structure_feature" | "worldgen/structure_piece" | "worldgen/structure_placement" | "worldgen/structure_pool_element" | "worldgen/structure_processor" | "worldgen/structure_type" | "worldgen/surface_builder" | "worldgen/tree_decorator_type" | "worldgen/trunk_placer_type">;
|
|
237
255
|
const ComplexSep = ":";
|
|
238
256
|
function mock(range: core.RangeLike): ObjectiveCriteriaNode;
|
|
239
257
|
}
|
|
@@ -254,9 +272,10 @@ export declare namespace ParticleNode {
|
|
|
254
272
|
}
|
|
255
273
|
export interface ScoreHolderNode extends core.AstNode {
|
|
256
274
|
type: 'mcfunction:score_holder';
|
|
257
|
-
children: [core.SymbolNode | EntitySelectorNode];
|
|
275
|
+
children: [core.LiteralNode | core.SymbolNode | EntitySelectorNode];
|
|
258
276
|
fakeName?: core.SymbolNode;
|
|
259
277
|
selector?: EntitySelectorNode;
|
|
278
|
+
wildcard?: core.LiteralNode;
|
|
260
279
|
}
|
|
261
280
|
export declare namespace ScoreHolderNode {
|
|
262
281
|
function mock(range: core.RangeLike): ScoreHolderNode;
|
|
@@ -181,6 +181,20 @@ export var ComponentListNode;
|
|
|
181
181
|
}
|
|
182
182
|
ComponentListNode.is = is;
|
|
183
183
|
})(ComponentListNode || (ComponentListNode = {}));
|
|
184
|
+
export var ComponentNode;
|
|
185
|
+
(function (ComponentNode) {
|
|
186
|
+
function is(node) {
|
|
187
|
+
return node.type === 'mcfunction:component';
|
|
188
|
+
}
|
|
189
|
+
ComponentNode.is = is;
|
|
190
|
+
})(ComponentNode || (ComponentNode = {}));
|
|
191
|
+
export var ComponentRemovalNode;
|
|
192
|
+
(function (ComponentRemovalNode) {
|
|
193
|
+
function is(node) {
|
|
194
|
+
return node.type === 'mcfunction:component_removal';
|
|
195
|
+
}
|
|
196
|
+
ComponentRemovalNode.is = is;
|
|
197
|
+
})(ComponentRemovalNode || (ComponentRemovalNode = {}));
|
|
184
198
|
export var ItemPredicateNode;
|
|
185
199
|
(function (ItemPredicateNode) {
|
|
186
200
|
function is(node) {
|
|
@@ -883,9 +883,12 @@ export function scoreHolderFakeName(usageType) {
|
|
|
883
883
|
return validateLength(symbol({ category: 'score_holder', usageType }), FakeNameMaxLength, 'mcfunction.parser.score_holder.fake-name.too-long');
|
|
884
884
|
}
|
|
885
885
|
export function scoreHolder(usageType, amount) {
|
|
886
|
-
return core.map(core.select([
|
|
887
|
-
|
|
888
|
-
|
|
886
|
+
return core.map(core.select([
|
|
887
|
+
// Technically score holders can start with *, but this doesn't account for it
|
|
888
|
+
{ prefix: '*', parser: core.literal('*') },
|
|
889
|
+
{ prefix: '@', parser: selector() },
|
|
890
|
+
{ parser: scoreHolderFakeName(usageType) },
|
|
891
|
+
]), (res, _src, ctx) => {
|
|
889
892
|
const ans = {
|
|
890
893
|
type: 'mcfunction:score_holder',
|
|
891
894
|
range: res.range,
|
|
@@ -894,9 +897,12 @@ export function scoreHolder(usageType, amount) {
|
|
|
894
897
|
if (core.SymbolNode.is(res)) {
|
|
895
898
|
ans.fakeName = res;
|
|
896
899
|
}
|
|
897
|
-
else {
|
|
900
|
+
else if (EntitySelectorNode.is(res)) {
|
|
898
901
|
ans.selector = res;
|
|
899
902
|
}
|
|
903
|
+
else {
|
|
904
|
+
ans.wildcard = res;
|
|
905
|
+
}
|
|
900
906
|
if (amount === 'single' && ans.selector && !ans.selector.single) {
|
|
901
907
|
ctx.err.report(localize('mcfunction.parser.entity-selector.multiple-disallowed'), ans);
|
|
902
908
|
}
|
|
@@ -1046,24 +1052,75 @@ function vector(options) {
|
|
|
1046
1052
|
return ans;
|
|
1047
1053
|
};
|
|
1048
1054
|
}
|
|
1049
|
-
const components =
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
key: core.resourceLocation({ category: 'data_component_type' }),
|
|
1053
|
-
sep: '=',
|
|
1054
|
-
value: nbt.parser.entry,
|
|
1055
|
-
end: ',',
|
|
1056
|
-
trailingEnd: true,
|
|
1057
|
-
},
|
|
1058
|
-
end: ']',
|
|
1059
|
-
}), (res) => {
|
|
1055
|
+
const components = (src, ctx) => {
|
|
1056
|
+
const release = ctx.project['loadedVersion'];
|
|
1057
|
+
const allowComponentRemoval = !release || ReleaseVersion.cmp(release, '1.21') >= 0;
|
|
1060
1058
|
const ans = {
|
|
1061
1059
|
type: 'mcfunction:component_list',
|
|
1062
|
-
range:
|
|
1063
|
-
children:
|
|
1060
|
+
range: core.Range.create(src),
|
|
1061
|
+
children: [],
|
|
1064
1062
|
};
|
|
1063
|
+
if (!src.trySkip('[')) {
|
|
1064
|
+
return core.Failure;
|
|
1065
|
+
}
|
|
1066
|
+
src.skipWhitespace();
|
|
1067
|
+
while (src.canRead() && src.peek() !== ']') {
|
|
1068
|
+
const start = src.cursor;
|
|
1069
|
+
if (allowComponentRemoval && src.tryPeek('!')) {
|
|
1070
|
+
const prefix = core.literal('!')(src, ctx);
|
|
1071
|
+
src.skipWhitespace();
|
|
1072
|
+
const key = core.resourceLocation({ category: 'data_component_type' })(src, ctx);
|
|
1073
|
+
ans.children.push({
|
|
1074
|
+
type: 'mcfunction:component_removal',
|
|
1075
|
+
range: core.Range.create(start, src),
|
|
1076
|
+
children: [prefix, key],
|
|
1077
|
+
prefix,
|
|
1078
|
+
key,
|
|
1079
|
+
});
|
|
1080
|
+
src.skipWhitespace();
|
|
1081
|
+
}
|
|
1082
|
+
else {
|
|
1083
|
+
const key = core.resourceLocation({ category: 'data_component_type' })(src, ctx);
|
|
1084
|
+
src.skipWhitespace();
|
|
1085
|
+
core.literal('=')(src, ctx);
|
|
1086
|
+
src.skipWhitespace();
|
|
1087
|
+
const value = nbt.parser.entry(src, ctx);
|
|
1088
|
+
if (value === core.Failure) {
|
|
1089
|
+
ctx.err.report(localize('expected', localize('parser.record.value')), core.Range.create(src, () => src.skipUntilOrEnd(',', ']', '\r', '\n')));
|
|
1090
|
+
ans.children.push({
|
|
1091
|
+
type: 'mcfunction:component',
|
|
1092
|
+
range: core.Range.create(start, src),
|
|
1093
|
+
children: [key],
|
|
1094
|
+
key,
|
|
1095
|
+
value: undefined,
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
ans.children.push({
|
|
1100
|
+
type: 'mcfunction:component',
|
|
1101
|
+
range: core.Range.create(start, src),
|
|
1102
|
+
children: [key, value],
|
|
1103
|
+
key,
|
|
1104
|
+
value,
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
src.skipWhitespace();
|
|
1108
|
+
}
|
|
1109
|
+
if (src.trySkip(',')) {
|
|
1110
|
+
src.skipWhitespace();
|
|
1111
|
+
if (src.peek() === ']') {
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
else {
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
src.skipWhitespace();
|
|
1120
|
+
core.literal(']')(src, ctx);
|
|
1121
|
+
ans.range.end = src.cursor;
|
|
1065
1122
|
return ans;
|
|
1066
|
-
}
|
|
1123
|
+
};
|
|
1067
1124
|
const componentTest = (src, ctx) => {
|
|
1068
1125
|
const start = src.cursor;
|
|
1069
1126
|
src.skipWhitespace();
|
|
@@ -1076,6 +1133,7 @@ const componentTest = (src, ctx) => {
|
|
|
1076
1133
|
key.options.pool = ['minecraft:count'];
|
|
1077
1134
|
}
|
|
1078
1135
|
if (src.trySkip('=')) {
|
|
1136
|
+
src.skipWhitespace();
|
|
1079
1137
|
const ans = {
|
|
1080
1138
|
type: 'mcfunction:component_test_exact',
|
|
1081
1139
|
range: core.Range.create(start, src),
|
|
@@ -1097,6 +1155,7 @@ const componentTest = (src, ctx) => {
|
|
|
1097
1155
|
return ans;
|
|
1098
1156
|
}
|
|
1099
1157
|
if (src.trySkip('~')) {
|
|
1158
|
+
src.skipWhitespace();
|
|
1100
1159
|
if (key.options.category !== undefined) {
|
|
1101
1160
|
key.options.category = 'item_sub_predicate_type';
|
|
1102
1161
|
}
|
|
@@ -23,16 +23,25 @@ export function getPatch(release) {
|
|
|
23
23
|
children: {
|
|
24
24
|
add: {
|
|
25
25
|
children: {
|
|
26
|
+
id: {
|
|
27
|
+
properties: {
|
|
28
|
+
category: 'attribute_modifier',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
26
31
|
uuid: {
|
|
27
32
|
properties: {
|
|
28
33
|
category: 'attribute_modifier_uuid',
|
|
29
|
-
usageType: 'definition',
|
|
30
34
|
},
|
|
31
35
|
},
|
|
32
36
|
},
|
|
33
37
|
},
|
|
34
38
|
remove: {
|
|
35
39
|
children: {
|
|
40
|
+
id: {
|
|
41
|
+
properties: {
|
|
42
|
+
category: 'attribute_modifier',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
36
45
|
uuid: {
|
|
37
46
|
properties: {
|
|
38
47
|
category: 'attribute_modifier_uuid',
|
|
@@ -44,6 +53,11 @@ export function getPatch(release) {
|
|
|
44
53
|
children: {
|
|
45
54
|
get: {
|
|
46
55
|
children: {
|
|
56
|
+
id: {
|
|
57
|
+
properties: {
|
|
58
|
+
category: 'attribute_modifier',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
47
61
|
uuid: {
|
|
48
62
|
properties: {
|
|
49
63
|
category: 'attribute_modifier_uuid',
|
|
@@ -635,9 +649,6 @@ export function getPatch(release) {
|
|
|
635
649
|
children: {
|
|
636
650
|
name: {
|
|
637
651
|
parser: 'spyglassmc:tag',
|
|
638
|
-
properties: {
|
|
639
|
-
usageType: 'definition',
|
|
640
|
-
},
|
|
641
652
|
},
|
|
642
653
|
},
|
|
643
654
|
},
|
|
@@ -937,6 +948,22 @@ const ExecuteStoreTarget = Object.freeze({
|
|
|
937
948
|
},
|
|
938
949
|
},
|
|
939
950
|
},
|
|
951
|
+
score: {
|
|
952
|
+
children: {
|
|
953
|
+
targets: {
|
|
954
|
+
properties: {
|
|
955
|
+
usageType: 'definition',
|
|
956
|
+
},
|
|
957
|
+
children: {
|
|
958
|
+
objective: {
|
|
959
|
+
properties: {
|
|
960
|
+
accessType: 1 /* SymbolAccessType.Write */,
|
|
961
|
+
},
|
|
962
|
+
},
|
|
963
|
+
},
|
|
964
|
+
},
|
|
965
|
+
},
|
|
966
|
+
},
|
|
940
967
|
},
|
|
941
968
|
});
|
|
942
969
|
const LootSource = Object.freeze({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spyglassmc/java-edition",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"release:dry": "npm publish --dry-run"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@spyglassmc/core": "0.4.
|
|
21
|
-
"@spyglassmc/json": "0.3.
|
|
22
|
-
"@spyglassmc/locales": "0.3.
|
|
23
|
-
"@spyglassmc/mcfunction": "0.2.
|
|
24
|
-
"@spyglassmc/mcdoc": "0.3.
|
|
25
|
-
"@spyglassmc/nbt": "0.3.
|
|
20
|
+
"@spyglassmc/core": "0.4.15",
|
|
21
|
+
"@spyglassmc/json": "0.3.17",
|
|
22
|
+
"@spyglassmc/locales": "0.3.9",
|
|
23
|
+
"@spyglassmc/mcfunction": "0.2.17",
|
|
24
|
+
"@spyglassmc/mcdoc": "0.3.18",
|
|
25
|
+
"@spyglassmc/nbt": "0.3.18"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"fast-glob": "^3.2.5"
|