mirror of
https://github.com/zaaarf/lillero-processor.git
synced 2024-11-22 10:04:51 +01:00
feat: mappings can now be taken in as an option, generified SrgMapper
This commit is contained in:
parent
036dec2bb2
commit
df3590d097
4 changed files with 218 additions and 244 deletions
|
@ -1,9 +1,9 @@
|
||||||
package ftbsc.lll.exceptions;
|
package ftbsc.lll.exceptions;
|
||||||
|
|
||||||
import ftbsc.lll.processor.tools.SrgMapper;
|
import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown upon failure to find the requested mapping within a loaded {@link SrgMapper}.
|
* Thrown upon failure to find the requested mapping within a loaded {@link ObfuscationMapper}.
|
||||||
*/
|
*/
|
||||||
public class MappingNotFoundException extends RuntimeException {
|
public class MappingNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
import ftbsc.lll.exceptions.TargetNotFoundException;
|
import ftbsc.lll.exceptions.TargetNotFoundException;
|
||||||
import ftbsc.lll.processor.annotations.*;
|
import ftbsc.lll.processor.annotations.*;
|
||||||
import ftbsc.lll.processor.tools.SrgMapper;
|
import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
|
||||||
import ftbsc.lll.proxies.FieldProxy;
|
import ftbsc.lll.proxies.FieldProxy;
|
||||||
import ftbsc.lll.proxies.MethodProxy;
|
import ftbsc.lll.proxies.MethodProxy;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import static ftbsc.lll.processor.tools.ASTUtils.*;
|
||||||
*/
|
*/
|
||||||
@SupportedAnnotationTypes("ftbsc.lll.processor.annotations.Patch")
|
@SupportedAnnotationTypes("ftbsc.lll.processor.annotations.Patch")
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
|
@SupportedOptions("mappingsFile")
|
||||||
public class LilleroProcessor extends AbstractProcessor {
|
public class LilleroProcessor extends AbstractProcessor {
|
||||||
/**
|
/**
|
||||||
* A {@link Set} of {@link String}s that will contain the fully qualified names
|
* A {@link Set} of {@link String}s that will contain the fully qualified names
|
||||||
|
@ -41,9 +42,35 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
private final Set<String> generatedInjectors = new HashSet<>();
|
private final Set<String> generatedInjectors = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static boolean that should be set to true when ran in a non-obfuscated environment.
|
* The {@link ObfuscationMapper} used to convert classes and variables
|
||||||
|
* to their obfuscated equivalent. Will be null when no mapper is in use.
|
||||||
*/
|
*/
|
||||||
public static boolean obfuscatedEnvironment = false; //todo: set this
|
private ObfuscationMapper mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the processor with the processing environment by
|
||||||
|
* setting the {@code processingEnv} field to the value of the
|
||||||
|
* {@code processingEnv} argument.
|
||||||
|
* @param processingEnv environment to access facilities the tool framework
|
||||||
|
* provides to the processor
|
||||||
|
* @throws IllegalStateException if this method is called more than once.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||||
|
super.init(processingEnv);
|
||||||
|
String location = processingEnv.getOptions().get("mappingsFile");
|
||||||
|
if(location == null)
|
||||||
|
mapper = null;
|
||||||
|
else { //TODO: add local file
|
||||||
|
try {
|
||||||
|
URL url = new URL(location);
|
||||||
|
InputStream is = url.openStream();
|
||||||
|
mapper = new ObfuscationMapper(new BufferedReader(new InputStreamReader(is,
|
||||||
|
StandardCharsets.UTF_8)).lines());
|
||||||
|
is.close();
|
||||||
|
} catch(IOException ignored) {} //TODO: proper handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where the actual processing happens.
|
* Where the actual processing happens.
|
||||||
|
@ -106,7 +133,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
/**
|
/**
|
||||||
* Finds the class name and maps it to the correct format.
|
* Finds the class name and maps it to the correct format.
|
||||||
* @param name the fully qualified name of the class to convert
|
* @param name the fully qualified name of the class to convert
|
||||||
* @param mapper the {@link SrgMapper} to use, may be null
|
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
||||||
* @implNote De facto, there is never any difference between the SRG and MCP name of a class.
|
* @implNote De facto, there is never any difference between the SRG and MCP name of a class.
|
||||||
* In theory, differences only arise between SRG/MCP names and Notch (fully obfuscated)
|
* In theory, differences only arise between SRG/MCP names and Notch (fully obfuscated)
|
||||||
* names. However, this method still performs a conversion - just in case there is an
|
* names. However, this method still performs a conversion - just in case there is an
|
||||||
|
@ -114,15 +141,15 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @return the fully qualified class name
|
* @return the fully qualified class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findClassName(String name, SrgMapper mapper) {
|
private static String findClassName(String name, ObfuscationMapper mapper) {
|
||||||
return mapper == null ? name : mapper.mapClass(name, obfuscatedEnvironment).replace('/', '.');
|
return mapper == null ? name : mapper.obfuscateClass(name).replace('/', '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the class name and maps it to the correct format.
|
* Finds the class name and maps it to the correct format.
|
||||||
* @param patchAnn the {@link Patch} annotation containing target class info
|
* @param patchAnn the {@link Patch} annotation containing target class info
|
||||||
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
||||||
* @param mapper the {@link SrgMapper} to use, may be null
|
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
||||||
* @implNote De facto, there is never any difference between the SRG and MCP name of a class.
|
* @implNote De facto, there is never any difference between the SRG and MCP name of a class.
|
||||||
* In theory, differences only arise between SRG/MCP names and Notch (fully obfuscated)
|
* In theory, differences only arise between SRG/MCP names and Notch (fully obfuscated)
|
||||||
* names. However, this method still performs a conversion - just in case there is an
|
* names. However, this method still performs a conversion - just in case there is an
|
||||||
|
@ -130,7 +157,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @return the fully qualified class name
|
* @return the fully qualified class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findClassName(Patch patchAnn, FindMethod methodAnn, SrgMapper mapper) {
|
private static String findClassName(Patch patchAnn, FindMethod methodAnn, ObfuscationMapper mapper) {
|
||||||
String fullyQualifiedName =
|
String fullyQualifiedName =
|
||||||
methodAnn == null || methodAnn.parent() == Object.class
|
methodAnn == null || methodAnn.parent() == Object.class
|
||||||
? getClassFullyQualifiedName(patchAnn.value())
|
? getClassFullyQualifiedName(patchAnn.value())
|
||||||
|
@ -141,11 +168,11 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
/**
|
/**
|
||||||
* Finds the class name and maps it to the correct format.
|
* Finds the class name and maps it to the correct format.
|
||||||
* @param patchAnn the {@link Patch} annotation containing target class info
|
* @param patchAnn the {@link Patch} annotation containing target class info
|
||||||
* @param mapper the {@link SrgMapper} to use, may be null
|
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
||||||
* @return the internal class name
|
* @return the internal class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findClassName(Patch patchAnn, SrgMapper mapper) {
|
private static String findClassName(Patch patchAnn, ObfuscationMapper mapper) {
|
||||||
return findClassName(patchAnn, null, mapper);
|
return findClassName(patchAnn, null, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +180,12 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* Finds the member name and maps it to the correct format.
|
* Finds the member name and maps it to the correct format.
|
||||||
* @param parentFQN the already mapped FQN of the parent class
|
* @param parentFQN the already mapped FQN of the parent class
|
||||||
* @param memberName the name of the member
|
* @param memberName the name of the member
|
||||||
* @param mapper the {@link SrgMapper} to use, may be null
|
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
||||||
* @return the internal class name
|
* @return the internal class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findMemberName(String parentFQN, String memberName, SrgMapper mapper) {
|
private static String findMemberName(String parentFQN, String memberName, ObfuscationMapper mapper) {
|
||||||
return mapper == null ? memberName : mapper.mapMember(parentFQN, memberName, obfuscatedEnvironment);
|
return mapper == null ? memberName : mapper.obfuscateMember(parentFQN, memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,11 +193,11 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @param parentFQN the already mapped FQN of the parent class
|
* @param parentFQN the already mapped FQN of the parent class
|
||||||
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
||||||
* @param stub the {@link ExecutableElement} for the stub
|
* @param stub the {@link ExecutableElement} for the stub
|
||||||
* @param mapper the {@link SrgMapper} to use, may be null
|
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
||||||
* @return the internal class name
|
* @return the internal class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findMethodName(String parentFQN, FindMethod methodAnn, ExecutableElement stub, SrgMapper mapper) {
|
private static String findMethodName(String parentFQN, FindMethod methodAnn, ExecutableElement stub, ObfuscationMapper mapper) {
|
||||||
String methodName = methodAnn == null ? stub.getSimpleName().toString() : methodAnn.name();
|
String methodName = methodAnn == null ? stub.getSimpleName().toString() : methodAnn.name();
|
||||||
try {
|
try {
|
||||||
methodName = findMemberName(parentFQN, methodName, mapper);
|
methodName = findMemberName(parentFQN, methodName, mapper);
|
||||||
|
@ -188,11 +215,11 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @param patchAnn the {@link Patch} annotation containing target class info
|
* @param patchAnn the {@link Patch} annotation containing target class info
|
||||||
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
* @param methodAnn the {@link FindMethod} annotation to fall back on, may be null
|
||||||
* @param stub the {@link ExecutableElement} for the stub
|
* @param stub the {@link ExecutableElement} for the stub
|
||||||
* @param mapper the {@link SrgMapper} to use
|
* @param mapper the {@link ObfuscationMapper} to use
|
||||||
* @return the internal class name
|
* @return the internal class name
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private static String findMethodName(Patch patchAnn, FindMethod methodAnn, ExecutableElement stub, SrgMapper mapper) {
|
private static String findMethodName(Patch patchAnn, FindMethod methodAnn, ExecutableElement stub, ObfuscationMapper mapper) {
|
||||||
return findMethodName(findClassName(patchAnn, methodAnn, mapper), methodAnn, stub, mapper);
|
return findMethodName(findClassName(patchAnn, methodAnn, mapper), methodAnn, stub, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,13 +277,13 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
/**
|
/**
|
||||||
* Finds the real method corresponding to a stub.
|
* Finds the real method corresponding to a stub.
|
||||||
* @param stub the {@link ExecutableElement} for the stub
|
* @param stub the {@link ExecutableElement} for the stub
|
||||||
* @param mapper the {@link SrgMapper} to use
|
* @param mapper the {@link ObfuscationMapper} to use
|
||||||
* @return the desired method, if it exists
|
* @return the desired method, if it exists
|
||||||
* @throws AmbiguousDefinitionException if it finds more than one candidate
|
* @throws AmbiguousDefinitionException if it finds more than one candidate
|
||||||
* @throws TargetNotFoundException if it finds no valid candidate
|
* @throws TargetNotFoundException if it finds no valid candidate
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private ExecutableElement findRealMethod(ExecutableElement stub, SrgMapper mapper) {
|
private ExecutableElement findRealMethod(ExecutableElement stub, ObfuscationMapper mapper) {
|
||||||
Patch patchAnn = stub.getEnclosingElement().getAnnotation(Patch.class);
|
Patch patchAnn = stub.getEnclosingElement().getAnnotation(Patch.class);
|
||||||
FindMethod findAnn = stub.getAnnotation(FindMethod.class); //this may be null, it means no fallback info
|
FindMethod findAnn = stub.getAnnotation(FindMethod.class); //this may be null, it means no fallback info
|
||||||
Target target = stub.getAnnotation(Target.class); //if this is null strict mode is always disabled
|
Target target = stub.getAnnotation(Target.class); //if this is null strict mode is always disabled
|
||||||
|
@ -272,12 +299,12 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
/**
|
/**
|
||||||
* Finds the real field corresponding to a stub.
|
* Finds the real field corresponding to a stub.
|
||||||
* @param stub the {@link ExecutableElement} for the stub
|
* @param stub the {@link ExecutableElement} for the stub
|
||||||
* @param mapper the {@link SrgMapper} to use
|
* @param mapper the {@link ObfuscationMapper} to use
|
||||||
* @return the desired method, if it exists
|
* @return the desired method, if it exists
|
||||||
* @throws TargetNotFoundException if it finds no valid candidate
|
* @throws TargetNotFoundException if it finds no valid candidate
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
private VariableElement findField(ExecutableElement stub, SrgMapper mapper) {
|
private VariableElement findField(ExecutableElement stub, ObfuscationMapper mapper) {
|
||||||
Patch patchAnn = stub.getEnclosingElement().getAnnotation(Patch.class);
|
Patch patchAnn = stub.getEnclosingElement().getAnnotation(Patch.class);
|
||||||
FindField fieldAnn = stub.getAnnotation(FindField.class);
|
FindField fieldAnn = stub.getAnnotation(FindField.class);
|
||||||
String parentName = findClassName(getClassFullyQualifiedName(
|
String parentName = findClassName(getClassFullyQualifiedName(
|
||||||
|
@ -307,15 +334,6 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @param cl the {@link TypeElement} for the given class
|
* @param cl the {@link TypeElement} for the given class
|
||||||
*/
|
*/
|
||||||
private void generateInjectors(TypeElement cl) {
|
private void generateInjectors(TypeElement cl) {
|
||||||
SrgMapper mapper = null;
|
|
||||||
try { //TODO: cant we get it from local?
|
|
||||||
URL url = new URL("https://data.fantabos.co/output.tsrg");
|
|
||||||
InputStream is = url.openStream();
|
|
||||||
mapper = new SrgMapper(new BufferedReader(new InputStreamReader(is,
|
|
||||||
StandardCharsets.UTF_8)).lines());
|
|
||||||
is.close();
|
|
||||||
} catch(IOException ignored) {} //TODO: proper handling
|
|
||||||
|
|
||||||
//find class information
|
//find class information
|
||||||
Patch patchAnn = cl.getAnnotation(Patch.class);
|
Patch patchAnn = cl.getAnnotation(Patch.class);
|
||||||
String targetClassSrgName = findClassName(patchAnn, mapper);
|
String targetClassSrgName = findClassName(patchAnn, mapper);
|
||||||
|
@ -481,7 +499,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
* @return a {@link List} of method specs
|
* @return a {@link List} of method specs
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
private List<MethodSpec> generateRequestedProxies(TypeElement cl, SrgMapper mapper) {
|
private List<MethodSpec> generateRequestedProxies(TypeElement cl, ObfuscationMapper mapper) {
|
||||||
List<MethodSpec> generated = new ArrayList<>();
|
List<MethodSpec> generated = new ArrayList<>();
|
||||||
findAnnotatedMethods(cl, FindMethod.class)
|
findAnnotatedMethods(cl, FindMethod.class)
|
||||||
.stream()
|
.stream()
|
||||||
|
|
|
@ -1,211 +0,0 @@
|
||||||
package ftbsc.lll.processor.tools;
|
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a .tsrg file into a mapper capable of converting from
|
|
||||||
* deobfuscated names to SRG names.
|
|
||||||
* Obviously, it may only be used at runtime if the .tsrg file is
|
|
||||||
* included in the resources. However, in that case, I'd recommend
|
|
||||||
* using the built-in Forge one and refrain from including an extra
|
|
||||||
* resource for no good reason.
|
|
||||||
* @since 0.2.0
|
|
||||||
*/
|
|
||||||
public class SrgMapper {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Map using the deobfuscated names as keys,
|
|
||||||
* holding information for that Srg class as value.
|
|
||||||
*/
|
|
||||||
private final Map<String, ObfuscationData> mapper = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The public constructor.
|
|
||||||
* Should be passed a {@link Stream} of Strings, one representing each line.
|
|
||||||
* Whether they contain line endings or not is irrelevant.
|
|
||||||
* @param str a {@link Stream} of strings
|
|
||||||
*/
|
|
||||||
public SrgMapper(Stream<String> str) {
|
|
||||||
AtomicReference<String> currentClass = new AtomicReference<>("");
|
|
||||||
str.forEach(l -> {
|
|
||||||
if(l.startsWith("\t"))
|
|
||||||
mapper.get(currentClass.get()).addMember(l);
|
|
||||||
else {
|
|
||||||
ObfuscationData s = new ObfuscationData(l);
|
|
||||||
currentClass.set(s.mcpName);
|
|
||||||
mapper.put(s.mcpName, s);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the SRG-obfuscated name of the class.
|
|
||||||
* @param mcp the MCP (deobfuscated) internal name of the desired class
|
|
||||||
* @return the SRG name of the class
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
*/
|
|
||||||
public String getSrgClass(String mcp) {
|
|
||||||
ObfuscationData data = mapper.get(mcp);
|
|
||||||
if(data == null)
|
|
||||||
throw new MappingNotFoundException(mcp);
|
|
||||||
else return data.srgName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the MCP (deobfuscated) name of the class.
|
|
||||||
* Due to how it's implemented, it's considerably less efficient than its
|
|
||||||
* opposite operation.
|
|
||||||
* @param srg the SRG-obfuscated internal name of the desired class
|
|
||||||
* @return the MCP name of the class
|
|
||||||
*/
|
|
||||||
public String getMcpClass(String srg) {
|
|
||||||
ObfuscationData data = getObfuscationData(srg);
|
|
||||||
return data.mcpName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets one between the SRG and MCP names.
|
|
||||||
* @param name the internal name of the desired class in either format
|
|
||||||
* @param obf whether it should return the obfuscated name
|
|
||||||
* @return a {@link String} containing the internal name of the class
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
* @since 0.3.0
|
|
||||||
*/
|
|
||||||
public String mapClass(String name, boolean obf) {
|
|
||||||
String srg;
|
|
||||||
try {
|
|
||||||
srg = this.getSrgClass(name);
|
|
||||||
} catch(MappingNotFoundException e) {
|
|
||||||
srg = name;
|
|
||||||
name = this.getMcpClass(srg);
|
|
||||||
}
|
|
||||||
if(obf) return srg;
|
|
||||||
else return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the SRG-obfuscated name of a class member (field or method).
|
|
||||||
* The method signature must be in this format: "methodName methodDescriptor",
|
|
||||||
* with a space, because that's how it is in .tsrg files.
|
|
||||||
* @param mcpClass the MCP (deobfuscated) internal name of the container class
|
|
||||||
* @param member the field name or method signature
|
|
||||||
* @return the SRG name of the given member
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
*/
|
|
||||||
public String getSrgMember(String mcpClass, String member) {
|
|
||||||
ObfuscationData data = mapper.get(mcpClass);
|
|
||||||
if(data == null)
|
|
||||||
throw new MappingNotFoundException(mcpClass + "::" + member);
|
|
||||||
return data.members.get(member);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the MCP (deobfuscated) name of the given member.
|
|
||||||
* Due to how it's implemented, it's considerably less efficient than its
|
|
||||||
* opposite operation.
|
|
||||||
* @param srgClass the SRG-obfuscated internal name of the container class
|
|
||||||
* @param member the field name or method signature
|
|
||||||
* @return the MCP name of the given member
|
|
||||||
*/
|
|
||||||
public String getMcpMember(String srgClass, String member) {
|
|
||||||
ObfuscationData data = getObfuscationData(srgClass);
|
|
||||||
for(String mcp : data.members.keySet())
|
|
||||||
if(data.members.get(mcp).equals(member))
|
|
||||||
return mcp;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obfuscates or deobfuscates a member, given one of its names and the effective.
|
|
||||||
* @param className the internal or fully qualified name of the container class
|
|
||||||
* @param memberName the member of the class
|
|
||||||
* @param obf whether it should return the obfuscated name
|
|
||||||
* @return the mapped member name
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
* @since 0.3.0
|
|
||||||
*/
|
|
||||||
public String mapMember(String className, String memberName, boolean obf) {
|
|
||||||
className = className.replace('.', '/');
|
|
||||||
String effectiveClassName = this.mapClass(className, obf);
|
|
||||||
String srgMemberName;
|
|
||||||
try {
|
|
||||||
srgMemberName = this.getSrgMember(effectiveClassName, memberName);
|
|
||||||
} catch(MappingNotFoundException e) {
|
|
||||||
srgMemberName = memberName;
|
|
||||||
memberName = this.getMcpMember(effectiveClassName, memberName);
|
|
||||||
}
|
|
||||||
if(obf) return srgMemberName;
|
|
||||||
else return memberName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally. Gets the obfuscation data corresponding to the given SRG name.
|
|
||||||
* @return the desired {@link ObfuscationData} object
|
|
||||||
* @throws MappingNotFoundException if no {@link ObfuscationData} object is found
|
|
||||||
*/
|
|
||||||
private ObfuscationData getObfuscationData(String srg) {
|
|
||||||
for(ObfuscationData s : mapper.values())
|
|
||||||
if(s.srgName.equals(srg))
|
|
||||||
return s;
|
|
||||||
throw new MappingNotFoundException(srg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private class used internally for storing information about each
|
|
||||||
* class. It's private because there is no good reason anyone would
|
|
||||||
* want to access this outside of this class.
|
|
||||||
*/
|
|
||||||
private static class ObfuscationData {
|
|
||||||
/**
|
|
||||||
* The MCP internal name (FQN with '/' instad of '.') of the class.
|
|
||||||
*/
|
|
||||||
private final String mcpName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The SRG internal name (FQN with '/' instad of '.') of the class.
|
|
||||||
*/
|
|
||||||
private final String srgName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Map} tying each member's deobfuscated name or signature to its
|
|
||||||
* SRG name.
|
|
||||||
*/
|
|
||||||
private final Map<String, String> members;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor. It takes in the line where the class is declared,
|
|
||||||
* which looks something like this:
|
|
||||||
* {@code internal/name/mcp internal/name/srg }
|
|
||||||
* @param s the String represeting the declaration line
|
|
||||||
*/
|
|
||||||
private ObfuscationData(String s) {
|
|
||||||
String[] split = s.trim().split(" ");
|
|
||||||
this.mcpName = split[0];
|
|
||||||
this.srgName = split[1];
|
|
||||||
this.members = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a member to the target class. It takes in the line where the
|
|
||||||
* member is declared.
|
|
||||||
* For fields it looks like this:
|
|
||||||
* {@code fieldMcpName field_srg_name}
|
|
||||||
* For methods it looks like this:
|
|
||||||
* {@code methodName methodDescriptor method_srg_name}
|
|
||||||
* @param s the String representing the declaration line
|
|
||||||
*/
|
|
||||||
public void addMember(String s) {
|
|
||||||
String[] split = s.trim().split(" ");
|
|
||||||
if(split.length == 2) //field
|
|
||||||
members.put(split[0], split[1]);
|
|
||||||
else if (split.length == 3) //method
|
|
||||||
members.put(split[0] + " " + split[1], split[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
package ftbsc.lll.processor.tools.obfuscation;
|
||||||
|
|
||||||
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a .tsrg file into a mapper capable of converting from
|
||||||
|
* deobfuscated names to obfuscated ones.
|
||||||
|
* Obviously, it may only be used at runtime if the .tsrg file is
|
||||||
|
* included in the resources. However, in that case, I'd recommend
|
||||||
|
* using the built-in Forge one and refrain from including an extra
|
||||||
|
* resource for no good reason.
|
||||||
|
* TODO: CSV format
|
||||||
|
* @since 0.2.0
|
||||||
|
*/
|
||||||
|
public class ObfuscationMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Map using the deobfuscated names as keys,
|
||||||
|
* holding information for that class as value.
|
||||||
|
*/
|
||||||
|
private final Map<String, ObfuscationData> mapper = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public constructor.
|
||||||
|
* Should be passed a {@link Stream} of Strings, one representing each line.
|
||||||
|
* Whether they contain line endings or not is irrelevant.
|
||||||
|
* @param str a {@link Stream} of strings
|
||||||
|
*/
|
||||||
|
public ObfuscationMapper(Stream<String> str) {
|
||||||
|
AtomicReference<String> currentClass = new AtomicReference<>("");
|
||||||
|
str.forEach(l -> {
|
||||||
|
if(l.startsWith("\t"))
|
||||||
|
mapper.get(currentClass.get()).addMember(l);
|
||||||
|
else {
|
||||||
|
String[] sp = l.split(" ");
|
||||||
|
ObfuscationData s = new ObfuscationData(sp[0], sp[1]);
|
||||||
|
currentClass.set(s.unobf);
|
||||||
|
mapper.put(s.unobf, s);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the obfuscated name of the class.
|
||||||
|
* @param name the unobfuscated internal name of the desired class
|
||||||
|
* @return the obfuscated name of the class
|
||||||
|
* @throws MappingNotFoundException if no mapping is found
|
||||||
|
*/
|
||||||
|
public String obfuscateClass(String name) {
|
||||||
|
ObfuscationData data = mapper.get(name);
|
||||||
|
if(data == null)
|
||||||
|
throw new MappingNotFoundException(name);
|
||||||
|
else return data.obf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unobfuscated name of the class.
|
||||||
|
* Due to how it's implemented, it's considerably less efficient than its
|
||||||
|
* opposite operation.
|
||||||
|
* @param obfName the obfuscated internal name of the desired class
|
||||||
|
* @return the deobfuscated name of the class
|
||||||
|
*/
|
||||||
|
public String deobfuscateClass(String obfName) {
|
||||||
|
ObfuscationData data = getObfuscationData(obfName);
|
||||||
|
return data.unobf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the obfuscated name of a class member (field or method).
|
||||||
|
* The method signature must be in this format: "methodName methodDescriptor",
|
||||||
|
* with a space, because that's how it is in .tsrg files.
|
||||||
|
* @param parentName the unobfuscated internal name of the parent class
|
||||||
|
* @param memberName the field name or method signature
|
||||||
|
* @return the obfuscated name of the given member
|
||||||
|
* @throws MappingNotFoundException if no mapping is found
|
||||||
|
*/
|
||||||
|
public String obfuscateMember(String parentName, String memberName) {
|
||||||
|
ObfuscationData data = mapper.get(parentName);
|
||||||
|
if(data == null)
|
||||||
|
throw new MappingNotFoundException(parentName + "::" + memberName);
|
||||||
|
return data.members.get(memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unobfuscated name of the given member.
|
||||||
|
* Due to how it's implemented, it's considerably less efficient than its
|
||||||
|
* opposite operation.
|
||||||
|
* @param parentObf the obfuscated internal name of the container class
|
||||||
|
* @param memberObf the field name or method signature
|
||||||
|
* @return the deobfuscated name of the given member
|
||||||
|
*/
|
||||||
|
public String deobfuscateMember(String parentObf, String memberObf) {
|
||||||
|
ObfuscationData data = getObfuscationData(parentObf);
|
||||||
|
for(String unobf : data.members.keySet())
|
||||||
|
if(data.members.get(unobf).equals(memberObf))
|
||||||
|
return unobf;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally. Gets the obfuscation data corresponding to the given obfuscated class name.
|
||||||
|
* @param classObfuscatedName the internal name of the obfuscated class
|
||||||
|
* @return the desired {@link ObfuscationData} object
|
||||||
|
* @throws MappingNotFoundException if no {@link ObfuscationData} object is found
|
||||||
|
*/
|
||||||
|
private ObfuscationData getObfuscationData(String classObfuscatedName) {
|
||||||
|
for(ObfuscationData s : mapper.values())
|
||||||
|
if(s.obf.equals(classObfuscatedName))
|
||||||
|
return s;
|
||||||
|
throw new MappingNotFoundException(classObfuscatedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private class used internally for storing information about each
|
||||||
|
* class. It's private because there is no good reason anyone would
|
||||||
|
* want to access this outside of this class.
|
||||||
|
*/
|
||||||
|
private static class ObfuscationData {
|
||||||
|
/**
|
||||||
|
* The unobfuscated name (FQN with '/' instad of '.') of the class.
|
||||||
|
*/
|
||||||
|
private final String unobf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The obfuscated internal name (FQN with '/' instad of '.') of the class.
|
||||||
|
*/
|
||||||
|
private final String obf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Map} tying each member's name or signature to its
|
||||||
|
* obfuscated counterpart.
|
||||||
|
*/
|
||||||
|
private final Map<String, String> members;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor. It takes in the names (obfuscated and non-obfuscated)
|
||||||
|
* of a class.
|
||||||
|
* @param unobf the unobfuscated name
|
||||||
|
* @param obf the obfuscated name
|
||||||
|
*/
|
||||||
|
private ObfuscationData(String unobf, String obf) {
|
||||||
|
this.unobf = unobf;
|
||||||
|
this.obf = obf;
|
||||||
|
this.members = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a member to the target class.
|
||||||
|
* For fields only the names are required; for methods,
|
||||||
|
* this takes in the full signature ({@code name + " " + space}).
|
||||||
|
* @param s the String representing the declaration line
|
||||||
|
*/
|
||||||
|
public void addMember(String s) {
|
||||||
|
String[] split = s.trim().split(" ");
|
||||||
|
if(split.length == 2) //field
|
||||||
|
members.put(split[0], split[1]);
|
||||||
|
else if (split.length == 3) //method
|
||||||
|
members.put(split[0] + " " + split[1], split[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue