Skip to content

Commit

Permalink
Merge 3 class processing class into one class. Add a reverse method f…
Browse files Browse the repository at this point in the history
…or namespaced mappings, but it has some limitations. Now can use --targetNamespace to specify the target namespace to remap to when you are using namespaced mappings to deobfuscate. v2.3 release.
  • Loading branch information
XiaoPangxie732 committed Jul 1, 2021
1 parent 12c7b97 commit df80d65
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 343 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>cn.maxpixel</groupId>
<artifactId>minecraft-decompiler</artifactId>
<version>2.3-SNAPSHOT</version>
<version>2.3</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<depend.asm.ver>9.2</depend.asm.ver>
Expand Down
42 changes: 22 additions & 20 deletions src/main/java/cn/maxpixel/mcdecompiler/Deobfuscator.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

package cn.maxpixel.mcdecompiler;

import cn.maxpixel.mcdecompiler.asm.*;
import cn.maxpixel.mcdecompiler.asm.ClassProcessor;
import cn.maxpixel.mcdecompiler.asm.ExtraClassesInformation;
import cn.maxpixel.mcdecompiler.asm.MappingRemapper;
import cn.maxpixel.mcdecompiler.mapping.namespaced.NamespacedClassMapping;
import cn.maxpixel.mcdecompiler.mapping.paired.PairedClassMapping;
import cn.maxpixel.mcdecompiler.reader.*;
Expand All @@ -28,7 +30,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;

Expand All @@ -40,7 +41,6 @@
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -124,29 +124,32 @@ public Deobfuscator deobfuscate(Path source, Path target) throws IOException {
}

public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers) throws IOException {
if(reader.getProcessor().isNamespaced()) deobfuscate(source, target, includeOthers, false);
return deobfuscate(source, target, includeOthers, Properties.get(Properties.Key.REVERSE));
}

public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers, boolean reverse) throws IOException {
if(reader.getProcessor().isPaired()) return deobfuscate(source, target, includeOthers, reverse, null, null);
if(reader.getProcessor().isPaired()) return deobfuscate(source, target, includeOthers, reverse, null);
String[] namespaces = reader.getProcessor().asNamespaced().getNamespaces();
return deobfuscate(source, target, includeOthers, reverse, namespaces[0], namespaces[namespaces.length - 1].equals("id") ?
return deobfuscate(source, target, includeOthers, reverse, namespaces[namespaces.length - 1].equals("id") ?
namespaces[namespaces.length - 2] : namespaces[namespaces.length - 1]);
}

public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers, String fromNamespace, String toNamespace) throws IOException {
public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers, String targetNamespace) throws IOException {
if(reader.getProcessor().isPaired()) throw new UnsupportedOperationException();
return deobfuscate(source, target, includeOthers, false, fromNamespace, toNamespace);
return deobfuscate(source, target, includeOthers, false, targetNamespace);
}

public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers, boolean reverse, String fromNamespace, String toNamespace) throws IOException {
public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers, boolean reverse, String targetNamespace) throws IOException {
LOGGER.info("Deobfuscating...");
FileUtil.requireExist(source);
Files.deleteIfExists(target);
if(reverse) reader.reverse();
if(reverse) {
if(reader.getProcessor().isNamespaced()) reader.reverse(targetNamespace);
else reader.reverse();
}
Object2ObjectOpenHashMap<String, ? extends PairedClassMapping> mappings = reader.getProcessor().isPaired() ?
reader.getMappingsByUnmappedNameMap() : reader.getMappingsByNamespaceMap(fromNamespace, toNamespace, toNamespace);
reader.getMappingsByUnmappedNameMap() :
reader.getMappingsByNamespaceMap(reader.getProcessor().asNamespaced().getNamespaces()[0], targetNamespace);
FileUtil.ensureDirectoryExist(target.getParent());
try(FileSystem fs = JarUtil.getJarFileSystemProvider().newFileSystem(source, Object2ObjectMaps.emptyMap());
FileSystem targetFs = JarUtil.getJarFileSystemProvider().newFileSystem(target, Object2ObjectMaps.singleton("create", "true"));
Expand All @@ -155,21 +158,20 @@ public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers,
.filter(p -> Files.isRegularFile(p) && mappings.containsKey(NamingUtil.asNativeName0(p.toString().substring(1))))
.parallel(), true, IOUtil::readZipFileBytes);
MappingRemapper mappingRemapper = reader.getProcessor().isPaired() ? new MappingRemapper(reader, info) :
new MappingRemapper(reader, info, fromNamespace, toNamespace);
new MappingRemapper(reader, info, targetNamespace);
boolean rvn = Properties.get(Properties.Key.REGEN_VAR_NAME);
if(rvn) JADNameGenerator.startRecord();
Optional<Object2ObjectOpenHashMap<String, ? extends NamespacedClassMapping>> optional = reader.getProcessor().isNamespaced() ?
Optional.of(reader.getMappingsByNamespaceMap(fromNamespace)) : Optional.empty();
if(rvn) ClassProcessor.startRecord();
Object2ObjectOpenHashMap<String, ? extends NamespacedClassMapping> namespaced = reader.getProcessor().isNamespaced() ?
reader.getMappingsByNamespaceMap(reader.getProcessor().asNamespaced().getNamespaces()[0]) : null;
paths.forEach(path -> {
try(InputStream inputStream = Files.newInputStream(path)) {
String classKeyName = NamingUtil.asNativeName0(path.toString().substring(1));
if(mappings.containsKey(classKeyName)) {
ClassReader reader = new ClassReader(inputStream);
ClassWriter writer = new ClassWriter(reader, 0);
RuntimeInvisibleParameterAnnotationsAttributeFixer fixer = new RuntimeInvisibleParameterAnnotationsAttributeFixer();
ClassVisitor visitor = new ClassRemapper(rvn ? new JADNameGenerator(fixer) : fixer, mappingRemapper);
reader.accept(optional.<ClassVisitor>map(map -> new LVTRenamer(visitor, map, fromNamespace, toNamespace)).orElse(visitor), 0);
fixer.accept(writer);
ClassProcessor processor = new ClassProcessor(rvn, this.reader, namespaced, targetNamespace);
reader.accept(new ClassRemapper(processor, mappingRemapper), 0);
processor.accept(writer);
Path output = targetFs.getPath(mappings.get(classKeyName).getMappedName() + ".class");
FileUtil.ensureDirectoryExist(output.getParent());
Files.write(output, writer.toByteArray(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
Expand All @@ -195,7 +197,7 @@ public Deobfuscator deobfuscate(Path source, Path target, boolean includeOthers,
LOGGER.error("Error when remapping classes or coping files", e);
}
});
if(rvn) JADNameGenerator.endRecord(Properties.get(Properties.Key.TEMP_DIR).resolve("fernflower_abstract_parameter_names.txt"));
if(rvn) ClassProcessor.endRecord(Properties.get(Properties.Key.TEMP_DIR).resolve("fernflower_abstract_parameter_names.txt"));
} catch (IOException e) {
LOGGER.error("Error when deobfuscating", e);
}
Expand Down
19 changes: 16 additions & 3 deletions src/main/java/cn/maxpixel/mcdecompiler/MinecraftDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class MinecraftDecompiler {
private final Deobfuscator deobfuscator;
private String version;
private Info.SideType type;
private String targetNamespace;

{
Path tempPath = Properties.get(Properties.Key.TEMP_DIR);
Expand Down Expand Up @@ -87,17 +88,27 @@ public MinecraftDecompiler(String version, Info.SideType type, String mappingPat
this(version, type, new Deobfuscator(mappingPath));
}

public MinecraftDecompiler(String version, Deobfuscator deobfuscator) {
public MinecraftDecompiler(String version, Deobfuscator deobfuscator, String targetNamespace) {
this.version = version;
this.deobfuscator = deobfuscator;
this.targetNamespace = targetNamespace;
}

public MinecraftDecompiler(String version, Deobfuscator deobfuscator) {
this(version, deobfuscator, null);
}

public MinecraftDecompiler(String version, String mappingPath) throws FileNotFoundException {
this(version, new Deobfuscator(mappingPath));
}

public MinecraftDecompiler(Deobfuscator deobfuscator) {
public MinecraftDecompiler(Deobfuscator deobfuscator, String targetNamespace) {
this.deobfuscator = deobfuscator;
this.targetNamespace = targetNamespace;
}

public MinecraftDecompiler(Deobfuscator deobfuscator) {
this(deobfuscator, null);
}

public MinecraftDecompiler(String mappingPath) throws FileNotFoundException {
Expand Down Expand Up @@ -138,11 +149,13 @@ public void deobfuscate() {
Properties.getOutputDeobfuscatedJarPath(version, type));
}
}

public void deobfuscate(Path input, Path output) {
try {
if(Properties.get(Properties.Key.REVERSE)) deobfuscator.deobfuscate(input, output, true, true, targetNamespace);
deobfuscator.deobfuscate(input, output);
} catch (IOException e) {
LOGGER.fatal("Error deobfuscating");
LOGGER.fatal("Error deobfuscating", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ public static void main(String[] args) throws Throwable {
OptionSpecBuilder regenVarNameO = parser.acceptsAll(asList("r", "rvn", "regenVarName"), "Regenerate local variable " +
"names using JAD style");
OptionSpecBuilder reverseO = parser.accepts("reverse", "Reverse the input mapping, then use the reversed mapping to " +
"deobfuscate. Doesn't support Tiny mappings. This option is ignored if you are using Tiny mappings.").availableUnless(sideTypeO);
"deobfuscate.").availableUnless(sideTypeO);
ArgumentAcceptingOptionSpec<String> targetNamespaceO = parser.accepts("targetNamespace", "The target namespace to remap " +
"to if you are using namespaced mappings(Tiny, Tsrgv2)").availableUnless(sideTypeO).withRequiredArg();
ArgumentAcceptingOptionSpec<Path> inputO = parser.acceptsAll(asList("i", "input"), "The input file. With this option, you must " +
"specify --mappingPath option and musn't specify --version or --side option.").availableUnless(sideTypeO).requiredUnless(sideTypeO)
.withRequiredArg().withValuesConvertedBy(new PathConverter());
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/cn/maxpixel/mcdecompiler/Properties.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@ private Key(String name) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
@SuppressWarnings("rawtypes") Key key = (Key) o;
if (!(o instanceof Key<?> key)) return false;
return name.equals(key.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
return name.hashCode();
}

public static final Key<Path> TEMP_DIR = new Key<>("tempDir");
Expand Down
Loading

0 comments on commit df80d65

Please sign in to comment.