Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions __tests__/core/remap-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,32 @@ describe('JAR Remapping', () => {
expect(intermediaryFieldCount).toBeLessThan(20);
}, 60000);
});

describe('Unobfuscated version handling', () => {
// 26.1+ snapshots ship without obfuscation — no intermediary or Yarn mappings exist.
const UNOBFUSCATED_VERSION = '26.1-snapshot-8';
Comment thread
GhostTypes marked this conversation as resolved.
Outdated

it('should throw a clear error when requesting yarn mappings for an unobfuscated version', async () => {
const remapService = getRemapService();
await expect(remapService.getRemappedJar(UNOBFUSCATED_VERSION, 'yarn')).rejects.toThrow(
/yarn mappings are not supported for unobfuscated/i,
);
}, 60000); // includes client JAR download on first run

it('should throw a clear error when requesting intermediary mappings for an unobfuscated version', async () => {
const remapService = getRemapService();
await expect(
remapService.getRemappedJar(UNOBFUSCATED_VERSION, 'intermediary'),
).rejects.toThrow(/intermediary mappings are not supported for unobfuscated/i);
}, 60000);

it('should return the raw client JAR for mojmap on an unobfuscated version', async () => {
const remapService = getRemapService();
const jarPath = await remapService.getRemappedJar(UNOBFUSCATED_VERSION, 'mojmap');
expect(jarPath).toBeDefined();
expect(existsSync(jarPath)).toBe(true);
// The returned path is the raw client JAR, not a remapped copy
expect(jarPath).not.toContain('remapped');
}, 60000);
});
});
16 changes: 16 additions & 0 deletions __tests__/core/version-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,20 @@ describe('Version Management', () => {

expect(exists).toBe(false);
}, 30000);

describe('Unobfuscated version detection', () => {
it('should return false for obfuscated versions', async () => {
const versionManager = getVersionManager();
// TEST_VERSION (1.21.11) is an obfuscated release — client_mappings present
const result = await versionManager.isVersionUnobfuscated(TEST_VERSION);
expect(result).toBe(false);
}, 30000);

it('should return true for unobfuscated versions (26.1+)', async () => {
const versionManager = getVersionManager();
// 26.1 snapshots ship without obfuscation — no client_mappings in version JSON
const result = await versionManager.isVersionUnobfuscated('26.1-snapshot-8');
expect(result).toBe(true);
}, 30000);
});
});
14 changes: 14 additions & 0 deletions src/services/remap-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ export class RemapService {
}
});

// Minecraft 26.1+ ships unobfuscated JARs — no remapping is possible or needed.
const isUnobfuscated = await this.versionManager.isVersionUnobfuscated(version);
if (isUnobfuscated) {
if (mapping !== 'mojmap') {
throw new Error(
`${mapping} mappings are not supported for unobfuscated Minecraft versions. ` +
`Version ${version} ships without obfuscation — use 'mojmap' mapping instead.`,
);
}
// The raw JAR is already in Mojang's human-readable names; decompile it directly.
logger.info(`Version ${version} is unobfuscated — skipping remapping (mojmap)`);
return inputJar;
}

// Yarn mappings require two-step remapping: official -> intermediary -> named
if (mapping === 'yarn') {
return await this.remapYarn(version, inputJar, outputPath, onProgress);
Expand Down
12 changes: 12 additions & 0 deletions src/services/version-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ export class VersionManager {
}
}

/**
* Check if a Minecraft version ships an unobfuscated JAR.
*
* Starting with Minecraft 26.1 snapshots, Mojang stopped obfuscating the
* client JAR. These versions have no `client_mappings` entry in their
* version JSON because there is nothing to reverse-map.
*/
async isVersionUnobfuscated(version: string): Promise<boolean> {
const versionJson = await this.downloader.getVersionJson(version);
Comment thread
GhostTypes marked this conversation as resolved.
return !versionJson.downloads.client_mappings;
Comment thread
GhostTypes marked this conversation as resolved.
Outdated
}

/**
* Get version JAR path (must be cached)
*/
Expand Down