2013-03-08 00:25:48 +00:00
|
|
|
/*
|
|
|
|
* Forge Mod Loader
|
|
|
|
* Copyright (c) 2012-2013 cpw.
|
|
|
|
* All rights reserved. This program and the accompanying materials
|
|
|
|
* are made available under the terms of the GNU Lesser Public License v2.1
|
|
|
|
* which accompanies this distribution, and is available at
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
2013-03-09 04:12:12 +00:00
|
|
|
*
|
2013-03-08 00:25:48 +00:00
|
|
|
* Contributors:
|
|
|
|
* cpw - implementation
|
|
|
|
*/
|
|
|
|
|
2013-01-27 22:09:00 +00:00
|
|
|
package cpw.mods.fml.common.asm.transformers.deobf;
|
|
|
|
|
|
|
|
import java.io.File;
|
2013-06-29 17:33:14 +00:00
|
|
|
import java.io.FileInputStream;
|
2013-01-27 22:09:00 +00:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
2013-01-28 03:42:36 +00:00
|
|
|
import java.util.Arrays;
|
2013-01-27 22:09:00 +00:00
|
|
|
import java.util.List;
|
2013-01-28 02:50:08 +00:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
2013-01-27 22:09:00 +00:00
|
|
|
import java.util.logging.Level;
|
2013-06-15 00:45:52 +00:00
|
|
|
import java.util.logging.Logger;
|
2013-01-27 22:09:00 +00:00
|
|
|
|
2013-06-14 21:21:49 +00:00
|
|
|
import net.minecraft.launchwrapper.LaunchClassLoader;
|
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
import org.objectweb.asm.ClassReader;
|
2013-01-27 22:09:00 +00:00
|
|
|
import org.objectweb.asm.commons.Remapper;
|
2013-11-10 16:49:06 +00:00
|
|
|
import org.objectweb.asm.tree.ClassNode;
|
|
|
|
import org.objectweb.asm.tree.FieldNode;
|
2013-01-27 22:09:00 +00:00
|
|
|
|
2013-01-28 22:39:22 +00:00
|
|
|
import com.google.common.base.CharMatcher;
|
2013-01-27 22:09:00 +00:00
|
|
|
import com.google.common.base.Charsets;
|
2013-01-28 22:39:22 +00:00
|
|
|
import com.google.common.base.Splitter;
|
2013-03-13 00:32:54 +00:00
|
|
|
import com.google.common.base.Strings;
|
2013-01-27 22:09:00 +00:00
|
|
|
import com.google.common.collect.BiMap;
|
|
|
|
import com.google.common.collect.ImmutableBiMap;
|
2013-11-10 16:49:06 +00:00
|
|
|
import com.google.common.collect.ImmutableBiMap.Builder;
|
2013-01-28 03:42:36 +00:00
|
|
|
import com.google.common.collect.ImmutableList;
|
2013-01-28 02:50:08 +00:00
|
|
|
import com.google.common.collect.ImmutableMap;
|
2013-06-29 08:40:01 +00:00
|
|
|
import com.google.common.collect.ImmutableSet;
|
2013-01-28 22:39:22 +00:00
|
|
|
import com.google.common.collect.Iterables;
|
2013-01-28 02:50:08 +00:00
|
|
|
import com.google.common.collect.Maps;
|
|
|
|
import com.google.common.collect.Sets;
|
2013-01-27 22:09:00 +00:00
|
|
|
import com.google.common.io.CharStreams;
|
|
|
|
import com.google.common.io.InputSupplier;
|
|
|
|
|
|
|
|
import cpw.mods.fml.common.FMLLog;
|
2013-09-24 15:09:27 +00:00
|
|
|
import cpw.mods.fml.common.patcher.ClassPatchManager;
|
2013-01-27 22:09:00 +00:00
|
|
|
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
|
|
|
|
|
|
|
public class FMLDeobfuscatingRemapper extends Remapper {
|
|
|
|
public static final FMLDeobfuscatingRemapper INSTANCE = new FMLDeobfuscatingRemapper();
|
|
|
|
|
|
|
|
private BiMap<String, String> classNameBiMap;
|
2013-03-09 04:12:12 +00:00
|
|
|
private BiMap<String, String> mcpNameBiMap;
|
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
private Map<String,Map<String,String>> rawFieldMaps;
|
|
|
|
private Map<String,Map<String,String>> rawMethodMaps;
|
2013-01-27 22:09:00 +00:00
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
private Map<String,Map<String,String>> fieldNameMaps;
|
|
|
|
private Map<String,Map<String,String>> methodNameMaps;
|
|
|
|
|
2013-06-14 21:21:49 +00:00
|
|
|
private LaunchClassLoader classLoader;
|
2013-01-27 22:09:00 +00:00
|
|
|
|
2013-09-24 15:09:27 +00:00
|
|
|
|
|
|
|
private static final boolean DEBUG_REMAPPING = Boolean.parseBoolean(System.getProperty("fml.remappingDebug", "false"));
|
|
|
|
private static final boolean DUMP_FIELD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpFieldMaps", "false")) && DEBUG_REMAPPING;
|
|
|
|
private static final boolean DUMP_METHOD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpMethodMaps", "false")) && DEBUG_REMAPPING;
|
|
|
|
|
2013-01-27 22:09:00 +00:00
|
|
|
private FMLDeobfuscatingRemapper()
|
|
|
|
{
|
2013-03-02 15:30:45 +00:00
|
|
|
classNameBiMap=ImmutableBiMap.of();
|
2013-03-09 04:12:12 +00:00
|
|
|
mcpNameBiMap=ImmutableBiMap.of();
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:53:10 +00:00
|
|
|
public void setupLoadOnly(String deobfFileName, boolean loadAll)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
File mapData = new File(deobfFileName);
|
2013-06-29 17:33:14 +00:00
|
|
|
LZMAInputSupplier zis = new LZMAInputSupplier(new FileInputStream(mapData));
|
2013-06-12 12:53:10 +00:00
|
|
|
InputSupplier<InputStreamReader> srgSupplier = CharStreams.newReaderSupplier(zis,Charsets.UTF_8);
|
|
|
|
List<String> srgList = CharStreams.readLines(srgSupplier);
|
|
|
|
rawMethodMaps = Maps.newHashMap();
|
|
|
|
rawFieldMaps = Maps.newHashMap();
|
|
|
|
Builder<String, String> builder = ImmutableBiMap.<String,String>builder();
|
|
|
|
Builder<String, String> mcpBuilder = ImmutableBiMap.<String,String>builder();
|
|
|
|
Splitter splitter = Splitter.on(CharMatcher.anyOf(": ")).omitEmptyStrings().trimResults();
|
|
|
|
for (String line : srgList)
|
|
|
|
{
|
|
|
|
String[] parts = Iterables.toArray(splitter.split(line),String.class);
|
|
|
|
String typ = parts[0];
|
|
|
|
if ("CL".equals(typ))
|
|
|
|
{
|
|
|
|
parseClass(builder, parts);
|
|
|
|
parseMCPClass(mcpBuilder,parts);
|
|
|
|
}
|
|
|
|
else if ("MD".equals(typ) && loadAll)
|
|
|
|
{
|
|
|
|
parseMethod(parts);
|
|
|
|
}
|
|
|
|
else if ("FD".equals(typ) && loadAll)
|
|
|
|
{
|
|
|
|
parseField(parts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
classNameBiMap = builder.build();
|
|
|
|
mcpNameBiMap = mcpBuilder.build();
|
|
|
|
}
|
|
|
|
catch (IOException ioe)
|
|
|
|
{
|
2013-06-15 00:45:52 +00:00
|
|
|
Logger.getLogger("FML").log(Level.SEVERE, "An error occurred loading the deobfuscation map data", ioe);
|
2013-06-12 12:53:10 +00:00
|
|
|
}
|
|
|
|
methodNameMaps = Maps.newHashMapWithExpectedSize(rawMethodMaps.size());
|
|
|
|
fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size());
|
|
|
|
|
|
|
|
}
|
2013-06-14 21:21:49 +00:00
|
|
|
public void setup(File mcDir, LaunchClassLoader classLoader, String deobfFileName)
|
2013-01-27 22:09:00 +00:00
|
|
|
{
|
2013-01-28 02:50:08 +00:00
|
|
|
this.classLoader = classLoader;
|
2013-01-27 22:09:00 +00:00
|
|
|
try
|
|
|
|
{
|
2013-06-29 17:33:14 +00:00
|
|
|
InputStream classData = getClass().getResourceAsStream(deobfFileName);
|
|
|
|
LZMAInputSupplier zis = new LZMAInputSupplier(classData);
|
2013-01-28 22:39:22 +00:00
|
|
|
InputSupplier<InputStreamReader> srgSupplier = CharStreams.newReaderSupplier(zis,Charsets.UTF_8);
|
|
|
|
List<String> srgList = CharStreams.readLines(srgSupplier);
|
2013-01-28 02:50:08 +00:00
|
|
|
rawMethodMaps = Maps.newHashMap();
|
2013-01-28 22:39:22 +00:00
|
|
|
rawFieldMaps = Maps.newHashMap();
|
|
|
|
Builder<String, String> builder = ImmutableBiMap.<String,String>builder();
|
2013-03-09 04:12:12 +00:00
|
|
|
Builder<String, String> mcpBuilder = ImmutableBiMap.<String,String>builder();
|
2013-01-28 22:39:22 +00:00
|
|
|
Splitter splitter = Splitter.on(CharMatcher.anyOf(": ")).omitEmptyStrings().trimResults();
|
|
|
|
for (String line : srgList)
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
2013-01-28 22:39:22 +00:00
|
|
|
String[] parts = Iterables.toArray(splitter.split(line),String.class);
|
|
|
|
String typ = parts[0];
|
|
|
|
if ("CL".equals(typ))
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
2013-01-28 22:39:22 +00:00
|
|
|
parseClass(builder, parts);
|
2013-03-09 04:12:12 +00:00
|
|
|
parseMCPClass(mcpBuilder,parts);
|
2013-01-28 22:39:22 +00:00
|
|
|
}
|
|
|
|
else if ("MD".equals(typ))
|
|
|
|
{
|
|
|
|
parseMethod(parts);
|
|
|
|
}
|
|
|
|
else if ("FD".equals(typ))
|
|
|
|
{
|
|
|
|
parseField(parts);
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-28 22:39:22 +00:00
|
|
|
classNameBiMap = builder.build();
|
2013-03-09 04:12:12 +00:00
|
|
|
// Special case some mappings for modloader mods
|
|
|
|
mcpBuilder.put("BaseMod","net/minecraft/src/BaseMod");
|
|
|
|
mcpBuilder.put("ModLoader","net/minecraft/src/ModLoader");
|
|
|
|
mcpBuilder.put("EntityRendererProxy","net/minecraft/src/EntityRendererProxy");
|
|
|
|
mcpBuilder.put("MLProp","net/minecraft/src/MLProp");
|
|
|
|
mcpBuilder.put("TradeEntry","net/minecraft/src/TradeEntry");
|
|
|
|
mcpNameBiMap = mcpBuilder.build();
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|
|
|
|
catch (IOException ioe)
|
|
|
|
{
|
2013-01-28 02:50:08 +00:00
|
|
|
FMLRelaunchLog.log(Level.SEVERE, ioe, "An error occurred loading the deobfuscation map data");
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|
2013-01-28 02:50:08 +00:00
|
|
|
methodNameMaps = Maps.newHashMapWithExpectedSize(rawMethodMaps.size());
|
2013-01-28 22:48:44 +00:00
|
|
|
fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size());
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|
2013-03-02 06:49:45 +00:00
|
|
|
|
|
|
|
public boolean isRemappedClass(String className)
|
|
|
|
{
|
2013-04-05 06:30:10 +00:00
|
|
|
className = className.replace('.', '/');
|
2013-03-27 23:23:10 +00:00
|
|
|
return classNameBiMap.containsKey(className) || mcpNameBiMap.containsKey(className) || (!classNameBiMap.isEmpty() && className.indexOf('/') == -1);
|
2013-03-02 06:49:45 +00:00
|
|
|
}
|
|
|
|
|
2013-01-28 22:39:22 +00:00
|
|
|
private void parseField(String[] parts)
|
|
|
|
{
|
2013-01-28 22:48:44 +00:00
|
|
|
String oldSrg = parts[1];
|
|
|
|
int lastOld = oldSrg.lastIndexOf('/');
|
|
|
|
String cl = oldSrg.substring(0,lastOld);
|
|
|
|
String oldName = oldSrg.substring(lastOld+1);
|
|
|
|
String newSrg = parts[2];
|
|
|
|
int lastNew = newSrg.lastIndexOf('/');
|
|
|
|
String newName = newSrg.substring(lastNew+1);
|
|
|
|
if (!rawFieldMaps.containsKey(cl))
|
|
|
|
{
|
|
|
|
rawFieldMaps.put(cl, Maps.<String,String>newHashMap());
|
|
|
|
}
|
2013-04-14 22:02:26 +00:00
|
|
|
rawFieldMaps.get(cl).put(oldName + ":" + getFieldType(cl, oldName), newName);
|
|
|
|
rawFieldMaps.get(cl).put(oldName + ":null", newName);
|
|
|
|
}
|
|
|
|
|
2013-04-15 21:30:35 +00:00
|
|
|
/*
|
|
|
|
* Cache the field descriptions for classes so we don't repeatedly reload the same data again and again
|
|
|
|
*/
|
|
|
|
private Map<String,Map<String,String>> fieldDescriptions = Maps.newHashMap();
|
|
|
|
|
2013-09-24 15:09:27 +00:00
|
|
|
// Cache null values so we don't waste time trying to recompute classes with no field or method maps
|
|
|
|
private Set<String> negativeCacheMethods = Sets.newHashSet();
|
|
|
|
private Set<String> negativeCacheFields = Sets.newHashSet();
|
|
|
|
|
2013-04-15 21:30:35 +00:00
|
|
|
private String getFieldType(String owner, String name)
|
2013-04-14 22:02:26 +00:00
|
|
|
{
|
2013-04-15 21:30:35 +00:00
|
|
|
if (fieldDescriptions.containsKey(owner))
|
|
|
|
{
|
|
|
|
return fieldDescriptions.get(owner).get(name);
|
|
|
|
}
|
|
|
|
synchronized (fieldDescriptions)
|
2013-04-14 22:02:26 +00:00
|
|
|
{
|
2013-04-15 21:30:35 +00:00
|
|
|
try
|
2013-04-14 22:02:26 +00:00
|
|
|
{
|
2013-09-24 15:09:27 +00:00
|
|
|
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(owner, map(owner).replace('/', '.'), classLoader);
|
2013-04-15 21:30:35 +00:00
|
|
|
if (classBytes == null)
|
|
|
|
{
|
|
|
|
return null;
|
2013-04-14 22:02:26 +00:00
|
|
|
}
|
2013-04-15 21:30:35 +00:00
|
|
|
ClassReader cr = new ClassReader(classBytes);
|
|
|
|
ClassNode classNode = new ClassNode();
|
|
|
|
cr.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
|
|
|
Map<String,String> resMap = Maps.newHashMap();
|
2013-04-21 12:09:19 +00:00
|
|
|
for (FieldNode fieldNode : (List<FieldNode>) classNode.fields) {
|
2013-04-15 21:30:35 +00:00
|
|
|
resMap.put(fieldNode.name, fieldNode.desc);
|
|
|
|
}
|
|
|
|
fieldDescriptions.put(owner, resMap);
|
|
|
|
return resMap.get(name);
|
2013-04-14 22:02:26 +00:00
|
|
|
}
|
2013-04-15 21:30:35 +00:00
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
FMLLog.log(Level.SEVERE,e, "A critical exception occured reading a class file %s", owner);
|
|
|
|
}
|
|
|
|
return null;
|
2013-04-14 22:02:26 +00:00
|
|
|
}
|
2013-01-28 22:39:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void parseClass(Builder<String, String> builder, String[] parts)
|
|
|
|
{
|
|
|
|
builder.put(parts[1],parts[2]);
|
|
|
|
}
|
|
|
|
|
2013-03-09 04:12:12 +00:00
|
|
|
private void parseMCPClass(Builder<String, String> builder, String[] parts)
|
|
|
|
{
|
|
|
|
int clIdx = parts[2].lastIndexOf('/');
|
|
|
|
builder.put("net/minecraft/src/"+parts[2].substring(clIdx+1),parts[2]);
|
|
|
|
}
|
|
|
|
|
2013-01-28 22:39:22 +00:00
|
|
|
private void parseMethod(String[] parts)
|
|
|
|
{
|
|
|
|
String oldSrg = parts[1];
|
|
|
|
int lastOld = oldSrg.lastIndexOf('/');
|
|
|
|
String cl = oldSrg.substring(0,lastOld);
|
|
|
|
String oldName = oldSrg.substring(lastOld+1);
|
|
|
|
String sig = parts[2];
|
|
|
|
String newSrg = parts[3];
|
|
|
|
int lastNew = newSrg.lastIndexOf('/');
|
|
|
|
String newName = newSrg.substring(lastNew+1);
|
|
|
|
if (!rawMethodMaps.containsKey(cl))
|
|
|
|
{
|
|
|
|
rawMethodMaps.put(cl, Maps.<String,String>newHashMap());
|
|
|
|
}
|
|
|
|
rawMethodMaps.get(cl).put(oldName+sig, newName);
|
|
|
|
}
|
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
@Override
|
|
|
|
public String mapFieldName(String owner, String name, String desc)
|
|
|
|
{
|
2013-03-02 15:46:32 +00:00
|
|
|
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
2013-01-28 22:48:44 +00:00
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
Map<String, String> fieldMap = getFieldMap(owner);
|
2013-04-14 22:02:26 +00:00
|
|
|
return fieldMap!=null && fieldMap.containsKey(name+":"+desc) ? fieldMap.get(name+":"+desc) : name;
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-27 22:09:00 +00:00
|
|
|
@Override
|
|
|
|
public String map(String typeName)
|
|
|
|
{
|
2013-03-02 15:46:32 +00:00
|
|
|
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
2013-01-27 22:09:00 +00:00
|
|
|
{
|
|
|
|
return typeName;
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:48:03 +00:00
|
|
|
int dollarIdx = typeName.indexOf('$');
|
|
|
|
String realType = dollarIdx > -1 ? typeName.substring(0, dollarIdx) : typeName;
|
|
|
|
String subType = dollarIdx > -1 ? typeName.substring(dollarIdx+1) : "";
|
|
|
|
|
|
|
|
String result = classNameBiMap.containsKey(realType) ? classNameBiMap.get(realType) : mcpNameBiMap.containsKey(realType) ? mcpNameBiMap.get(realType) : realType;
|
|
|
|
result = dollarIdx > -1 ? result+"$"+subType : result;
|
2013-01-27 22:09:00 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String unmap(String typeName)
|
|
|
|
{
|
2013-03-09 18:48:03 +00:00
|
|
|
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
2013-01-27 22:09:00 +00:00
|
|
|
{
|
|
|
|
return typeName;
|
|
|
|
}
|
2013-03-09 18:48:03 +00:00
|
|
|
int dollarIdx = typeName.indexOf('$');
|
|
|
|
String realType = dollarIdx > -1 ? typeName.substring(0, dollarIdx) : typeName;
|
|
|
|
String subType = dollarIdx > -1 ? typeName.substring(dollarIdx+1) : "";
|
|
|
|
|
|
|
|
|
|
|
|
String result = classNameBiMap.containsValue(realType) ? classNameBiMap.inverse().get(realType) : mcpNameBiMap.containsValue(realType) ? mcpNameBiMap.inverse().get(realType) : realType;
|
|
|
|
result = dollarIdx > -1 ? result+"$"+subType : result;
|
2013-03-09 04:12:12 +00:00
|
|
|
return result;
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|
2013-01-28 02:50:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String mapMethodName(String owner, String name, String desc)
|
|
|
|
{
|
2013-03-02 15:46:32 +00:00
|
|
|
if (classNameBiMap==null || classNameBiMap.isEmpty())
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
Map<String, String> methodMap = getMethodMap(owner);
|
|
|
|
String methodDescriptor = name+desc;
|
2013-01-28 03:42:36 +00:00
|
|
|
return methodMap!=null && methodMap.containsKey(methodDescriptor) ? methodMap.get(methodDescriptor) : name;
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-28 22:48:44 +00:00
|
|
|
private Map<String,String> getFieldMap(String className)
|
|
|
|
{
|
2013-09-24 15:09:27 +00:00
|
|
|
if (!fieldNameMaps.containsKey(className) && !negativeCacheFields.contains(className))
|
2013-01-28 22:48:44 +00:00
|
|
|
{
|
|
|
|
findAndMergeSuperMaps(className);
|
2013-09-24 15:09:27 +00:00
|
|
|
if (!fieldNameMaps.containsKey(className))
|
|
|
|
{
|
|
|
|
negativeCacheFields.add(className);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DUMP_FIELD_MAPS)
|
|
|
|
{
|
|
|
|
FMLRelaunchLog.finest("Field map for %s : %s", className, fieldNameMaps.get(className));
|
|
|
|
}
|
2013-01-28 22:48:44 +00:00
|
|
|
}
|
|
|
|
return fieldNameMaps.get(className);
|
|
|
|
}
|
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
private Map<String,String> getMethodMap(String className)
|
|
|
|
{
|
2013-09-24 15:09:27 +00:00
|
|
|
if (!methodNameMaps.containsKey(className) && !negativeCacheMethods.contains(className))
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
|
|
|
findAndMergeSuperMaps(className);
|
2013-09-24 15:09:27 +00:00
|
|
|
if (!methodNameMaps.containsKey(className))
|
|
|
|
{
|
|
|
|
negativeCacheMethods.add(className);
|
|
|
|
}
|
|
|
|
if (DUMP_METHOD_MAPS)
|
|
|
|
{
|
|
|
|
FMLRelaunchLog.finest("Method map for %s : %s", className, methodNameMaps.get(className));
|
|
|
|
}
|
|
|
|
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
return methodNameMaps.get(className);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void findAndMergeSuperMaps(String name)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2013-09-24 15:09:27 +00:00
|
|
|
String superName = null;
|
|
|
|
String[] interfaces = new String[0];
|
|
|
|
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(name, map(name), classLoader);
|
|
|
|
if (classBytes != null)
|
2013-01-28 03:42:36 +00:00
|
|
|
{
|
2013-09-24 15:09:27 +00:00
|
|
|
ClassReader cr = new ClassReader(classBytes);
|
|
|
|
superName = cr.getSuperName();
|
|
|
|
interfaces = cr.getInterfaces();
|
2013-01-28 03:42:36 +00:00
|
|
|
}
|
|
|
|
mergeSuperMaps(name, superName, interfaces);
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
2013-01-28 03:42:36 +00:00
|
|
|
public void mergeSuperMaps(String name, String superName, String[] interfaces)
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
2013-03-11 20:31:26 +00:00
|
|
|
// System.out.printf("Computing super maps for %s: %s %s\n", name, superName, Arrays.asList(interfaces));
|
2013-03-02 15:46:32 +00:00
|
|
|
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-03-13 00:32:54 +00:00
|
|
|
// Skip Object
|
|
|
|
if (Strings.isNullOrEmpty(superName))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-28 03:42:36 +00:00
|
|
|
List<String> allParents = ImmutableList.<String>builder().add(superName).addAll(Arrays.asList(interfaces)).build();
|
2013-03-13 00:32:54 +00:00
|
|
|
// generate maps for all parent objects
|
2013-01-28 03:42:36 +00:00
|
|
|
for (String parentThing : allParents)
|
2013-01-28 02:50:08 +00:00
|
|
|
{
|
2013-03-13 00:32:54 +00:00
|
|
|
if (!methodNameMaps.containsKey(parentThing))
|
2013-01-28 03:42:36 +00:00
|
|
|
{
|
2013-03-13 00:32:54 +00:00
|
|
|
findAndMergeSuperMaps(parentThing);
|
2013-01-28 03:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Map<String, String> methodMap = Maps.<String,String>newHashMap();
|
2013-01-28 22:48:44 +00:00
|
|
|
Map<String, String> fieldMap = Maps.<String,String>newHashMap();
|
2013-01-28 03:42:36 +00:00
|
|
|
for (String parentThing : allParents)
|
|
|
|
{
|
|
|
|
if (methodNameMaps.containsKey(parentThing))
|
|
|
|
{
|
|
|
|
methodMap.putAll(methodNameMaps.get(parentThing));
|
|
|
|
}
|
2013-01-28 22:48:44 +00:00
|
|
|
if (fieldNameMaps.containsKey(parentThing))
|
|
|
|
{
|
|
|
|
fieldMap.putAll(fieldNameMaps.get(parentThing));
|
|
|
|
}
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
|
|
|
if (rawMethodMaps.containsKey(name))
|
|
|
|
{
|
|
|
|
methodMap.putAll(rawMethodMaps.get(name));
|
|
|
|
}
|
2013-01-28 22:48:44 +00:00
|
|
|
if (rawFieldMaps.containsKey(name))
|
|
|
|
{
|
|
|
|
fieldMap.putAll(rawFieldMaps.get(name));
|
|
|
|
}
|
2013-01-28 02:50:08 +00:00
|
|
|
methodNameMaps.put(name, ImmutableMap.copyOf(methodMap));
|
2013-01-28 22:48:44 +00:00
|
|
|
fieldNameMaps.put(name, ImmutableMap.copyOf(fieldMap));
|
2013-03-11 20:31:26 +00:00
|
|
|
// System.out.printf("Maps: %s %s\n", name, methodMap);
|
2013-01-28 02:50:08 +00:00
|
|
|
}
|
2013-06-29 08:40:01 +00:00
|
|
|
|
|
|
|
public Set<String> getObfedClasses()
|
|
|
|
{
|
|
|
|
return ImmutableSet.copyOf(classNameBiMap.keySet());
|
|
|
|
}
|
2013-01-27 22:09:00 +00:00
|
|
|
}
|