Improved HTML rendering of obfuscation mapping: added constructor signatures and modifiers for classes, fields and methods
This commit is contained in:
parent
3b30968c15
commit
53869636f5
@ -295,6 +295,8 @@ public class Reflect {
|
|||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract int getModifiers();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,7 +360,10 @@ public class Reflect {
|
|||||||
setValue(null, value);
|
setValue(null, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getModifiers() {
|
||||||
|
return get().getModifiers();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,6 +393,12 @@ public class Reflect {
|
|||||||
public Object invokeStatic(Object... values) throws ReflectiveOperationException {
|
public Object invokeStatic(Object... values) throws ReflectiveOperationException {
|
||||||
return invoke(null, values);
|
return invoke(null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getModifiers() {
|
||||||
|
return get().getModifiers();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -420,6 +431,12 @@ public class Reflect {
|
|||||||
public T instanciate(Object... values) throws ReflectiveOperationException {
|
public T instanciate(Object... values) throws ReflectiveOperationException {
|
||||||
return get().newInstance(values);
|
return get().newInstance(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getModifiers() {
|
||||||
|
return get().getModifiers();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -21,6 +23,7 @@ import fr.pandacube.lib.core.util.Log;
|
|||||||
import fr.pandacube.lib.core.util.Reflect;
|
import fr.pandacube.lib.core.util.Reflect;
|
||||||
import fr.pandacube.lib.core.util.Reflect.ReflectClass;
|
import fr.pandacube.lib.core.util.Reflect.ReflectClass;
|
||||||
import fr.pandacube.lib.core.util.Reflect.ReflectField;
|
import fr.pandacube.lib.core.util.Reflect.ReflectField;
|
||||||
|
import fr.pandacube.lib.core.util.Reflect.ReflectMember;
|
||||||
import fr.pandacube.lib.core.util.Reflect.ReflectMethod;
|
import fr.pandacube.lib.core.util.Reflect.ReflectMethod;
|
||||||
import net.fabricmc.mappingio.MappingReader;
|
import net.fabricmc.mappingio.MappingReader;
|
||||||
import net.fabricmc.mappingio.format.MappingFormat;
|
import net.fabricmc.mappingio.format.MappingFormat;
|
||||||
@ -152,12 +155,13 @@ public class NMSReflect {
|
|||||||
html {
|
html {
|
||||||
background-color: #2F2F2F;
|
background-color: #2F2F2F;
|
||||||
color: white;
|
color: white;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-family: monospace;
|
font-family: Consolas, monospace;
|
||||||
}
|
}
|
||||||
tr:nth-child(2n) {
|
tr:nth-child(2n) {
|
||||||
background-color: #373737;
|
background-color: #373737;
|
||||||
@ -190,6 +194,12 @@ public class NMSReflect {
|
|||||||
.fld {
|
.fld {
|
||||||
color: #8DDAF8;
|
color: #8DDAF8;
|
||||||
}
|
}
|
||||||
|
.st {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.st.fn {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
"""
|
"""
|
||||||
+ "</head><body>\n"
|
+ "</head><body>\n"
|
||||||
@ -216,10 +226,10 @@ public class NMSReflect {
|
|||||||
/* package */ final String obfName;
|
/* package */ final String obfName;
|
||||||
/* package */ final String mojName;
|
/* package */ final String mojName;
|
||||||
|
|
||||||
private final Map<MethodId, MemberMapping<MethodId>> methodsByObf = new TreeMap<>();
|
private final Map<MethodId, MemberMapping<MethodId, ReflectMethod<?>>> methodsByObf = new TreeMap<>();
|
||||||
private final Map<MethodId, MemberMapping<MethodId>> methodsByMoj = new TreeMap<>();
|
private final Map<MethodId, MemberMapping<MethodId, ReflectMethod<?>>> methodsByMoj = new TreeMap<>();
|
||||||
private final Map<String, MemberMapping<String>> fieldsByObf = new TreeMap<>();
|
private final Map<String, MemberMapping<String, ReflectField<?>>> fieldsByObf = new TreeMap<>();
|
||||||
private final Map<String, MemberMapping<String>> fieldsByMoj = new TreeMap<>();
|
private final Map<String, MemberMapping<String, ReflectField<?>>> fieldsByMoj = new TreeMap<>();
|
||||||
|
|
||||||
private ReflectClass<?> runtimeReflectClass = null;
|
private ReflectClass<?> runtimeReflectClass = null;
|
||||||
|
|
||||||
@ -228,10 +238,12 @@ public class NMSReflect {
|
|||||||
mojName = binaryClassName(cls.getName(MOJ_NAMESPACE));
|
mojName = binaryClassName(cls.getName(MOJ_NAMESPACE));
|
||||||
|
|
||||||
cls.getMethods().stream().map(MemberMapping::of).forEach(method -> {
|
cls.getMethods().stream().map(MemberMapping::of).forEach(method -> {
|
||||||
|
method.declaringClass = this;
|
||||||
methodsByObf.put(method.obfDesc.identifier, method);
|
methodsByObf.put(method.obfDesc.identifier, method);
|
||||||
methodsByMoj.put(method.mojDesc.identifier, method);
|
methodsByMoj.put(method.mojDesc.identifier, method);
|
||||||
});
|
});
|
||||||
cls.getFields().stream().map(MemberMapping::of).forEach(field -> {
|
cls.getFields().stream().map(MemberMapping::of).forEach(field -> {
|
||||||
|
field.declaringClass = this;
|
||||||
fieldsByObf.put(field.obfDesc.identifier, field);
|
fieldsByObf.put(field.obfDesc.identifier, field);
|
||||||
fieldsByMoj.put(field.mojDesc.identifier, field);
|
fieldsByMoj.put(field.mojDesc.identifier, field);
|
||||||
});
|
});
|
||||||
@ -273,11 +285,19 @@ public class NMSReflect {
|
|||||||
*/
|
*/
|
||||||
public ReflectMethod<?> mojMethod(String mojName, Object... mojParametersType) throws ClassNotFoundException, NoSuchMethodException {
|
public ReflectMethod<?> mojMethod(String mojName, Object... mojParametersType) throws ClassNotFoundException, NoSuchMethodException {
|
||||||
MethodId mId = new MethodId(mojName, Type.toTypeList(Arrays.asList(mojParametersType)));
|
MethodId mId = new MethodId(mojName, Type.toTypeList(Arrays.asList(mojParametersType)));
|
||||||
MemberMapping<MethodId> mm = methodsByMoj.get(mId);
|
MemberMapping<MethodId, ReflectMethod<?>> mm = methodsByMoj.get(mId);
|
||||||
Objects.requireNonNull(mm, "Unable to find the Mojang mapped method " + mId);
|
Objects.requireNonNull(mm, "Unable to find the Mojang mapped method " + mId);
|
||||||
|
|
||||||
MethodId reflectId = (IS_SERVER_OBFUSCATED ? mm.obfDesc : mm.mojDesc).identifier;
|
try {
|
||||||
return runtimeReflectClass.method(reflectId.name, Type.toClassArray(reflectId.parametersType));
|
return mm.getReflectMember();
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
if (e instanceof ClassNotFoundException cnfe)
|
||||||
|
throw cnfe;
|
||||||
|
if (e instanceof NoSuchMethodException nsme)
|
||||||
|
throw nsme;
|
||||||
|
// should not have another exception
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -291,9 +311,16 @@ public class NMSReflect {
|
|||||||
* @throws NoSuchFieldException if there is no runtime method to represent the provided method.
|
* @throws NoSuchFieldException if there is no runtime method to represent the provided method.
|
||||||
*/
|
*/
|
||||||
public ReflectField<?> mojField(String mojName) throws NoSuchFieldException {
|
public ReflectField<?> mojField(String mojName) throws NoSuchFieldException {
|
||||||
MemberMapping<String> fm = fieldsByMoj.get(mojName);
|
MemberMapping<String, ReflectField<?>> fm = fieldsByMoj.get(mojName);
|
||||||
Objects.requireNonNull(fm, "Unable to find the Mojang mapped field '" + mojName + "'");
|
Objects.requireNonNull(fm, "Unable to find the Mojang mapped field '" + mojName + "'");
|
||||||
return runtimeReflectClass.field((IS_SERVER_OBFUSCATED ? fm.obfDesc : fm.mojDesc).identifier);
|
try {
|
||||||
|
return fm.getReflectMember();
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
if (e instanceof NoSuchFieldException nsfe)
|
||||||
|
throw nsfe;
|
||||||
|
// should not have another exception
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -318,8 +345,9 @@ public class NMSReflect {
|
|||||||
|
|
||||||
|
|
||||||
private void printHTML(PrintStream out) {
|
private void printHTML(PrintStream out) {
|
||||||
out.println("<tr id='c" + id + "'><th class='kw'>" + classKind() + "</th><th>" + nameToHTML(true) + "</th><th>" + nameToHTML(false) + "</th></tr>");
|
out.println("<tr id='c" + id + "'><th class='kw'>" + classModifiers() + "</th><th>" + nameToHTML(true) + "</th><th>" + nameToHTML(false) + "</th></tr>");
|
||||||
fieldsByObf.values().forEach(f -> f.printHTML(out));
|
fieldsByObf.values().forEach(f -> f.printHTML(out));
|
||||||
|
printConstructorsHTML(out);
|
||||||
methodsByObf.values().forEach(m -> m.printHTML(out));
|
methodsByObf.values().forEach(m -> m.printHTML(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +398,41 @@ public class NMSReflect {
|
|||||||
return "record";
|
return "record";
|
||||||
if (clazz.isPrimitive())
|
if (clazz.isPrimitive())
|
||||||
return "primitive";
|
return "primitive";
|
||||||
return "Class";
|
return "class";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String classModifiers() {
|
||||||
|
Class<?> clazz = runtimeClass();
|
||||||
|
int clModifiers = clazz.getModifiers();
|
||||||
|
return modifiersToString(clModifiers) + " " + classKind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void printConstructorsHTML(PrintStream out) {
|
||||||
|
String classObfSimpleName = obfName.substring(obfName.lastIndexOf('.') + 1);
|
||||||
|
String classMojSimpleName = mojName.substring(mojName.lastIndexOf('.') + 1);
|
||||||
|
for (Constructor<?> ct : runtimeClass().getDeclaredConstructors()) {
|
||||||
|
List<Type> obfParams = new ArrayList<>();
|
||||||
|
List<Type> mojParams = new ArrayList<>();
|
||||||
|
for (Class<?> param : ct.getParameterTypes()) {
|
||||||
|
ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(param.getName());
|
||||||
|
if (cm == null) {
|
||||||
|
Type t = Type.of(param);
|
||||||
|
obfParams.add(t);
|
||||||
|
mojParams.add(t);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obfParams.add(cm.toType(true));
|
||||||
|
mojParams.add(cm.toType(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.println("<tr>"
|
||||||
|
+ "<td class='kw'>" + modifiersToString(ct.getModifiers()) + "</td>"
|
||||||
|
+ "<td><b class='mtd' title='Constructor'>" + classObfSimpleName + "</b>(" + obfParams.stream().map(t -> t.toHTML(true)).collect(Collectors.joining(", ")) + ")</td>"
|
||||||
|
+ "<td><b class='mtd' title='Constructor'>" + classMojSimpleName + "</b>(" + mojParams.stream().map(t -> t.toHTML(false)).collect(Collectors.joining(", ")) + ")</td>"
|
||||||
|
+ "</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,9 +452,14 @@ public class NMSReflect {
|
|||||||
return toString().compareTo(o.toString());
|
return toString().compareTo(o.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toHTML(boolean isObfClass) {
|
private String toHTML(boolean isObfClass, boolean isStatic, boolean isFinal) {
|
||||||
String paramsHTML = parametersType.stream().map(p -> p.toHTML(isObfClass)).collect(Collectors.joining(", "));
|
String paramsHTML = parametersType.stream().map(p -> p.toHTML(isObfClass)).collect(Collectors.joining(", "));
|
||||||
String identifierHTML = "<b class='mtd'>" + name + "</b>(" + paramsHTML + ")";
|
String cl = "mtd";
|
||||||
|
if (isStatic)
|
||||||
|
cl += " st";
|
||||||
|
if (isFinal)
|
||||||
|
cl += " fn";
|
||||||
|
String identifierHTML = "<span class='" + cl + "'>" + name + "</span>(" + paramsHTML + ")";
|
||||||
return identifierHTML;
|
return identifierHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,12 +473,18 @@ public class NMSReflect {
|
|||||||
|
|
||||||
|
|
||||||
private static record MemberDesc<I extends Comparable<I>>(I identifier, Type returnType) {
|
private static record MemberDesc<I extends Comparable<I>>(I identifier, Type returnType) {
|
||||||
private String toHTML(boolean isObfClass) {
|
private String toHTML(boolean isObfClass, boolean isStatic, boolean isFinal) { // TODO
|
||||||
String identifierHTML = "";
|
String identifierHTML = "";
|
||||||
if (identifier instanceof MethodId mId)
|
if (identifier instanceof MethodId mId)
|
||||||
identifierHTML = mId.toHTML(isObfClass);
|
identifierHTML = mId.toHTML(isObfClass, isStatic, isFinal);
|
||||||
else if (identifier instanceof String n)
|
else if (identifier instanceof String n) {
|
||||||
identifierHTML = "<b class='fld'>" + n + "</b>";
|
String cl = "fld";
|
||||||
|
if (isStatic)
|
||||||
|
cl += " st";
|
||||||
|
if (isFinal)
|
||||||
|
cl += " fn";
|
||||||
|
identifierHTML = "<span class='" + cl + "'>" + n + "</span>";
|
||||||
|
}
|
||||||
return returnType.toHTML(isObfClass) + " " + identifierHTML;
|
return returnType.toHTML(isObfClass) + " " + identifierHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,25 +520,54 @@ public class NMSReflect {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static class MemberMapping<I extends Comparable<I>> {
|
private static abstract class MemberMapping<I extends Comparable<I>, R extends ReflectMember<?, ?, ?, ?>> {
|
||||||
private String type;
|
|
||||||
/* package */ MemberDesc<I> obfDesc, mojDesc;
|
/* package */ MemberDesc<I> obfDesc, mojDesc;
|
||||||
private MemberMapping(String type, MemberDesc<I> obfDesc, MemberDesc<I> mojDesc) {
|
/* package */ ClassMapping declaringClass;
|
||||||
this.type = type;
|
private MemberMapping(MemberDesc<I> obfDesc, MemberDesc<I> mojDesc) {
|
||||||
this.obfDesc = obfDesc;
|
this.obfDesc = obfDesc;
|
||||||
this.mojDesc = mojDesc;
|
this.mojDesc = mojDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void printHTML(PrintStream out) {
|
/* package */ void printHTML(PrintStream out) {
|
||||||
out.println("<tr><td>" + type + "</td><td>" + obfDesc.toHTML(true) + "</td><td>" + mojDesc.toHTML(false) + "</td></tr>");
|
int mod = 0;
|
||||||
|
try {
|
||||||
|
mod = getReflectMember().getModifiers();
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
boolean isStatic = Modifier.isStatic(mod);
|
||||||
|
boolean isFinal = Modifier.isFinal(mod);
|
||||||
|
out.println("<tr>"
|
||||||
|
+ "<td class='kw'>" + modifiersToString(mod) + "</td>"
|
||||||
|
+ "<td>" + obfDesc.toHTML(true, isStatic, isFinal) + "</td>"
|
||||||
|
+ "<td>" + mojDesc.toHTML(false, isStatic, isFinal) + "</td>"
|
||||||
|
+ "</tr>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MemberMapping<MethodId> of(MappingTree.MethodMapping mioMapping) {
|
/* package */ MemberDesc<I> getReflectDesc() {
|
||||||
return new MemberMapping<>("Method", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE));
|
return (IS_SERVER_OBFUSCATED ? obfDesc : mojDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MemberMapping<String> of(MappingTree.FieldMapping mioMapping) {
|
/* package */ abstract R getReflectMember() throws ReflectiveOperationException;
|
||||||
return new MemberMapping<>("Field", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE));
|
|
||||||
|
private static MemberMapping<MethodId, ReflectMethod<?>> of(MappingTree.MethodMapping mioMapping) {
|
||||||
|
return new MemberMapping<>(MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE)) {
|
||||||
|
@Override
|
||||||
|
ReflectMethod<?> getReflectMember() throws ClassNotFoundException, NoSuchMethodException {
|
||||||
|
MethodId id = getReflectDesc().identifier;
|
||||||
|
return declaringClass.runtimeReflectClass.method(id.name, Type.toClassArray(id.parametersType));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MemberMapping<String, ReflectField<?>> of(MappingTree.FieldMapping mioMapping) {
|
||||||
|
return new MemberMapping<>(MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE)) {
|
||||||
|
@Override
|
||||||
|
ReflectField<?> getReflectMember() throws NoSuchFieldException {
|
||||||
|
String id = getReflectDesc().identifier;
|
||||||
|
return declaringClass.runtimeReflectClass.field(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -474,8 +576,6 @@ public class NMSReflect {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* package */ static String binaryClassName(String cl) {
|
/* package */ static String binaryClassName(String cl) {
|
||||||
return cl.replace('/', '.');
|
return cl.replace('/', '.');
|
||||||
}
|
}
|
||||||
@ -483,4 +583,27 @@ public class NMSReflect {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static String modifiersToString(int elModifiers) {
|
||||||
|
List<String> modifiers = new ArrayList<>();
|
||||||
|
|
||||||
|
if (Modifier.isPublic(elModifiers))
|
||||||
|
modifiers.add("public");
|
||||||
|
if (Modifier.isProtected(elModifiers))
|
||||||
|
modifiers.add("protected");
|
||||||
|
if (Modifier.isPrivate(elModifiers))
|
||||||
|
modifiers.add("private");
|
||||||
|
|
||||||
|
if (Modifier.isStatic(elModifiers))
|
||||||
|
modifiers.add("static");
|
||||||
|
|
||||||
|
if (Modifier.isAbstract(elModifiers))
|
||||||
|
modifiers.add("abstract");
|
||||||
|
if (Modifier.isFinal(elModifiers))
|
||||||
|
modifiers.add("final");
|
||||||
|
|
||||||
|
return String.join(" ", modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user