@adhisang/minecraft-modding-mcp 3.1.0 → 3.1.1
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/CHANGELOG.md +38 -34
- package/README.md +62 -95
- package/dist/config.js +19 -11
- package/dist/entry-tools/analyze-symbol-service.d.ts +2 -0
- package/dist/entry-tools/analyze-symbol-service.js +6 -3
- package/dist/entry-tools/inspect-minecraft-service.d.ts +18 -1
- package/dist/entry-tools/inspect-minecraft-service.js +318 -55
- package/dist/index.js +210 -1
- package/dist/mapping-service.d.ts +1 -0
- package/dist/mapping-service.js +55 -34
- package/dist/source-service.d.ts +2 -0
- package/dist/source-service.js +162 -58
- package/dist/tool-contract-manifest.js +72 -74
- package/package.json +1 -1
package/dist/source-service.js
CHANGED
|
@@ -159,6 +159,7 @@ function clampLimit(limit, fallback, max) {
|
|
|
159
159
|
}
|
|
160
160
|
const MAX_REGEX_QUERY_LENGTH = 200;
|
|
161
161
|
const MAX_REGEX_RESULT_LIMIT = 100;
|
|
162
|
+
const TRACE_LIFECYCLE_MAX_CONCURRENCY = 3;
|
|
162
163
|
function normalizePathStyle(path) {
|
|
163
164
|
return path.replaceAll("\\", "/");
|
|
164
165
|
}
|
|
@@ -214,6 +215,18 @@ function normalizeOptionalProjectPath(projectPath) {
|
|
|
214
215
|
const normalized = normalizePathForHost(trimmed, undefined, "projectPath");
|
|
215
216
|
return isAbsolute(normalized) ? normalized : resolvePath(process.cwd(), normalized);
|
|
216
217
|
}
|
|
218
|
+
function looksLikeClassSegment(name) {
|
|
219
|
+
const trimmed = name.trim();
|
|
220
|
+
return /^[A-Z_$]/.test(trimmed);
|
|
221
|
+
}
|
|
222
|
+
function looksLikeJvmMethodDescriptor(descriptor) {
|
|
223
|
+
const trimmed = descriptor?.trim();
|
|
224
|
+
if (!trimmed || !trimmed.startsWith("(")) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const closing = trimmed.indexOf(")");
|
|
228
|
+
return closing > 0 && closing < trimmed.length - 1;
|
|
229
|
+
}
|
|
217
230
|
function resolveGradleUserHomePath() {
|
|
218
231
|
const configured = process.env.GRADLE_USER_HOME?.trim();
|
|
219
232
|
if (!configured) {
|
|
@@ -278,16 +291,19 @@ function scopeToJarType(scope) {
|
|
|
278
291
|
}
|
|
279
292
|
function parseQualifiedMethodSymbol(symbol) {
|
|
280
293
|
const trimmed = symbol.trim();
|
|
281
|
-
const
|
|
282
|
-
|
|
294
|
+
const descriptorStart = trimmed.indexOf("(");
|
|
295
|
+
const qualifiedSymbol = descriptorStart >= 0 ? trimmed.slice(0, descriptorStart) : trimmed;
|
|
296
|
+
const inlineDescriptor = descriptorStart >= 0 ? trimmed.slice(descriptorStart).trim() : undefined;
|
|
297
|
+
const separator = qualifiedSymbol.lastIndexOf(".");
|
|
298
|
+
if (separator <= 0 || separator >= qualifiedSymbol.length - 1) {
|
|
283
299
|
throw createError({
|
|
284
300
|
code: ERROR_CODES.INVALID_INPUT,
|
|
285
301
|
message: `symbol must be in the form "fully.qualified.Class.method".`,
|
|
286
302
|
details: { symbol }
|
|
287
303
|
});
|
|
288
304
|
}
|
|
289
|
-
const className =
|
|
290
|
-
const methodName =
|
|
305
|
+
const className = qualifiedSymbol.slice(0, separator);
|
|
306
|
+
const methodName = qualifiedSymbol.slice(separator + 1);
|
|
291
307
|
if (!className ||
|
|
292
308
|
!methodName ||
|
|
293
309
|
className.includes("/") ||
|
|
@@ -299,7 +315,11 @@ function parseQualifiedMethodSymbol(symbol) {
|
|
|
299
315
|
details: { symbol }
|
|
300
316
|
});
|
|
301
317
|
}
|
|
302
|
-
return {
|
|
318
|
+
return {
|
|
319
|
+
className,
|
|
320
|
+
methodName,
|
|
321
|
+
...(inlineDescriptor ? { inlineDescriptor } : {})
|
|
322
|
+
};
|
|
303
323
|
}
|
|
304
324
|
function normalizeOptionalString(value) {
|
|
305
325
|
if (value == null) {
|
|
@@ -308,6 +328,27 @@ function normalizeOptionalString(value) {
|
|
|
308
328
|
const trimmed = value.trim();
|
|
309
329
|
return trimmed ? trimmed : undefined;
|
|
310
330
|
}
|
|
331
|
+
async function mapWithConcurrencyLimit(items, limit, mapper) {
|
|
332
|
+
if (items.length === 0) {
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
const results = new Array(items.length);
|
|
336
|
+
let nextIndex = 0;
|
|
337
|
+
const workerCount = Math.max(1, Math.min(Math.trunc(limit), items.length));
|
|
338
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
339
|
+
while (true) {
|
|
340
|
+
// Safe in Node's single-threaded event loop because no await occurs between
|
|
341
|
+
// reading and incrementing nextIndex inside this synchronous dispatch section.
|
|
342
|
+
const currentIndex = nextIndex;
|
|
343
|
+
nextIndex += 1;
|
|
344
|
+
if (currentIndex >= items.length) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
results[currentIndex] = await mapper(items[currentIndex], currentIndex);
|
|
348
|
+
}
|
|
349
|
+
}));
|
|
350
|
+
return results;
|
|
351
|
+
}
|
|
311
352
|
function normalizeStrictPositiveInt(value, field) {
|
|
312
353
|
if (value == null) {
|
|
313
354
|
return undefined;
|
|
@@ -1644,8 +1685,9 @@ export class SourceService {
|
|
|
1644
1685
|
}
|
|
1645
1686
|
async traceSymbolLifecycle(input) {
|
|
1646
1687
|
const mapping = normalizeMapping(input.mapping);
|
|
1647
|
-
const { className: userClassName, methodName: userMethodName } = parseQualifiedMethodSymbol(input.symbol);
|
|
1648
|
-
const descriptor = normalizeOptionalString(input.descriptor)
|
|
1688
|
+
const { className: userClassName, methodName: userMethodName, inlineDescriptor } = parseQualifiedMethodSymbol(input.symbol);
|
|
1689
|
+
const descriptor = normalizeOptionalString(input.descriptor)
|
|
1690
|
+
?? (looksLikeJvmMethodDescriptor(inlineDescriptor) ? normalizeOptionalString(inlineDescriptor) : undefined);
|
|
1649
1691
|
const includeTimeline = input.includeTimeline ?? false;
|
|
1650
1692
|
const includeSnapshots = input.includeSnapshots ?? false;
|
|
1651
1693
|
const maxVersions = clampLimit(input.maxVersions, 120, 400);
|
|
@@ -1701,60 +1743,75 @@ export class SourceService {
|
|
|
1701
1743
|
selectedVersions = selectedVersions.slice(selectedVersions.length - maxVersions);
|
|
1702
1744
|
warnings.push(`Version scan truncated to ${maxVersions} entries. Effective fromVersion is now "${selectedVersions[0]}".`);
|
|
1703
1745
|
}
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
|
|
1746
|
+
const referenceVersion = selectedVersions[selectedVersions.length - 1];
|
|
1747
|
+
await this.rejectLifecycleClassLikeInput({
|
|
1748
|
+
symbol: input.symbol,
|
|
1749
|
+
className: userClassName,
|
|
1750
|
+
methodName: userMethodName,
|
|
1751
|
+
mapping,
|
|
1752
|
+
version: referenceVersion,
|
|
1753
|
+
sourcePriority: input.sourcePriority
|
|
1754
|
+
});
|
|
1755
|
+
const scannedResults = await mapWithConcurrencyLimit(selectedVersions, TRACE_LIFECYCLE_MAX_CONCURRENCY, async (version) => {
|
|
1756
|
+
const versionWarnings = [];
|
|
1707
1757
|
try {
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
]);
|
|
1714
|
-
resolvedSymbols = {
|
|
1715
|
-
className: obfuscatedClassName,
|
|
1716
|
-
methodName: obfuscatedMethod.name,
|
|
1717
|
-
methodDescriptor: obfuscatedMethod.descriptor
|
|
1718
|
-
};
|
|
1719
|
-
resolvedSymbolsByVersion.set(version, resolvedSymbols);
|
|
1720
|
-
}
|
|
1721
|
-
const resolvedJar = await this.versionService.resolveVersionJar(version);
|
|
1758
|
+
const [obfuscatedClassName, obfuscatedMethod, resolvedJar] = await Promise.all([
|
|
1759
|
+
this.resolveToObfuscatedClassName(userClassName, version, mapping, input.sourcePriority, versionWarnings),
|
|
1760
|
+
this.resolveToObfuscatedMemberName(userMethodName, userClassName, descriptor, "method", version, mapping, input.sourcePriority, versionWarnings),
|
|
1761
|
+
this.versionService.resolveVersionJar(version)
|
|
1762
|
+
]);
|
|
1722
1763
|
const signature = await this.explorerService.getSignature({
|
|
1723
|
-
fqn:
|
|
1764
|
+
fqn: obfuscatedClassName,
|
|
1724
1765
|
jarPath: resolvedJar.jarPath,
|
|
1725
1766
|
access: "all",
|
|
1726
1767
|
includeSynthetic: true
|
|
1727
1768
|
});
|
|
1728
|
-
const sameNameMethods = signature.methods.filter((method) => method.name ===
|
|
1729
|
-
const
|
|
1730
|
-
|
|
1769
|
+
const sameNameMethods = signature.methods.filter((method) => method.name === obfuscatedMethod.name);
|
|
1770
|
+
const effectiveDescriptor = obfuscatedMethod.descriptor ?? descriptor;
|
|
1771
|
+
const matchesDescriptor = effectiveDescriptor
|
|
1772
|
+
? sameNameMethods.some((method) => method.jvmDescriptor === effectiveDescriptor)
|
|
1731
1773
|
: sameNameMethods.length > 0;
|
|
1732
1774
|
const reason = !matchesDescriptor && descriptor && sameNameMethods.length > 0 ? "descriptor-mismatch" : undefined;
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1775
|
+
return {
|
|
1776
|
+
entry: {
|
|
1777
|
+
version,
|
|
1778
|
+
exists: matchesDescriptor,
|
|
1779
|
+
reason,
|
|
1780
|
+
determinate: true
|
|
1781
|
+
},
|
|
1782
|
+
warnings: versionWarnings
|
|
1783
|
+
};
|
|
1739
1784
|
}
|
|
1740
1785
|
catch (caughtError) {
|
|
1741
1786
|
if (isAppError(caughtError) && caughtError.code === ERROR_CODES.CLASS_NOT_FOUND) {
|
|
1742
|
-
|
|
1787
|
+
return {
|
|
1788
|
+
entry: {
|
|
1789
|
+
version,
|
|
1790
|
+
exists: false,
|
|
1791
|
+
reason: "class-not-found",
|
|
1792
|
+
determinate: true
|
|
1793
|
+
},
|
|
1794
|
+
warnings: versionWarnings
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
versionWarnings.push(`Failed to evaluate ${version}: ${caughtError instanceof Error ? caughtError.message : String(caughtError)}`);
|
|
1798
|
+
return {
|
|
1799
|
+
entry: {
|
|
1743
1800
|
version,
|
|
1744
1801
|
exists: false,
|
|
1745
|
-
reason: "
|
|
1746
|
-
determinate:
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
reason: "unresolved",
|
|
1754
|
-
determinate: false
|
|
1755
|
-
});
|
|
1756
|
-
warnings.push(`Failed to evaluate ${version}: ${caughtError instanceof Error ? caughtError.message : String(caughtError)}`);
|
|
1802
|
+
reason: "unresolved",
|
|
1803
|
+
determinate: false
|
|
1804
|
+
},
|
|
1805
|
+
warnings: versionWarnings
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
finally {
|
|
1809
|
+
this.releaseLifecycleMappingGraph(version, input.sourcePriority);
|
|
1757
1810
|
}
|
|
1811
|
+
});
|
|
1812
|
+
const scanned = scannedResults.map((result) => result.entry);
|
|
1813
|
+
for (const result of scannedResults) {
|
|
1814
|
+
warnings.push(...result.warnings);
|
|
1758
1815
|
}
|
|
1759
1816
|
const determinate = scanned.filter((entry) => entry.determinate);
|
|
1760
1817
|
const present = determinate.filter((entry) => entry.exists);
|
|
@@ -2695,17 +2752,18 @@ export class SourceService {
|
|
|
2695
2752
|
path: this.resolveMixinInputPath(path, "path")
|
|
2696
2753
|
},
|
|
2697
2754
|
sourcePath: path
|
|
2698
|
-
})), input);
|
|
2755
|
+
})), input, []);
|
|
2699
2756
|
}
|
|
2700
2757
|
const resolvedInput = mode === "project"
|
|
2701
2758
|
? this.createProjectValidateMixinConfigInput(input)
|
|
2702
2759
|
: input;
|
|
2703
|
-
const configSources = await this.resolveMixinConfigSources(resolvedInput);
|
|
2760
|
+
const { sources: configSources, warnings: configWarnings } = await this.resolveMixinConfigSources(resolvedInput);
|
|
2704
2761
|
if (configSources.length === 0) {
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2762
|
+
const emptyOutput = this.buildValidateMixinOutput(mode, []);
|
|
2763
|
+
return this.applyValidateMixinOutputCompaction({
|
|
2764
|
+
...emptyOutput,
|
|
2765
|
+
warnings: [...new Set([...emptyOutput.warnings, ...configWarnings])]
|
|
2766
|
+
}, input);
|
|
2709
2767
|
}
|
|
2710
2768
|
return this.validateMixinMany(mode, configSources.map((entry) => ({
|
|
2711
2769
|
source: {
|
|
@@ -2715,7 +2773,7 @@ export class SourceService {
|
|
|
2715
2773
|
configPath: entry.configPath
|
|
2716
2774
|
},
|
|
2717
2775
|
sourcePath: entry.sourcePath
|
|
2718
|
-
})), resolvedInput);
|
|
2776
|
+
})), resolvedInput, configWarnings);
|
|
2719
2777
|
}
|
|
2720
2778
|
createProjectValidateMixinConfigInput(input) {
|
|
2721
2779
|
if (input.input.mode !== "project") {
|
|
@@ -3245,9 +3303,13 @@ export class SourceService {
|
|
|
3245
3303
|
}
|
|
3246
3304
|
async resolveMixinConfigSources(input) {
|
|
3247
3305
|
if (input.input.mode !== "config") {
|
|
3248
|
-
return
|
|
3306
|
+
return {
|
|
3307
|
+
sources: [],
|
|
3308
|
+
warnings: []
|
|
3309
|
+
};
|
|
3249
3310
|
}
|
|
3250
3311
|
const results = [];
|
|
3312
|
+
const warnings = [];
|
|
3251
3313
|
for (const rawConfigPath of input.input.configPaths) {
|
|
3252
3314
|
const resolvedConfigPath = this.resolveMixinInputPath(rawConfigPath, "configPath");
|
|
3253
3315
|
let configJson;
|
|
@@ -3268,6 +3330,7 @@ export class SourceService {
|
|
|
3268
3330
|
...(configJson.server ?? [])
|
|
3269
3331
|
];
|
|
3270
3332
|
if (classNames.length === 0) {
|
|
3333
|
+
warnings.push(`Mixin config "${resolvedConfigPath}" contains no mixin class entries.`);
|
|
3271
3334
|
continue;
|
|
3272
3335
|
}
|
|
3273
3336
|
const projectBase = input.projectPath
|
|
@@ -3302,9 +3365,12 @@ export class SourceService {
|
|
|
3302
3365
|
});
|
|
3303
3366
|
}
|
|
3304
3367
|
}
|
|
3305
|
-
return
|
|
3368
|
+
return {
|
|
3369
|
+
sources: results,
|
|
3370
|
+
warnings
|
|
3371
|
+
};
|
|
3306
3372
|
}
|
|
3307
|
-
async validateMixinMany(mode, entries, input) {
|
|
3373
|
+
async validateMixinMany(mode, entries, input, additionalWarnings) {
|
|
3308
3374
|
const results = [];
|
|
3309
3375
|
const batchWarningMode = input.warningMode ?? "aggregated";
|
|
3310
3376
|
const { input: _discardedInput, ...sharedInput } = input;
|
|
@@ -3331,7 +3397,13 @@ export class SourceService {
|
|
|
3331
3397
|
});
|
|
3332
3398
|
}
|
|
3333
3399
|
}
|
|
3334
|
-
|
|
3400
|
+
const output = this.buildValidateMixinOutput(mode, results);
|
|
3401
|
+
return this.applyValidateMixinOutputCompaction({
|
|
3402
|
+
...output,
|
|
3403
|
+
warnings: additionalWarnings.length === 0
|
|
3404
|
+
? output.warnings
|
|
3405
|
+
: [...new Set([...output.warnings, ...additionalWarnings])]
|
|
3406
|
+
}, input);
|
|
3335
3407
|
}
|
|
3336
3408
|
applyValidateMixinOutputCompaction(output, input) {
|
|
3337
3409
|
let nextOutput = output;
|
|
@@ -4045,6 +4117,38 @@ export class SourceService {
|
|
|
4045
4117
|
details
|
|
4046
4118
|
});
|
|
4047
4119
|
}
|
|
4120
|
+
rejectLifecycleClassLikeInput(input) {
|
|
4121
|
+
if (!looksLikeClassSegment(input.methodName)) {
|
|
4122
|
+
return;
|
|
4123
|
+
}
|
|
4124
|
+
const classLikeSymbol = `${input.className}.${input.methodName}`;
|
|
4125
|
+
throw createError({
|
|
4126
|
+
code: ERROR_CODES.INVALID_INPUT,
|
|
4127
|
+
message: `symbol must be in the form "fully.qualified.Class.method".`,
|
|
4128
|
+
details: {
|
|
4129
|
+
symbol: input.symbol,
|
|
4130
|
+
classLikeSymbol,
|
|
4131
|
+
nextAction: "Pass lifecycle input as Class.method and use the separate descriptor field for exact overload matching.",
|
|
4132
|
+
suggestedCall: input.version
|
|
4133
|
+
? {
|
|
4134
|
+
tool: "check-symbol-exists",
|
|
4135
|
+
params: {
|
|
4136
|
+
version: input.version,
|
|
4137
|
+
kind: "class",
|
|
4138
|
+
name: classLikeSymbol,
|
|
4139
|
+
sourceMapping: input.mapping
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
: undefined
|
|
4143
|
+
}
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
releaseLifecycleMappingGraph(version, sourcePriority) {
|
|
4147
|
+
if ("releaseGraphCacheEntry" in this.mappingService &&
|
|
4148
|
+
typeof this.mappingService.releaseGraphCacheEntry === "function") {
|
|
4149
|
+
this.mappingService.releaseGraphCacheEntry(version, sourcePriority);
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4048
4152
|
async resolveToObfuscatedClassName(className, version, mapping, sourcePriority, warnings) {
|
|
4049
4153
|
return this.resolveClassNameForLookup({
|
|
4050
4154
|
className,
|
|
@@ -11,128 +11,126 @@ export const TOOL_SURFACE_SECTION_IDS = [
|
|
|
11
11
|
const SECTION_ROWS = {
|
|
12
12
|
"v3-entry-tools": {
|
|
13
13
|
en: [
|
|
14
|
-
"| `inspect-minecraft` |
|
|
15
|
-
"| `analyze-symbol` |
|
|
16
|
-
"| `compare-minecraft` | Compare version pairs, class
|
|
17
|
-
"| `analyze-mod` |
|
|
18
|
-
"| `validate-project` |
|
|
19
|
-
"| `manage-cache` |
|
|
14
|
+
"| `inspect-minecraft` | Inspect versions, artifacts, classes, files, source text, and workspace-aware lookup flows |",
|
|
15
|
+
"| `analyze-symbol` | Handle symbol existence checks, namespace mapping, lifecycle tracing, workspace symbol resolution, and API overviews |",
|
|
16
|
+
"| `compare-minecraft` | Compare version pairs, class diffs, registry diffs, and migration-oriented summaries |",
|
|
17
|
+
"| `analyze-mod` | Summarize mod metadata, decompile and search mod code, inspect class source, and preview or apply remaps |",
|
|
18
|
+
"| `validate-project` | Summarize workspaces and run direct Mixin or Access Widener validation |",
|
|
19
|
+
"| `manage-cache` | List, verify, and preview or apply cache cleanup and rebuild operations |"
|
|
20
20
|
],
|
|
21
21
|
ja: [
|
|
22
|
-
"| `inspect-minecraft` |
|
|
23
|
-
"| `analyze-symbol` |
|
|
24
|
-
"| `compare-minecraft` |
|
|
25
|
-
"| `analyze-mod` | Mod
|
|
26
|
-
"| `validate-project` | ワークスペース要約と、Mixin / Access Widener
|
|
27
|
-
"| `manage-cache` |
|
|
22
|
+
"| `inspect-minecraft` | バージョン、アーティファクト、クラス、ファイル、ソース本文、ワークスペース文脈の調査フローをまとめて扱う |",
|
|
23
|
+
"| `analyze-symbol` | シンボル存在確認、名前空間変換、ライフサイクル追跡、ワークスペースシンボル解決、API 概要をまとめて扱う |",
|
|
24
|
+
"| `compare-minecraft` | バージョン差分、クラス差分、レジストリ差分、移行向け概要を比較する |",
|
|
25
|
+
"| `analyze-mod` | Mod メタデータの要約、Mod コードのデコンパイル / 検索、クラスソース確認、リマップのプレビュー / 実行を扱う |",
|
|
26
|
+
"| `validate-project` | ワークスペース要約と、Mixin / Access Widener の直接検証を行う |",
|
|
27
|
+
"| `manage-cache` | キャッシュの一覧、検証、クリーンアップ / 再構築のプレビュー / 実行を行う |"
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"source-exploration": {
|
|
31
31
|
en: [
|
|
32
|
-
"| `list-versions` | List available Minecraft versions from Mojang
|
|
33
|
-
"| `resolve-artifact` | Resolve source
|
|
34
|
-
"| `find-class` |
|
|
35
|
-
"| `get-class-source` |
|
|
36
|
-
"| `get-class-members` |
|
|
37
|
-
"| `search-class-source` | Search indexed class source
|
|
38
|
-
"| `get-artifact-file` | Read full source file with byte
|
|
39
|
-
"| `list-artifact-files` | List indexed source file paths with cursor pagination |
|
|
40
|
-
"| `index-artifact` | Rebuild
|
|
32
|
+
"| `list-versions` | List available Minecraft versions from Mojang metadata and local cache |",
|
|
33
|
+
"| `resolve-artifact` | Resolve source artifacts from versions, JAR paths, or Maven coordinates |",
|
|
34
|
+
"| `find-class` | Find simple or fully-qualified class names inside an artifact |",
|
|
35
|
+
"| `get-class-source` | Read class source from an artifact or resolve the backing artifact on demand |",
|
|
36
|
+
"| `get-class-members` | List constructors, fields, and methods from bytecode |",
|
|
37
|
+
"| `search-class-source` | Search indexed class source by symbol, text, or path |",
|
|
38
|
+
"| `get-artifact-file` | Read a full source file with a byte limit |",
|
|
39
|
+
"| `list-artifact-files` | List indexed source file paths with cursor pagination |",
|
|
40
|
+
"| `index-artifact` | Rebuild indexed metadata for an existing artifact |"
|
|
41
41
|
],
|
|
42
42
|
ja: [
|
|
43
|
-
"| `list-versions` | Mojang
|
|
44
|
-
"| `resolve-artifact` |
|
|
45
|
-
"| `find-class` |
|
|
46
|
-
"| `get-class-source` |
|
|
47
|
-
"| `get-class-members` |
|
|
48
|
-
"| `search-class-source` |
|
|
49
|
-
"| `get-artifact-file` | バイト上限付きでソースファイル全体を読み取る |
|
|
50
|
-
"| `list-artifact-files` |
|
|
51
|
-
"| `index-artifact` |
|
|
43
|
+
"| `list-versions` | Mojang メタデータとローカルキャッシュから利用可能な Minecraft バージョンを一覧表示する |",
|
|
44
|
+
"| `resolve-artifact` | バージョン、JAR パス、Maven 座標からソースアーティファクトを解決する |",
|
|
45
|
+
"| `find-class` | アーティファクト内で簡易名または完全修飾クラス名を探す |",
|
|
46
|
+
"| `get-class-source` | アーティファクトからクラスソースを読み取り、必要に応じて背後のアーティファクトを解決する |",
|
|
47
|
+
"| `get-class-members` | バイトコードからコンストラクタ、フィールド、メソッドを一覧化する |",
|
|
48
|
+
"| `search-class-source` | インデックス化されたクラスソースをシンボル、テキスト、パスで検索する |",
|
|
49
|
+
"| `get-artifact-file` | バイト上限付きでソースファイル全体を読み取る |",
|
|
50
|
+
"| `list-artifact-files` | インデックス化されたソースファイルパスをカーソルページネーション付きで一覧表示する |",
|
|
51
|
+
"| `index-artifact` | 既存アーティファクトのインデックスメタデータを再構築する |"
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
54
|
"version-comparison-symbol-tracking": {
|
|
55
55
|
en: [
|
|
56
|
-
"| `trace-symbol-lifecycle` | Trace when `Class.method` exists across Minecraft versions
|
|
57
|
-
"| `diff-class-signatures` | Compare one class
|
|
58
|
-
"| `compare-versions` | Compare class
|
|
56
|
+
"| `trace-symbol-lifecycle` | Trace when `Class.method` exists across Minecraft versions |",
|
|
57
|
+
"| `diff-class-signatures` | Compare one class across two versions and return member deltas |",
|
|
58
|
+
"| `compare-versions` | Compare class and registry changes between two versions |"
|
|
59
59
|
],
|
|
60
60
|
ja: [
|
|
61
|
-
"| `trace-symbol-lifecycle` | `Class.method` が Minecraft
|
|
62
|
-
"| `diff-class-signatures` | 2 つのバージョン間で 1 つのクラスを比較し、メンバー差分を返す |
|
|
63
|
-
"| `compare-versions` | 2
|
|
61
|
+
"| `trace-symbol-lifecycle` | `Class.method` が Minecraft のどのバージョンで存在するかを追跡する |",
|
|
62
|
+
"| `diff-class-signatures` | 2 つのバージョン間で 1 つのクラスを比較し、メンバー差分を返す |",
|
|
63
|
+
"| `compare-versions` | 2 つのバージョン間でクラスとレジストリの変更を比較する |"
|
|
64
64
|
]
|
|
65
65
|
},
|
|
66
66
|
"mapping-symbols": {
|
|
67
67
|
en: [
|
|
68
|
-
"| `find-mapping` |
|
|
69
|
-
"| `resolve-method-mapping-exact` | Resolve one method mapping with strict owner
|
|
70
|
-
"| `get-class-api-matrix` | Show one class API
|
|
71
|
-
"| `resolve-workspace-symbol` | Resolve compile-visible symbol names
|
|
72
|
-
"| `check-symbol-exists` |
|
|
68
|
+
"| `find-mapping` | Look up mapping candidates for class, field, or method symbols |",
|
|
69
|
+
"| `resolve-method-mapping-exact` | Resolve one method mapping with strict owner, name, and descriptor matching |",
|
|
70
|
+
"| `get-class-api-matrix` | Show one class API across `obfuscated`, `mojang`, `intermediary`, and `yarn` |",
|
|
71
|
+
"| `resolve-workspace-symbol` | Resolve compile-visible symbol names from a Gradle workspace |",
|
|
72
|
+
"| `check-symbol-exists` | Check whether a class, field, or method exists in a namespace |"
|
|
73
73
|
],
|
|
74
74
|
ja: [
|
|
75
|
-
"| `find-mapping` |
|
|
76
|
-
"| `resolve-method-mapping-exact` | owner
|
|
77
|
-
"| `get-class-api-matrix` | 1 つのクラス API
|
|
78
|
-
"| `resolve-workspace-symbol` | Gradle
|
|
79
|
-
"| `check-symbol-exists` |
|
|
75
|
+
"| `find-mapping` | クラス、フィールド、メソッドのシンボルに対するマッピング候補を調べる |",
|
|
76
|
+
"| `resolve-method-mapping-exact` | owner、name、descriptor の厳密一致で 1 つのメソッドマッピングを解決する |",
|
|
77
|
+
"| `get-class-api-matrix` | 1 つのクラス API を `obfuscated`、`mojang`、`intermediary`、`yarn` で見比べる |",
|
|
78
|
+
"| `resolve-workspace-symbol` | Gradle ワークスペースからコンパイル時に見えるシンボル名を解決する |",
|
|
79
|
+
"| `check-symbol-exists` | 名前空間内でクラス、フィールド、メソッドが存在するかを確認する |"
|
|
80
80
|
]
|
|
81
81
|
},
|
|
82
82
|
"nbt-utilities": {
|
|
83
83
|
en: [
|
|
84
|
-
"| `nbt-to-json` | Decode Java Edition NBT binary
|
|
85
|
-
"| `nbt-apply-json-patch` | Apply RFC 6902
|
|
86
|
-
"| `json-to-nbt` | Encode typed JSON back to Java Edition NBT binary
|
|
84
|
+
"| `nbt-to-json` | Decode Java Edition NBT binary payloads into typed JSON |",
|
|
85
|
+
"| `nbt-apply-json-patch` | Apply RFC 6902 patches to typed NBT JSON |",
|
|
86
|
+
"| `json-to-nbt` | Encode typed JSON back to Java Edition NBT binary |"
|
|
87
87
|
],
|
|
88
88
|
ja: [
|
|
89
|
-
"| `nbt-to-json` | Java Edition の NBT
|
|
90
|
-
"| `nbt-apply-json-patch` |
|
|
91
|
-
"| `json-to-nbt` | 型付き JSON を Java Edition の NBT
|
|
89
|
+
"| `nbt-to-json` | Java Edition の NBT バイナリを型付き JSON にデコードする |",
|
|
90
|
+
"| `nbt-apply-json-patch` | 型付き NBT JSON に RFC 6902 パッチを適用する |",
|
|
91
|
+
"| `json-to-nbt` | 型付き JSON を Java Edition の NBT バイナリへ再エンコードする |"
|
|
92
92
|
]
|
|
93
93
|
},
|
|
94
94
|
"mod-analysis": {
|
|
95
95
|
en: [
|
|
96
|
-
"| `analyze-mod-jar` | Extract mod metadata
|
|
97
|
-
"| `decompile-mod-jar` | Decompile mod JAR and optionally return one class source |
|
|
98
|
-
"| `get-mod-class-source` | Read one class source from decompiled mod cache |
|
|
99
|
-
"| `search-mod-source` | Search decompiled mod source by class
|
|
100
|
-
"| `remap-mod-jar` | Remap a Fabric
|
|
96
|
+
"| `analyze-mod-jar` | Extract mod metadata, dependencies, entrypoints, and mixin config info from a JAR |",
|
|
97
|
+
"| `decompile-mod-jar` | Decompile a mod JAR and optionally return one class source |",
|
|
98
|
+
"| `get-mod-class-source` | Read one class source from the decompiled mod cache |",
|
|
99
|
+
"| `search-mod-source` | Search decompiled mod source by class, method, field, or content |",
|
|
100
|
+
"| `remap-mod-jar` | Remap a Fabric or Quilt mod JAR to `yarn` or `mojang` names |"
|
|
101
101
|
],
|
|
102
102
|
ja: [
|
|
103
|
-
"| `analyze-mod-jar` |
|
|
104
|
-
"| `decompile-mod-jar` | Mod JAR をデコンパイルし、必要に応じて 1 つのクラスソースを返す |
|
|
105
|
-
"| `get-mod-class-source` | デコンパイル済み Mod キャッシュから 1 つのクラスソースを読み取る |
|
|
106
|
-
"| `search-mod-source` | デコンパイル済み Mod ソースを class
|
|
107
|
-
"| `remap-mod-jar` | Fabric
|
|
103
|
+
"| `analyze-mod-jar` | JAR から Mod メタデータ、依存関係、エントリポイント、Mixin 設定情報を抽出する |",
|
|
104
|
+
"| `decompile-mod-jar` | Mod JAR をデコンパイルし、必要に応じて 1 つのクラスソースを返す |",
|
|
105
|
+
"| `get-mod-class-source` | デコンパイル済み Mod キャッシュから 1 つのクラスソースを読み取る |",
|
|
106
|
+
"| `search-mod-source` | デコンパイル済み Mod ソースを class、method、field、content で検索する |",
|
|
107
|
+
"| `remap-mod-jar` | Fabric または Quilt の Mod JAR を `yarn` または `mojang` 名へリマップする |"
|
|
108
108
|
]
|
|
109
109
|
},
|
|
110
110
|
"validation": {
|
|
111
111
|
en: [
|
|
112
|
-
"| `validate-mixin` |
|
|
113
|
-
"| `validate-access-widener` |
|
|
112
|
+
"| `validate-mixin` | Validate Mixin source against a target Minecraft version |",
|
|
113
|
+
"| `validate-access-widener` | Validate Access Widener content against a target Minecraft version |"
|
|
114
114
|
],
|
|
115
115
|
ja: [
|
|
116
|
-
"| `validate-mixin` | 対象 Minecraft バージョンに対して Mixin
|
|
117
|
-
"| `validate-access-widener` |
|
|
116
|
+
"| `validate-mixin` | 対象 Minecraft バージョンに対して Mixin ソースを検証する |",
|
|
117
|
+
"| `validate-access-widener` | 対象 Minecraft バージョンに対して Access Widener の内容を検証する |"
|
|
118
118
|
]
|
|
119
119
|
},
|
|
120
120
|
"registry-diagnostics": {
|
|
121
121
|
en: [
|
|
122
|
-
"| `get-registry-data` |
|
|
123
|
-
"| `get-runtime-metrics` | Inspect runtime
|
|
122
|
+
"| `get-registry-data` | Read generated registry snapshots and optionally include entry data |",
|
|
123
|
+
"| `get-runtime-metrics` | Inspect runtime metrics and latency snapshots |"
|
|
124
124
|
],
|
|
125
125
|
ja: [
|
|
126
|
-
"| `get-registry-data` |
|
|
127
|
-
"| `get-runtime-metrics` |
|
|
126
|
+
"| `get-registry-data` | 生成済みレジストリスナップショットを読み取り、必要に応じてエントリデータも含める |",
|
|
127
|
+
"| `get-runtime-metrics` | ランタイムメトリクスとレイテンシスナップショットを確認する |"
|
|
128
128
|
]
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
131
|
export function renderToolSurfaceSection(locale, sectionId) {
|
|
132
|
-
const header = locale === "en"
|
|
133
|
-
|
|
134
|
-
: "| ツール | 役割 | 主な入力 | 主な出力 |";
|
|
135
|
-
const divider = "| --- | --- | --- | --- |";
|
|
132
|
+
const header = locale === "en" ? "| Tool | Purpose |" : "| ツール | 役割 |";
|
|
133
|
+
const divider = "| --- | --- |";
|
|
136
134
|
const rows = SECTION_ROWS[sectionId][locale];
|
|
137
135
|
return [header, divider, ...rows].join("\n");
|
|
138
136
|
}
|