diff --git a/Core/src/main/java/fr/pandacube/lib/core/util/Reflect.java b/Core/src/main/java/fr/pandacube/lib/core/util/Reflect.java
index 7d82cd9..52dcabf 100644
--- a/Core/src/main/java/fr/pandacube/lib/core/util/Reflect.java
+++ b/Core/src/main/java/fr/pandacube/lib/core/util/Reflect.java
@@ -295,6 +295,8 @@ public class Reflect {
return cached;
}
+ public abstract int getModifiers();
+
}
@@ -358,7 +360,10 @@ public class Reflect {
setValue(null, value);
}
-
+ @Override
+ public int getModifiers() {
+ return get().getModifiers();
+ }
}
@@ -388,6 +393,12 @@ public class Reflect {
public Object invokeStatic(Object... values) throws ReflectiveOperationException {
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 {
return get().newInstance(values);
}
+
+ @Override
+ public int getModifiers() {
+ return get().getModifiers();
+ }
+
}
diff --git a/Paper/src/main/java/fr/pandacube/lib/paper/reflect/NMSReflect.java b/Paper/src/main/java/fr/pandacube/lib/paper/reflect/NMSReflect.java
index 3e4459f..3aa82a8 100644
--- a/Paper/src/main/java/fr/pandacube/lib/paper/reflect/NMSReflect.java
+++ b/Paper/src/main/java/fr/pandacube/lib/paper/reflect/NMSReflect.java
@@ -5,6 +5,8 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
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.ReflectClass;
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 net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.format.MappingFormat;
@@ -152,12 +155,13 @@ public class NMSReflect {
html {
background-color: #2F2F2F;
color: white;
+ font-size: 14px;
}
table {
border-collapse: collapse;
width: 100%;
margin: auto;
- font-family: monospace;
+ font-family: Consolas, monospace;
}
tr:nth-child(2n) {
background-color: #373737;
@@ -190,6 +194,12 @@ public class NMSReflect {
.fld {
color: #8DDAF8;
}
+ .st {
+ font-style: italic;
+ }
+ .st.fn {
+ font-weight: bold;
+ }
"""
+ "
\n"
@@ -216,10 +226,10 @@ public class NMSReflect {
/* package */ final String obfName;
/* package */ final String mojName;
- private final Map> methodsByObf = new TreeMap<>();
- private final Map> methodsByMoj = new TreeMap<>();
- private final Map> fieldsByObf = new TreeMap<>();
- private final Map> fieldsByMoj = new TreeMap<>();
+ private final Map>> methodsByObf = new TreeMap<>();
+ private final Map>> methodsByMoj = new TreeMap<>();
+ private final Map>> fieldsByObf = new TreeMap<>();
+ private final Map>> fieldsByMoj = new TreeMap<>();
private ReflectClass> runtimeReflectClass = null;
@@ -228,10 +238,12 @@ public class NMSReflect {
mojName = binaryClassName(cls.getName(MOJ_NAMESPACE));
cls.getMethods().stream().map(MemberMapping::of).forEach(method -> {
+ method.declaringClass = this;
methodsByObf.put(method.obfDesc.identifier, method);
methodsByMoj.put(method.mojDesc.identifier, method);
});
cls.getFields().stream().map(MemberMapping::of).forEach(field -> {
+ field.declaringClass = this;
fieldsByObf.put(field.obfDesc.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 {
MethodId mId = new MethodId(mojName, Type.toTypeList(Arrays.asList(mojParametersType)));
- MemberMapping mm = methodsByMoj.get(mId);
+ MemberMapping> mm = methodsByMoj.get(mId);
Objects.requireNonNull(mm, "Unable to find the Mojang mapped method " + mId);
- MethodId reflectId = (IS_SERVER_OBFUSCATED ? mm.obfDesc : mm.mojDesc).identifier;
- return runtimeReflectClass.method(reflectId.name, Type.toClassArray(reflectId.parametersType));
+ try {
+ 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.
*/
public ReflectField> mojField(String mojName) throws NoSuchFieldException {
- MemberMapping fm = fieldsByMoj.get(mojName);
+ MemberMapping> fm = fieldsByMoj.get(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) {
- out.println("" + classKind() + " | " + nameToHTML(true) + " | " + nameToHTML(false) + " |
");
+ out.println("" + classModifiers() + " | " + nameToHTML(true) + " | " + nameToHTML(false) + " |
");
fieldsByObf.values().forEach(f -> f.printHTML(out));
+ printConstructorsHTML(out);
methodsByObf.values().forEach(m -> m.printHTML(out));
}
@@ -370,8 +398,42 @@ public class NMSReflect {
return "record";
if (clazz.isPrimitive())
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 obfParams = new ArrayList<>();
+ List 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(""
+ + "" + modifiersToString(ct.getModifiers()) + " | "
+ + "" + classObfSimpleName + "(" + obfParams.stream().map(t -> t.toHTML(true)).collect(Collectors.joining(", ")) + ") | "
+ + "" + classMojSimpleName + "(" + mojParams.stream().map(t -> t.toHTML(false)).collect(Collectors.joining(", ")) + ") | "
+ + "
");
+ }
+
+ }
}
@@ -390,9 +452,14 @@ public class NMSReflect {
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 identifierHTML = "" + name + "(" + paramsHTML + ")";
+ String cl = "mtd";
+ if (isStatic)
+ cl += " st";
+ if (isFinal)
+ cl += " fn";
+ String identifierHTML = "" + name + "(" + paramsHTML + ")";
return identifierHTML;
}
@@ -406,12 +473,18 @@ public class NMSReflect {
private static record MemberDesc>(I identifier, Type returnType) {
- private String toHTML(boolean isObfClass) {
+ private String toHTML(boolean isObfClass, boolean isStatic, boolean isFinal) { // TODO
String identifierHTML = "";
if (identifier instanceof MethodId mId)
- identifierHTML = mId.toHTML(isObfClass);
- else if (identifier instanceof String n)
- identifierHTML = "" + n + "";
+ identifierHTML = mId.toHTML(isObfClass, isStatic, isFinal);
+ else if (identifier instanceof String n) {
+ String cl = "fld";
+ if (isStatic)
+ cl += " st";
+ if (isFinal)
+ cl += " fn";
+ identifierHTML = "" + n + "";
+ }
return returnType.toHTML(isObfClass) + " " + identifierHTML;
}
@@ -447,25 +520,54 @@ public class NMSReflect {
- private static class MemberMapping> {
- private String type;
+ private static abstract class MemberMapping, R extends ReflectMember, ?, ?, ?>> {
/* package */ MemberDesc obfDesc, mojDesc;
- private MemberMapping(String type, MemberDesc obfDesc, MemberDesc mojDesc) {
- this.type = type;
+ /* package */ ClassMapping declaringClass;
+ private MemberMapping(MemberDesc obfDesc, MemberDesc mojDesc) {
this.obfDesc = obfDesc;
this.mojDesc = mojDesc;
}
/* package */ void printHTML(PrintStream out) {
- out.println("" + type + " | " + obfDesc.toHTML(true) + " | " + mojDesc.toHTML(false) + " |
");
+ int mod = 0;
+ try {
+ mod = getReflectMember().getModifiers();
+ } catch (ReflectiveOperationException e) {
+ // ignore
+ }
+ boolean isStatic = Modifier.isStatic(mod);
+ boolean isFinal = Modifier.isFinal(mod);
+ out.println(""
+ + "" + modifiersToString(mod) + " | "
+ + "" + obfDesc.toHTML(true, isStatic, isFinal) + " | "
+ + "" + mojDesc.toHTML(false, isStatic, isFinal) + " | "
+ + "
");
}
- private static MemberMapping of(MappingTree.MethodMapping mioMapping) {
- return new MemberMapping<>("Method", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE));
+ /* package */ MemberDesc getReflectDesc() {
+ return (IS_SERVER_OBFUSCATED ? obfDesc : mojDesc);
}
- private static MemberMapping of(MappingTree.FieldMapping mioMapping) {
- return new MemberMapping<>("Field", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE));
+ /* package */ abstract R getReflectMember() throws ReflectiveOperationException;
+
+ private static MemberMapping> 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> 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,13 +576,34 @@ public class NMSReflect {
-
-
/* package */ static String binaryClassName(String cl) {
return cl.replace('/', '.');
}
+
+
+ private static String modifiersToString(int elModifiers) {
+ List 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);
+ }
+
}