/*******************************************************************************
* Copyright (c) 2015 Jeff Martin.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public
* License v3.0 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* Contributors:
* Jeff Martin - initial API and implementation
******************************************************************************/
package cuchaz.enigma;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.jar.JarFile;
import cuchaz.enigma.convert.ClassMatches;
import cuchaz.enigma.convert.MappingsConverter;
import cuchaz.enigma.convert.MatchesReader;
import cuchaz.enigma.convert.MemberMatches;
import cuchaz.enigma.mapping.*;
public class ConvertMain
{
public static void main(String[] args) throws IOException,
MappingParseException
{
// init files
File home = new File(System.getProperty("user.home"));
JarFile sourceJar =
new JarFile(new File(home, ".minecraft/versions/1.8/1.8.jar"));
JarFile destJar =
new JarFile(new File(home, ".minecraft/versions/1.8.3/1.8.3.jar"));
File inMappingsFile = new File("../Enigma Mappings/1.8.mappings");
File outMappingsFile = new File("../Enigma Mappings/1.8.3.mappings");
Mappings mappings =
new MappingsReader().read(new FileReader(inMappingsFile));
File classMatchesFile =
new File(inMappingsFile.getName() + ".class.matches");
File fieldMatchesFile =
new File(inMappingsFile.getName() + ".field.matches");
File methodMatchesFile =
new File(inMappingsFile.getName() + ".method.matches");
// match classes
// computeClassMatches(classMatchesFile, sourceJar, destJar, mappings);
// editClasssMatches(classMatchesFile, sourceJar, destJar, mappings);
// convertMappings(outMappingsFile, sourceJar, destJar, mappings,
// classMatchesFile);
// match fields
// computeFieldMatches(fieldMatchesFile, destJar, outMappingsFile,
// classMatchesFile);
// editFieldMatches(sourceJar, destJar, outMappingsFile, mappings,
// classMatchesFile, fieldMatchesFile);
// convertMappings(outMappingsFile, sourceJar, destJar, mappings,
// classMatchesFile, fieldMatchesFile);
// match methods/constructors
// computeMethodMatches(methodMatchesFile, destJar, outMappingsFile,
// classMatchesFile);
// editMethodMatches(sourceJar, destJar, outMappingsFile, mappings,
// classMatchesFile, methodMatchesFile);
convertMappings(outMappingsFile, sourceJar, destJar, mappings,
classMatchesFile, fieldMatchesFile, methodMatchesFile);
}
private static void convertMappings(File outMappingsFile,
JarFile sourceJar, JarFile destJar, Mappings mappings,
File classMatchesFile, File fieldMatchesFile, File methodMatchesFile)
throws IOException
{
System.out.println("Reading matches...");
ClassMatches classMatches = MatchesReader.readClasses(classMatchesFile);
MemberMatches<FieldEntry> fieldMatches =
MatchesReader.readMembers(fieldMatchesFile);
MemberMatches<BehaviorEntry> methodMatches =
MatchesReader.readMembers(methodMatchesFile);
Deobfuscators deobfuscators = new Deobfuscators(sourceJar, destJar);
deobfuscators.source.setMappings(mappings);
// apply matches
Mappings newMappings =
MappingsConverter.newMappings(classMatches, mappings,
deobfuscators.source, deobfuscators.dest);
MappingsConverter.applyMemberMatches(newMappings, classMatches,
fieldMatches, MappingsConverter.getFieldDoer());
MappingsConverter.applyMemberMatches(newMappings, classMatches,
methodMatches, MappingsConverter.getMethodDoer());
// check the final mappings
MappingsChecker checker =
new MappingsChecker(deobfuscators.dest.getJarIndex());
checker.dropBrokenMappings(newMappings);
for(java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker
.getDroppedClassMappings().entrySet())
System.out.println("WARNING: Broken class entry "
+ mapping.getKey() + " (" + mapping.getValue().getDeobfName()
+ ")");
for(java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker
.getDroppedInnerClassMappings().entrySet())
System.out.println("WARNING: Broken inner class entry "
+ mapping.getKey() + " (" + mapping.getValue().getDeobfName()
+ ")");
for(java.util.Map.Entry<FieldEntry, FieldMapping> mapping : checker
.getDroppedFieldMappings().entrySet())
System.out.println("WARNING: Broken field entry "
+ mapping.getKey() + " (" + mapping.getValue().getDeobfName()
+ ")");
for(java.util.Map.Entry<BehaviorEntry, MethodMapping> mapping : checker
.getDroppedMethodMappings().entrySet())
System.out.println("WARNING: Broken behavior entry "
+ mapping.getKey() + " (" + mapping.getValue().getDeobfName()
+ ")");
// write out the converted mappings
try(FileWriter out = new FileWriter(outMappingsFile))
{
new MappingsWriter().write(out, newMappings);
}
System.out.println("Wrote converted mappings to:\n\t"
+ outMappingsFile.getAbsolutePath());
}
private static class Deobfuscators
{
public Deobfuscator source;
public Deobfuscator dest;
public Deobfuscators(JarFile sourceJar, JarFile destJar)
{
System.out.println("Indexing source jar...");
IndexerThread sourceIndexer = new IndexerThread(sourceJar);
sourceIndexer.start();
System.out.println("Indexing dest jar...");
IndexerThread destIndexer = new IndexerThread(destJar);
destIndexer.start();
sourceIndexer.joinOrBail();
destIndexer.joinOrBail();
source = sourceIndexer.deobfuscator;
dest = destIndexer.deobfuscator;
}
}
private static class IndexerThread extends Thread
{
private JarFile m_jarFile;
public Deobfuscator deobfuscator;
public IndexerThread(JarFile jarFile)
{
m_jarFile = jarFile;
deobfuscator = null;
}
public void joinOrBail()
{
try
{
join();
}catch(InterruptedException ex)
{
throw new Error(ex);
}
}
@Override
public void run()
{
try
{
deobfuscator = new Deobfuscator(m_jarFile);
}catch(IOException ex)
{
throw new Error(ex);
}
}
}
}