@adhisang/minecraft-modding-mcp 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +86 -46
- package/dist/index.js +150 -174
- package/dist/mapping-pipeline-service.d.ts +1 -1
- package/dist/mapping-pipeline-service.js +5 -5
- package/dist/mapping-service.d.ts +3 -4
- package/dist/mapping-service.js +40 -46
- package/dist/mcp-helpers.d.ts +10 -2
- package/dist/mcp-helpers.js +59 -5
- package/dist/minecraft-explorer-service.d.ts +1 -1
- package/dist/minecraft-explorer-service.js +1 -1
- package/dist/mixin-validator.js +5 -5
- package/dist/mojang-tiny-mapping-service.js +26 -26
- package/dist/resources.js +7 -7
- package/dist/search-hit-accumulator.d.ts +0 -3
- package/dist/search-hit-accumulator.js +4 -4
- package/dist/source-resolver.d.ts +1 -0
- package/dist/source-resolver.js +94 -2
- package/dist/source-service.d.ts +34 -43
- package/dist/source-service.js +597 -670
- package/dist/storage/files-repo.d.ts +9 -0
- package/dist/storage/files-repo.js +42 -0
- package/dist/storage/migrations.d.ts +1 -1
- package/dist/storage/migrations.js +6 -2
- package/dist/storage/schema.d.ts +1 -0
- package/dist/storage/schema.js +7 -0
- package/dist/tool-input.d.ts +6 -0
- package/dist/tool-input.js +64 -0
- package/dist/types.d.ts +1 -1
- package/package.json +4 -1
package/dist/mapping-service.js
CHANGED
|
@@ -7,7 +7,7 @@ import { defaultDownloadPath, downloadToCache } from "./repo-downloader.js";
|
|
|
7
7
|
import { listJarEntries, readJarEntryAsUtf8 } from "./source-jar-reader.js";
|
|
8
8
|
import { VersionService, isUnobfuscatedVersion } from "./version-service.js";
|
|
9
9
|
const SUPPORTED_MAPPINGS = new Set([
|
|
10
|
-
"
|
|
10
|
+
"obfuscated",
|
|
11
11
|
"mojang",
|
|
12
12
|
"intermediary",
|
|
13
13
|
"yarn"
|
|
@@ -254,7 +254,7 @@ const PROGUARD_PRIMITIVES = {
|
|
|
254
254
|
/**
|
|
255
255
|
* Convert a single proguard type (e.g. "int", "net.minecraft.Foo", "int[][]")
|
|
256
256
|
* to JVM notation (e.g. "I", "Lnet/minecraft/Foo;", "[[I").
|
|
257
|
-
* `classLookup` maps mojang class names →
|
|
257
|
+
* `classLookup` maps mojang class names → obfuscated class names (for the obfuscated descriptor).
|
|
258
258
|
* Pass `undefined` to skip class name translation (for mojang descriptors).
|
|
259
259
|
*/
|
|
260
260
|
function proguardTypeToJvm(type, classLookup) {
|
|
@@ -294,12 +294,12 @@ function parseProguardMethod(value, classLookup) {
|
|
|
294
294
|
return { name, descriptor: `(${paramDescriptor})${returnDescriptor}` };
|
|
295
295
|
}
|
|
296
296
|
function parseClientMappings(text) {
|
|
297
|
-
const
|
|
298
|
-
const
|
|
297
|
+
const obfuscatedToMojang = createDirectionIndex();
|
|
298
|
+
const mojangToObfuscated = createDirectionIndex();
|
|
299
299
|
// Two-pass parsing: first collect class name mappings, then parse members with descriptors.
|
|
300
300
|
const lines = text.split(/\r?\n/);
|
|
301
|
-
// Pass 1: collect class name mappings (mojang →
|
|
302
|
-
const
|
|
301
|
+
// Pass 1: collect class name mappings (mojang → obfuscated)
|
|
302
|
+
const mojangToObfuscatedClass = new Map();
|
|
303
303
|
let classCount = 0;
|
|
304
304
|
for (const rawLine of lines) {
|
|
305
305
|
const line = rawLine.trim();
|
|
@@ -309,9 +309,9 @@ function parseClientMappings(text) {
|
|
|
309
309
|
const classMatch = /^(.+?)\s+->\s+(.+):$/.exec(line);
|
|
310
310
|
if (classMatch) {
|
|
311
311
|
const mojangClass = classMatch[1]?.trim() ?? "";
|
|
312
|
-
const
|
|
313
|
-
if (mojangClass &&
|
|
314
|
-
|
|
312
|
+
const obfuscatedClass = classMatch[2]?.trim() ?? "";
|
|
313
|
+
if (mojangClass && obfuscatedClass) {
|
|
314
|
+
mojangToObfuscatedClass.set(mojangClass, obfuscatedClass);
|
|
315
315
|
classCount += 1;
|
|
316
316
|
}
|
|
317
317
|
}
|
|
@@ -332,17 +332,17 @@ function parseClientMappings(text) {
|
|
|
332
332
|
const classMatch = /^(.+?)\s+->\s+(.+):$/.exec(line);
|
|
333
333
|
if (classMatch) {
|
|
334
334
|
const mojangClass = classMatch[1]?.trim() ?? "";
|
|
335
|
-
const
|
|
336
|
-
if (!mojangClass || !
|
|
335
|
+
const obfuscatedClass = classMatch[2]?.trim() ?? "";
|
|
336
|
+
if (!mojangClass || !obfuscatedClass) {
|
|
337
337
|
currentClass = undefined;
|
|
338
338
|
continue;
|
|
339
339
|
}
|
|
340
340
|
currentClass = {
|
|
341
|
-
|
|
341
|
+
obfuscated: obfuscatedClass,
|
|
342
342
|
mojang: mojangClass
|
|
343
343
|
};
|
|
344
|
-
addLookupEntries(
|
|
345
|
-
addLookupEntries(
|
|
344
|
+
addLookupEntries(obfuscatedToMojang, createClassSymbolRecord(obfuscatedClass), createClassSymbolRecord(mojangClass));
|
|
345
|
+
addLookupEntries(mojangToObfuscated, createClassSymbolRecord(mojangClass), createClassSymbolRecord(obfuscatedClass));
|
|
346
346
|
continue;
|
|
347
347
|
}
|
|
348
348
|
if (!currentClass) {
|
|
@@ -359,31 +359,31 @@ function parseClientMappings(text) {
|
|
|
359
359
|
}
|
|
360
360
|
const mojangMemberSignature = stripLineInfo(leftRaw);
|
|
361
361
|
// Try method parsing with JVM descriptor
|
|
362
|
-
const
|
|
363
|
-
if (
|
|
362
|
+
const obfuscatedMethod = parseProguardMethod(mojangMemberSignature, mojangToObfuscatedClass);
|
|
363
|
+
if (obfuscatedMethod) {
|
|
364
364
|
const mojangMethod = parseProguardMethod(mojangMemberSignature, undefined);
|
|
365
|
-
const
|
|
365
|
+
const obfuscatedDescriptor = obfuscatedMethod.descriptor;
|
|
366
366
|
const mojangDescriptor = mojangMethod?.descriptor;
|
|
367
|
-
addLookupEntries(
|
|
368
|
-
addLookupEntries(
|
|
367
|
+
addLookupEntries(obfuscatedToMojang, createMethodSymbolRecord(currentClass.obfuscated, rightRaw, obfuscatedDescriptor), createMethodSymbolRecord(currentClass.mojang, obfuscatedMethod.name, mojangDescriptor));
|
|
368
|
+
addLookupEntries(mojangToObfuscated, createMethodSymbolRecord(currentClass.mojang, obfuscatedMethod.name, mojangDescriptor), createMethodSymbolRecord(currentClass.obfuscated, rightRaw, obfuscatedDescriptor));
|
|
369
369
|
continue;
|
|
370
370
|
}
|
|
371
371
|
const fieldName = parseFieldName(mojangMemberSignature);
|
|
372
372
|
if (!fieldName) {
|
|
373
373
|
continue;
|
|
374
374
|
}
|
|
375
|
-
addLookupEntries(
|
|
376
|
-
addLookupEntries(
|
|
375
|
+
addLookupEntries(obfuscatedToMojang, createFieldSymbolRecord(currentClass.obfuscated, rightRaw), createFieldSymbolRecord(currentClass.mojang, fieldName));
|
|
376
|
+
addLookupEntries(mojangToObfuscated, createFieldSymbolRecord(currentClass.mojang, fieldName), createFieldSymbolRecord(currentClass.obfuscated, rightRaw));
|
|
377
377
|
}
|
|
378
378
|
const result = new Map();
|
|
379
|
-
result.set(pairKey("
|
|
380
|
-
result.set(pairKey("mojang", "
|
|
379
|
+
result.set(pairKey("obfuscated", "mojang"), obfuscatedToMojang);
|
|
380
|
+
result.set(pairKey("mojang", "obfuscated"), mojangToObfuscated);
|
|
381
381
|
return result;
|
|
382
382
|
}
|
|
383
383
|
function normalizeTinyNamespace(namespace) {
|
|
384
384
|
const normalized = namespace.trim().toLowerCase();
|
|
385
|
-
if (normalized === "
|
|
386
|
-
return "
|
|
385
|
+
if (normalized === "obfuscated") {
|
|
386
|
+
return "obfuscated";
|
|
387
387
|
}
|
|
388
388
|
if (normalized === "mojang") {
|
|
389
389
|
return "mojang";
|
|
@@ -973,8 +973,8 @@ export class MappingService {
|
|
|
973
973
|
sourceMapping,
|
|
974
974
|
targetMapping,
|
|
975
975
|
sourcePriority: priority,
|
|
976
|
-
nextAction: "Try mapping=
|
|
977
|
-
suggestedCall: { tool: "resolve-artifact", params: { mapping: "
|
|
976
|
+
nextAction: "Try mapping=obfuscated which is always available.",
|
|
977
|
+
suggestedCall: { tool: "resolve-artifact", params: { mapping: "obfuscated" } }
|
|
978
978
|
}
|
|
979
979
|
});
|
|
980
980
|
}
|
|
@@ -1000,16 +1000,10 @@ export class MappingService {
|
|
|
1000
1000
|
}
|
|
1001
1001
|
});
|
|
1002
1002
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
details: {
|
|
1008
|
-
kind: input.kind
|
|
1009
|
-
}
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
const { record: queryRecord, querySymbol } = normalizeQuerySymbol(input);
|
|
1003
|
+
const { record: queryRecord, querySymbol } = normalizeQuerySymbol({
|
|
1004
|
+
...input,
|
|
1005
|
+
kind: "method"
|
|
1006
|
+
});
|
|
1013
1007
|
const owner = queryRecord.owner;
|
|
1014
1008
|
const method = queryRecord.name;
|
|
1015
1009
|
const descriptor = queryRecord.descriptor;
|
|
@@ -1159,7 +1153,7 @@ export class MappingService {
|
|
|
1159
1153
|
classByMapping[mapping] = mapped[0];
|
|
1160
1154
|
}
|
|
1161
1155
|
}
|
|
1162
|
-
const baseMapping = classByMapping.
|
|
1156
|
+
const baseMapping = classByMapping.obfuscated ? "obfuscated" : classNameMapping;
|
|
1163
1157
|
const baseClass = classByMapping[baseMapping];
|
|
1164
1158
|
if (!baseClass) {
|
|
1165
1159
|
return {
|
|
@@ -1167,7 +1161,7 @@ export class MappingService {
|
|
|
1167
1161
|
className,
|
|
1168
1162
|
classNameMapping,
|
|
1169
1163
|
classIdentity: {
|
|
1170
|
-
|
|
1164
|
+
obfuscated: classByMapping.obfuscated?.symbol,
|
|
1171
1165
|
mojang: classByMapping.mojang?.symbol,
|
|
1172
1166
|
intermediary: classByMapping.intermediary?.symbol,
|
|
1173
1167
|
yarn: classByMapping.yarn?.symbol
|
|
@@ -1255,7 +1249,7 @@ export class MappingService {
|
|
|
1255
1249
|
};
|
|
1256
1250
|
row[mapping] = entry;
|
|
1257
1251
|
}
|
|
1258
|
-
row.completeness = Boolean(row.
|
|
1252
|
+
row.completeness = Boolean(row.obfuscated && row.mojang && row.intermediary && row.yarn);
|
|
1259
1253
|
rows.push(row);
|
|
1260
1254
|
if (rowHadAmbiguity) {
|
|
1261
1255
|
ambiguousRowCount += 1;
|
|
@@ -1266,7 +1260,7 @@ export class MappingService {
|
|
|
1266
1260
|
className,
|
|
1267
1261
|
classNameMapping,
|
|
1268
1262
|
classIdentity: {
|
|
1269
|
-
|
|
1263
|
+
obfuscated: classByMapping.obfuscated?.symbol,
|
|
1270
1264
|
mojang: classByMapping.mojang?.symbol,
|
|
1271
1265
|
intermediary: classByMapping.intermediary?.symbol,
|
|
1272
1266
|
yarn: classByMapping.yarn?.symbol
|
|
@@ -1568,16 +1562,16 @@ export class MappingService {
|
|
|
1568
1562
|
if (!tinyAvailable) {
|
|
1569
1563
|
degradations.push("No intermediary/yarn tiny mappings were found for this version.");
|
|
1570
1564
|
}
|
|
1571
|
-
// Check if member remap path exists (requestedMapping →
|
|
1565
|
+
// Check if member remap path exists (requestedMapping → obfuscated)
|
|
1572
1566
|
let memberRemapAvailable = false;
|
|
1573
|
-
if (input.requestedMapping === "
|
|
1567
|
+
if (input.requestedMapping === "obfuscated") {
|
|
1574
1568
|
memberRemapAvailable = true;
|
|
1575
1569
|
}
|
|
1576
1570
|
else {
|
|
1577
|
-
const path = namespacePath(graph.pairs, input.requestedMapping, "
|
|
1571
|
+
const path = namespacePath(graph.pairs, input.requestedMapping, "obfuscated");
|
|
1578
1572
|
memberRemapAvailable = path != null && path.length > 1;
|
|
1579
1573
|
if (!memberRemapAvailable) {
|
|
1580
|
-
degradations.push(`No mapping path from ${input.requestedMapping} to
|
|
1574
|
+
degradations.push(`No mapping path from ${input.requestedMapping} to obfuscated; member remap will fail.`);
|
|
1581
1575
|
}
|
|
1582
1576
|
}
|
|
1583
1577
|
return {
|
|
@@ -1618,7 +1612,7 @@ export class MappingService {
|
|
|
1618
1612
|
priority,
|
|
1619
1613
|
pairs: new Map(),
|
|
1620
1614
|
warnings: [
|
|
1621
|
-
`Version ${version} is unobfuscated; mapping graph is empty
|
|
1615
|
+
`Version ${version} is unobfuscated; mapping graph is empty because the runtime already uses deobfuscated names.`
|
|
1622
1616
|
]
|
|
1623
1617
|
};
|
|
1624
1618
|
}
|
package/dist/mcp-helpers.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
|
|
2
|
+
import { type ErrorCode } from "./errors.js";
|
|
3
|
+
type ObjectResultOptions = {
|
|
4
|
+
isError?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function objectResult<T extends Record<string, unknown>>(data: T, options?: ObjectResultOptions): CallToolResult;
|
|
3
7
|
export declare function textResource(uri: string, value: string): ReadResourceResult;
|
|
4
8
|
export declare function objectResource(uri: string, data: Record<string, unknown>): ReadResourceResult;
|
|
5
|
-
export declare function errorResource(uri: string,
|
|
9
|
+
export declare function errorResource(uri: string, error: string | {
|
|
10
|
+
message: string;
|
|
11
|
+
code?: ErrorCode;
|
|
12
|
+
}): ReadResourceResult;
|
|
13
|
+
export {};
|
package/dist/mcp-helpers.js
CHANGED
|
@@ -1,13 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { ERROR_CODES } from "./errors.js";
|
|
2
|
+
export function objectResult(data, options = {}) {
|
|
3
|
+
return {
|
|
4
|
+
content: [{ type: "text", text: JSON.stringify(data) }],
|
|
5
|
+
structuredContent: data,
|
|
6
|
+
...(options.isError ? { isError: true } : {})
|
|
7
|
+
};
|
|
3
8
|
}
|
|
4
9
|
export function textResource(uri, value) {
|
|
5
10
|
return { contents: [{ uri, text: value }] };
|
|
6
11
|
}
|
|
7
12
|
export function objectResource(uri, data) {
|
|
8
|
-
return {
|
|
13
|
+
return {
|
|
14
|
+
contents: [
|
|
15
|
+
{
|
|
16
|
+
uri,
|
|
17
|
+
mimeType: "application/json",
|
|
18
|
+
text: JSON.stringify({
|
|
19
|
+
result: data,
|
|
20
|
+
meta: { uri }
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
};
|
|
9
25
|
}
|
|
10
|
-
|
|
11
|
-
|
|
26
|
+
function statusForResourceErrorCode(code) {
|
|
27
|
+
if (code === ERROR_CODES.INVALID_INPUT) {
|
|
28
|
+
return 400;
|
|
29
|
+
}
|
|
30
|
+
if (code === ERROR_CODES.FILE_NOT_FOUND ||
|
|
31
|
+
code === ERROR_CODES.SOURCE_NOT_FOUND ||
|
|
32
|
+
code === ERROR_CODES.CLASS_NOT_FOUND ||
|
|
33
|
+
code === ERROR_CODES.VERSION_NOT_FOUND ||
|
|
34
|
+
code === ERROR_CODES.JAR_NOT_FOUND) {
|
|
35
|
+
return 404;
|
|
36
|
+
}
|
|
37
|
+
if (code === ERROR_CODES.MAPPING_UNAVAILABLE ||
|
|
38
|
+
code === ERROR_CODES.MAPPING_NOT_APPLIED ||
|
|
39
|
+
code === ERROR_CODES.NAMESPACE_MISMATCH) {
|
|
40
|
+
return 422;
|
|
41
|
+
}
|
|
42
|
+
return 500;
|
|
43
|
+
}
|
|
44
|
+
export function errorResource(uri, error) {
|
|
45
|
+
const detail = typeof error === "string" ? error : error.message;
|
|
46
|
+
const code = typeof error === "string" ? ERROR_CODES.INVALID_INPUT : error.code ?? ERROR_CODES.INTERNAL;
|
|
47
|
+
return {
|
|
48
|
+
contents: [
|
|
49
|
+
{
|
|
50
|
+
uri,
|
|
51
|
+
mimeType: "application/json",
|
|
52
|
+
text: JSON.stringify({
|
|
53
|
+
error: {
|
|
54
|
+
type: "https://minecraft-modding-mcp.dev/problems/resource",
|
|
55
|
+
title: "Resource read failed",
|
|
56
|
+
detail,
|
|
57
|
+
status: statusForResourceErrorCode(code),
|
|
58
|
+
code,
|
|
59
|
+
instance: uri
|
|
60
|
+
},
|
|
61
|
+
meta: { uri }
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
12
66
|
}
|
|
13
67
|
//# sourceMappingURL=mcp-helpers.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Config } from "./types.js";
|
|
2
|
-
export type MappingNamespace = "
|
|
2
|
+
export type MappingNamespace = "obfuscated" | "mojang" | "yarn";
|
|
3
3
|
type SignatureAccess = "public" | "all";
|
|
4
4
|
export interface ResponseContext {
|
|
5
5
|
minecraftVersion: string;
|
|
@@ -531,7 +531,7 @@ export class MinecraftExplorerService {
|
|
|
531
531
|
return {
|
|
532
532
|
minecraftVersion: extractVersionFromPath(jarPath) ?? "unknown",
|
|
533
533
|
mappingType: "unknown",
|
|
534
|
-
mappingNamespace: "
|
|
534
|
+
mappingNamespace: "obfuscated",
|
|
535
535
|
jarHash: artifactSignatureFromFile(jarPath).sourceArtifactId,
|
|
536
536
|
generatedAt: new Date().toISOString()
|
|
537
537
|
};
|
package/dist/mixin-validator.js
CHANGED
|
@@ -161,7 +161,7 @@ function validateInjection(inj, targetMembers, targetNames, issues, resolvedMemb
|
|
|
161
161
|
const isSigFailed = signatureFailedTargets?.has(targetName);
|
|
162
162
|
const issueConfidence = isRemapFailed ? "uncertain" : confidence;
|
|
163
163
|
const issueConfidenceReason = isRemapFailed
|
|
164
|
-
? `Member remap from
|
|
164
|
+
? `Member remap from obfuscated→mapping failed; name mismatch may be a remap artifact, not a true missing member.`
|
|
165
165
|
: confidenceReason;
|
|
166
166
|
const resolutionPath = isRemapFailed
|
|
167
167
|
? "member-remap-failed"
|
|
@@ -207,7 +207,7 @@ function validateShadow(shadow, targetMembers, targetNames, issues, resolvedMemb
|
|
|
207
207
|
const isSigFailed = signatureFailedTargets?.has(targetName);
|
|
208
208
|
const issueConfidence = isRemapFailed ? "uncertain" : confidence;
|
|
209
209
|
const issueConfidenceReason = isRemapFailed
|
|
210
|
-
? `Member remap from
|
|
210
|
+
? `Member remap from obfuscated→mapping failed; name mismatch may be a remap artifact, not a true missing member.`
|
|
211
211
|
: confidenceReason;
|
|
212
212
|
const resolutionPath = isRemapFailed
|
|
213
213
|
? "member-remap-failed"
|
|
@@ -274,7 +274,7 @@ function validateAccessor(accessor, targetMembers, targetNames, issues, resolved
|
|
|
274
274
|
const isSigFailed = signatureFailedTargets?.has(targetName);
|
|
275
275
|
const issueConfidence = isRemapFailed ? "uncertain" : confidence;
|
|
276
276
|
const issueConfidenceReason = isRemapFailed
|
|
277
|
-
? `Member remap from
|
|
277
|
+
? `Member remap from obfuscated→mapping failed; name mismatch may be a remap artifact, not a true missing member.`
|
|
278
278
|
: confidenceReason;
|
|
279
279
|
const resolutionPath = isRemapFailed
|
|
280
280
|
? "member-remap-failed"
|
|
@@ -323,9 +323,9 @@ export function validateParsedMixin(parsed, targetMembers, warnings, provenance,
|
|
|
323
323
|
kind: "target-mapping-failed",
|
|
324
324
|
annotation: "@Mixin",
|
|
325
325
|
target: target.className,
|
|
326
|
-
message: `Could not map target class "${target.className}" to
|
|
326
|
+
message: `Could not map target class "${target.className}" to obfuscated namespace; class may still exist under a different mapping.`,
|
|
327
327
|
confidence: "uncertain",
|
|
328
|
-
confidenceReason: `Mapping from "${provenance?.requestedMapping}" to
|
|
328
|
+
confidenceReason: `Mapping from "${provenance?.requestedMapping}" to obfuscated failed for this class.`,
|
|
329
329
|
category: "mapping",
|
|
330
330
|
resolutionPath: "target-mapping-failed",
|
|
331
331
|
falsePositiveRisk: healthReport?.overallHealthy === false ? "high" : "medium"
|
|
@@ -30,13 +30,13 @@ function parseProguardMappings(text) {
|
|
|
30
30
|
const classMatch = /^(.+?)\s+->\s+(.+):$/.exec(line);
|
|
31
31
|
if (classMatch) {
|
|
32
32
|
const mojangFqn = normalizeFqn(classMatch[1] ?? "");
|
|
33
|
-
const
|
|
34
|
-
if (!mojangFqn || !
|
|
33
|
+
const obfuscatedInternal = normalizeInternalName(classMatch[2] ?? "");
|
|
34
|
+
if (!mojangFqn || !obfuscatedInternal) {
|
|
35
35
|
currentClass = undefined;
|
|
36
36
|
continue;
|
|
37
37
|
}
|
|
38
38
|
currentClass = mojangFqn;
|
|
39
|
-
classes.push({ mojangFqn,
|
|
39
|
+
classes.push({ mojangFqn, obfuscatedInternal });
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
42
42
|
if (!currentClass) {
|
|
@@ -47,14 +47,14 @@ function parseProguardMappings(text) {
|
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
49
|
const leftRaw = stripLineInfo(line.slice(0, arrowIndex));
|
|
50
|
-
const
|
|
51
|
-
if (!leftRaw || !
|
|
50
|
+
const obfuscatedName = line.slice(arrowIndex + 4).trim();
|
|
51
|
+
if (!leftRaw || !obfuscatedName) {
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
54
54
|
members.push({
|
|
55
55
|
ownerMojangFqn: currentClass,
|
|
56
56
|
leftSignature: leftRaw,
|
|
57
|
-
|
|
57
|
+
obfuscatedName
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
return { classes, members };
|
|
@@ -164,8 +164,8 @@ function normalizeMemberMappings(rawMappings, classMap, warnings) {
|
|
|
164
164
|
const seen = new Set();
|
|
165
165
|
for (const mapping of rawMappings) {
|
|
166
166
|
for (const member of mapping.members) {
|
|
167
|
-
const
|
|
168
|
-
if (!
|
|
167
|
+
const ownerObfuscated = classMap.get(normalizeFqn(member.ownerMojangFqn));
|
|
168
|
+
if (!ownerObfuscated) {
|
|
169
169
|
warnings.push(`Skipping member mapping for "${member.ownerMojangFqn}" because class mapping is missing.`);
|
|
170
170
|
continue;
|
|
171
171
|
}
|
|
@@ -183,7 +183,7 @@ function normalizeMemberMappings(rawMappings, classMap, warnings) {
|
|
|
183
183
|
record = {
|
|
184
184
|
kind: "m",
|
|
185
185
|
descriptor,
|
|
186
|
-
|
|
186
|
+
obfuscatedName: member.obfuscatedName,
|
|
187
187
|
mojangName
|
|
188
188
|
};
|
|
189
189
|
}
|
|
@@ -203,19 +203,19 @@ function normalizeMemberMappings(rawMappings, classMap, warnings) {
|
|
|
203
203
|
record = {
|
|
204
204
|
kind: "f",
|
|
205
205
|
descriptor,
|
|
206
|
-
|
|
206
|
+
obfuscatedName: member.obfuscatedName,
|
|
207
207
|
mojangName
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
|
-
const dedupeKey = `${
|
|
210
|
+
const dedupeKey = `${ownerObfuscated}|${record.kind}|${record.obfuscatedName}|` +
|
|
211
211
|
`${record.mojangName}|${record.descriptor}`;
|
|
212
212
|
if (seen.has(dedupeKey)) {
|
|
213
213
|
continue;
|
|
214
214
|
}
|
|
215
215
|
seen.add(dedupeKey);
|
|
216
|
-
const list = membersByOwner.get(
|
|
216
|
+
const list = membersByOwner.get(ownerObfuscated) ?? [];
|
|
217
217
|
list.push(record);
|
|
218
|
-
membersByOwner.set(
|
|
218
|
+
membersByOwner.set(ownerObfuscated, list);
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
return membersByOwner;
|
|
@@ -225,38 +225,38 @@ function mergeClasses(rawMappings, warnings) {
|
|
|
225
225
|
for (const mapping of rawMappings) {
|
|
226
226
|
for (const clazz of mapping.classes) {
|
|
227
227
|
const mojang = normalizeFqn(clazz.mojangFqn);
|
|
228
|
-
const
|
|
228
|
+
const obfuscated = normalizeInternalName(clazz.obfuscatedInternal);
|
|
229
229
|
const existing = classMap.get(mojang);
|
|
230
|
-
if (existing && existing !==
|
|
231
|
-
warnings.push(`Conflicting class mapping for "${mojang}" (${existing} vs ${
|
|
230
|
+
if (existing && existing !== obfuscated) {
|
|
231
|
+
warnings.push(`Conflicting class mapping for "${mojang}" (${existing} vs ${obfuscated}); keeping first.`);
|
|
232
232
|
continue;
|
|
233
233
|
}
|
|
234
|
-
classMap.set(mojang,
|
|
234
|
+
classMap.set(mojang, obfuscated);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
return classMap;
|
|
238
238
|
}
|
|
239
239
|
function renderTinyV2(classMap, membersByOwner) {
|
|
240
240
|
const classEntries = [...classMap.entries()]
|
|
241
|
-
.map(([mojangFqn,
|
|
242
|
-
|
|
241
|
+
.map(([mojangFqn, obfuscatedInternal]) => ({
|
|
242
|
+
obfuscatedInternal,
|
|
243
243
|
mojangInternal: mojangFqn.replace(/\./g, "/")
|
|
244
244
|
}))
|
|
245
|
-
.sort((left, right) => left.
|
|
246
|
-
const lines = ["tiny\t2\t0\
|
|
245
|
+
.sort((left, right) => left.obfuscatedInternal.localeCompare(right.obfuscatedInternal));
|
|
246
|
+
const lines = ["tiny\t2\t0\tobfuscated\tmojang"];
|
|
247
247
|
for (const entry of classEntries) {
|
|
248
|
-
lines.push(`c\t${entry.
|
|
249
|
-
const members = [...(membersByOwner.get(entry.
|
|
248
|
+
lines.push(`c\t${entry.obfuscatedInternal}\t${entry.mojangInternal}`);
|
|
249
|
+
const members = [...(membersByOwner.get(entry.obfuscatedInternal) ?? [])].sort((left, right) => {
|
|
250
250
|
if (left.kind !== right.kind) {
|
|
251
251
|
return left.kind.localeCompare(right.kind);
|
|
252
252
|
}
|
|
253
|
-
if (left.
|
|
254
|
-
return left.
|
|
253
|
+
if (left.obfuscatedName !== right.obfuscatedName) {
|
|
254
|
+
return left.obfuscatedName.localeCompare(right.obfuscatedName);
|
|
255
255
|
}
|
|
256
256
|
return left.descriptor.localeCompare(right.descriptor);
|
|
257
257
|
});
|
|
258
258
|
for (const member of members) {
|
|
259
|
-
lines.push(`\t${member.kind}\t${member.descriptor}\t${member.
|
|
259
|
+
lines.push(`\t${member.kind}\t${member.descriptor}\t${member.obfuscatedName}\t${member.mojangName}`);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
return `${lines.join("\n")}\n`;
|
package/dist/resources.js
CHANGED
|
@@ -30,7 +30,7 @@ export function registerResources(server, sourceService) {
|
|
|
30
30
|
}
|
|
31
31
|
catch (e) {
|
|
32
32
|
if (isAppError(e))
|
|
33
|
-
return errorResource(uri.href, e.message);
|
|
33
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
34
34
|
throw e;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
@@ -41,7 +41,7 @@ export function registerResources(server, sourceService) {
|
|
|
41
41
|
}
|
|
42
42
|
catch (e) {
|
|
43
43
|
if (isAppError(e))
|
|
44
|
-
return errorResource(uri.href, e.message);
|
|
44
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
45
45
|
throw e;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
@@ -56,7 +56,7 @@ export function registerResources(server, sourceService) {
|
|
|
56
56
|
}
|
|
57
57
|
catch (e) {
|
|
58
58
|
if (isAppError(e))
|
|
59
|
-
return errorResource(uri.href, e.message);
|
|
59
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
60
60
|
throw e;
|
|
61
61
|
}
|
|
62
62
|
});
|
|
@@ -70,7 +70,7 @@ export function registerResources(server, sourceService) {
|
|
|
70
70
|
}
|
|
71
71
|
catch (e) {
|
|
72
72
|
if (isAppError(e))
|
|
73
|
-
return errorResource(uri.href, e.message);
|
|
73
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
74
74
|
throw e;
|
|
75
75
|
}
|
|
76
76
|
});
|
|
@@ -87,7 +87,7 @@ export function registerResources(server, sourceService) {
|
|
|
87
87
|
}
|
|
88
88
|
catch (e) {
|
|
89
89
|
if (isAppError(e))
|
|
90
|
-
return errorResource(uri.href, e.message);
|
|
90
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
91
91
|
throw e;
|
|
92
92
|
}
|
|
93
93
|
});
|
|
@@ -101,7 +101,7 @@ export function registerResources(server, sourceService) {
|
|
|
101
101
|
}
|
|
102
102
|
catch (e) {
|
|
103
103
|
if (isAppError(e))
|
|
104
|
-
return errorResource(uri.href, e.message);
|
|
104
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
105
105
|
throw e;
|
|
106
106
|
}
|
|
107
107
|
});
|
|
@@ -112,7 +112,7 @@ export function registerResources(server, sourceService) {
|
|
|
112
112
|
}
|
|
113
113
|
catch (e) {
|
|
114
114
|
if (isAppError(e))
|
|
115
|
-
return errorResource(uri.href, e.message);
|
|
115
|
+
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
116
116
|
throw e;
|
|
117
117
|
}
|
|
118
118
|
});
|
|
@@ -12,8 +12,8 @@ export function scoreHitOrder(left, right) {
|
|
|
12
12
|
if (symbolCompare !== 0) {
|
|
13
13
|
return symbolCompare;
|
|
14
14
|
}
|
|
15
|
-
const leftLine = left.symbol?.line ??
|
|
16
|
-
const rightLine = right.symbol?.line ??
|
|
15
|
+
const leftLine = left.symbol?.line ?? 0;
|
|
16
|
+
const rightLine = right.symbol?.line ?? 0;
|
|
17
17
|
return leftLine - rightLine;
|
|
18
18
|
}
|
|
19
19
|
export function encodeSearchCursor(hit, contextKey) {
|
|
@@ -21,7 +21,7 @@ export function encodeSearchCursor(hit, contextKey) {
|
|
|
21
21
|
score: hit.score,
|
|
22
22
|
filePath: hit.filePath,
|
|
23
23
|
symbolName: hit.symbol?.symbolName ?? "",
|
|
24
|
-
line: hit.symbol?.line ??
|
|
24
|
+
line: hit.symbol?.line ?? 0,
|
|
25
25
|
contextKey
|
|
26
26
|
}), "utf8").toString("base64");
|
|
27
27
|
}
|
|
@@ -66,7 +66,7 @@ export function isAfterSearchCursor(hit, cursor) {
|
|
|
66
66
|
if (symbolCompare < 0) {
|
|
67
67
|
return false;
|
|
68
68
|
}
|
|
69
|
-
const hitLine = hit.symbol?.line ??
|
|
69
|
+
const hitLine = hit.symbol?.line ?? 0;
|
|
70
70
|
return hitLine > cursor.line;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Config, ResolvedSourceArtifact, SourceTargetInput } from "./types.js";
|
|
2
2
|
export interface ResolveSourceTargetOptions {
|
|
3
3
|
allowDecompile: boolean;
|
|
4
|
+
preferBinaryOnly?: boolean;
|
|
4
5
|
preferredRepos?: string[];
|
|
5
6
|
onRepoFailover?: (event: {
|
|
6
7
|
stage: "source" | "binary";
|