diff --git a/src/main/java/cn/maxpixel/mcdecompiler/ClassifiedDeobfuscator.java b/src/main/java/cn/maxpixel/mcdecompiler/ClassifiedDeobfuscator.java index 5a2d52f..6e5bebf 100644 --- a/src/main/java/cn/maxpixel/mcdecompiler/ClassifiedDeobfuscator.java +++ b/src/main/java/cn/maxpixel/mcdecompiler/ClassifiedDeobfuscator.java @@ -29,6 +29,7 @@ import cn.maxpixel.mcdecompiler.reader.ClassifiedMappingReader; import cn.maxpixel.mcdecompiler.util.*; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; import it.unimi.dsi.fastutil.objects.ObjectLists; import org.objectweb.asm.ClassReader; @@ -108,6 +109,8 @@ public ClassifiedDeobfuscator(ClassifiedMappingReader reader, this.mappingRemapper = new ClassifiedMappingRemapper(reader.mappings, sourceNamespace, targetNamespace); } + final ObjectArrayList toDecompile = new ObjectArrayList<>(); + public ClassifiedDeobfuscator deobfuscate(Path source, Path target) throws IOException { LOGGER.info("Deobfuscating..."); Files.deleteIfExists(target); @@ -126,6 +129,7 @@ public ClassifiedDeobfuscator deobfuscate(Path source, Path target) throws IOExc }); mappingRemapper.setExtraClassesInformation(info); ClassProcessor.beforeRunning(options, targetNamespace, mappingRemapper); + toDecompile.clear(); paths.forEach(path -> { try { String classKeyName = NamingUtil.asNativeName0(path.toString().substring(1)); @@ -134,8 +138,11 @@ public ClassifiedDeobfuscator deobfuscate(Path source, Path target) throws IOExc ClassWriter writer = new ClassWriter(0); ClassMapping cm = mappings.get(classKeyName); reader.accept(ClassProcessor.getVisitor(writer, options, reader, cm, targetNamespace, mappingRemapper), 0); - try(OutputStream os = Files.newOutputStream(FileUtil.ensureFileExist(targetFs - .getPath(cm.mapping.getMappedName().concat(".class"))))) { + String mapped = cm.mapping.getMappedName().concat(".class"); + synchronized(toDecompile) { + toDecompile.add(mapped); + } + try(OutputStream os = Files.newOutputStream(FileUtil.ensureFileExist(targetFs.getPath(mapped)))) { os.write(writer.toByteArray()); } } else if(options.includeOthers()) { diff --git a/src/main/java/cn/maxpixel/mcdecompiler/MinecraftDecompiler.java b/src/main/java/cn/maxpixel/mcdecompiler/MinecraftDecompiler.java index d08a7ad..0da6cd4 100644 --- a/src/main/java/cn/maxpixel/mcdecompiler/MinecraftDecompiler.java +++ b/src/main/java/cn/maxpixel/mcdecompiler/MinecraftDecompiler.java @@ -44,7 +44,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.ForkJoinPool; import java.util.logging.Level; import java.util.logging.Logger; @@ -84,18 +87,16 @@ public void deobfuscate() { public void decompile(Info.DecompilerType decompilerType) { if(Files.notExists(options.outputJar())) deobfuscate(); LOGGER.log(Level.INFO, "Decompiling using \"{0}\"", decompilerType); - decompile0(Decompilers.get(decompilerType), options.outputJar(), options.outputDecompDir()); + decompile0(Decompilers.get(decompilerType), deobfuscator.toDecompile, options.outputJar(), options.outputDecompDir()); } public void decompileCustomized(String customizedDecompilerName) { if(Files.notExists(options.outputJar())) deobfuscate(); LOGGER.log(Level.INFO, "Decompiling using customized decompiler \"{0}\"", customizedDecompilerName); - decompile0(Decompilers.getCustom(customizedDecompilerName), options.outputJar(), options.outputDecompDir()); + decompile0(Decompilers.getCustom(customizedDecompilerName), deobfuscator.toDecompile, options.outputJar(), options.outputDecompDir()); } - private static final Set skippedPkgs = Set.of("authlib", "bridge", "brigadier", "datafixers", "serialization", "util"); - - private void decompile0(IDecompiler decompiler, Path inputJar, Path outputDir) { + private void decompile0(IDecompiler decompiler, ObjectList paths, Path inputJar, Path outputDir) { try(FileSystem jarFs = JarUtil.createZipFs(inputJar, false)) { FileUtil.deleteIfExists(outputDir); Files.createDirectories(outputDir); @@ -104,20 +105,14 @@ private void decompile0(IDecompiler decompiler, Path inputJar, Path outputDir) { if(decompiler instanceof IExternalResourcesDecompiler erd) erd.extractTo(Properties.TEMP_DIR.toAbsolutePath().normalize()); if(decompiler instanceof ILibRecommendedDecompiler lrd) { - if(options.bundledLibs().isPresent()) lrd.receiveLibs(options.bundledLibs().get()); - else if(options.version() != null) lrd.downloadLib(libDownloadPath, options.version()); + options.bundledLibs().ifPresentOrElse(lrd::receiveLibs, LambdaUtil.unwrap(() -> { + if(options.version() != null) lrd.downloadLib(libDownloadPath, options.version()); + })); } switch (decompiler.getSourceType()) { case DIRECTORY -> { Path decompileClasses = Properties.TEMP_DIR.resolve("decompileClasses").toAbsolutePath().normalize(); - FileUtil.copyDirectory(jarFs.getPath("net"), decompileClasses.resolve("net")); - if(options.bundledLibs().isEmpty() && Files.isDirectory(jarFs.getPath("com/mojang"))) { - try(Stream mjDirs = Files.list(jarFs.getPath("com/mojang")) - .filter(p -> !skippedPkgs.contains(p.getFileName().toString()))) { - Path mjDir = decompileClasses.resolve("com/mojang"); - mjDirs.forEach(p -> FileUtil.copyDirectory(p, mjDir)); - } - } + paths.parallelStream().forEach(path -> FileUtil.copyFile(jarFs.getPath(path), decompileClasses.resolve(path))); decompiler.decompile(decompileClasses, outputDir); } case FILE -> decompiler.decompile(inputJar, outputDir); @@ -178,11 +173,13 @@ private void preprocess(Path inputJar) { this.inputJar = extractDir.resolve(versionPath.getFileName().toString()); } else throw new IllegalArgumentException("Why multiple versions in a bundle?"); ObjectArrayList libs = new ObjectArrayList<>(); - Files.lines(metaInf.resolve("libraries.list")).forEach(line -> { - Path lib = metaInf.resolve("libraries").resolve(line.split("\t")[2]); - FileUtil.copyFile(lib, extractDir); - libs.add(extractDir.resolve(lib.getFileName().toString())); - }); + try(Stream lines = Files.lines(metaInf.resolve("libraries.list"))) { + lines.forEach(line -> { + Path lib = metaInf.resolve("libraries").resolve(line.split("\t")[2]); + FileUtil.copyFile(lib, extractDir); + libs.add(extractDir.resolve(lib.getFileName().toString())); + }); + } this.bundledLibs = Optional.of(libs); } else this.inputJar = inputJar; Path versionJson = jarFs.getPath("/version.json"); diff --git a/src/main/java/cn/maxpixel/mcdecompiler/util/Logging.java b/src/main/java/cn/maxpixel/mcdecompiler/util/Logging.java index fb027f4..10690d1 100644 --- a/src/main/java/cn/maxpixel/mcdecompiler/util/Logging.java +++ b/src/main/java/cn/maxpixel/mcdecompiler/util/Logging.java @@ -31,7 +31,6 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.Arrays; import java.util.function.Supplier; import java.util.logging.*; @@ -193,13 +192,10 @@ private static StringBuilder getMessage(String sourceClass, String sourceMethod, } else if(sourceMethod != null) builder.append("[Method ").append(sourceMethod).append("] "); if(message != null) { if(params != null && params.length > 0) { - if(params[params.length - 1] instanceof Throwable) { - thrown = (Throwable) params[params.length - 1]; - params = Arrays.copyOf(params, params.length - 1); - for(int i = 0; i < params.length; i++) { - Object o = params[i]; - if(o instanceof Supplier s) params[i] = s.get(); - } + int paramLength = params.length; + if(params[paramLength - 1] instanceof Throwable) thrown = (Throwable) params[--paramLength]; + for(int i = 0; i < paramLength; i++) { + if(params[i] instanceof Supplier s) params[i] = s.get(); } message = String.format(MessageFormat.format(message, params), params); }