mirror of
https://github.com/BG-Software-LLC/WildLoaders.git
synced 2024-11-28 12:56:42 +01:00
Added nms utilities to better detect incorrect usage of nms
This commit is contained in:
parent
2750455435
commit
c0a137ff01
@ -0,0 +1,55 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class MappingParser {
|
||||||
|
|
||||||
|
private static final Pattern NEW_CLASS_REMAP_PATTERN = Pattern.compile("^([^ ]+) -> [^ ]+:$");
|
||||||
|
private static final Pattern FIELD_REMAP_PATTERN = Pattern.compile("^[ ]{4}[^ ]+ ([^ (]+)+ -> ([^ ]+)$");
|
||||||
|
private static final Pattern METHOD_REMAP_PATTERN = Pattern.compile("^[ ]{4}[^ ]+ ([^ ]+)\\(.*\\) -> ([^ ]+)$");
|
||||||
|
|
||||||
|
private MappingParser() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Remapped> parseRemappedMap(File mappingsFile) throws IOException {
|
||||||
|
Map<String, Remapped> remappedMap = new HashMap<>();
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(mappingsFile))) {
|
||||||
|
Remapped currentRemapped = null;
|
||||||
|
String currentLine;
|
||||||
|
|
||||||
|
while ((currentLine = reader.readLine()) != null) {
|
||||||
|
if (currentLine.startsWith("#")) // Comment
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Matcher matcher;
|
||||||
|
|
||||||
|
if ((matcher = NEW_CLASS_REMAP_PATTERN.matcher(currentLine)).matches()) {
|
||||||
|
currentRemapped = new Remapped();
|
||||||
|
remappedMap.put(matcher.group(1), currentRemapped);
|
||||||
|
} else if (currentRemapped != null) {
|
||||||
|
if ((matcher = FIELD_REMAP_PATTERN.matcher(currentLine)).matches()) {
|
||||||
|
String fieldName = matcher.group(1);
|
||||||
|
String obfuscatedName = matcher.group(2);
|
||||||
|
currentRemapped.put(Remap.Type.FIELD, fieldName, obfuscatedName);
|
||||||
|
} else if ((matcher = METHOD_REMAP_PATTERN.matcher(currentLine)).matches()) {
|
||||||
|
String methodName = matcher.group(1);
|
||||||
|
String obfuscatedName = matcher.group(2);
|
||||||
|
currentRemapped.put(Remap.Type.METHOD, methodName, obfuscatedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return remappedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Repeatable(Remaps.class)
|
||||||
|
public @interface Remap {
|
||||||
|
|
||||||
|
String classPath();
|
||||||
|
|
||||||
|
String name();
|
||||||
|
|
||||||
|
Type type();
|
||||||
|
|
||||||
|
String remappedName() default "";
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
|
||||||
|
FIELD,
|
||||||
|
METHOD
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
public class RemapFailure extends RuntimeException {
|
||||||
|
|
||||||
|
public RemapFailure(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Remapped {
|
||||||
|
|
||||||
|
private final EnumMap<Remap.Type, Map<String, List<String>>> mappings = new EnumMap<>(Remap.Type.class);
|
||||||
|
|
||||||
|
public List<String> getObfuscatedNames(String name, Remap.Type type) {
|
||||||
|
Map<String, List<String>> typeMappings = mappings.get(type);
|
||||||
|
|
||||||
|
if (typeMappings != null) {
|
||||||
|
List<String> obfuscatedNames = typeMappings.get(name);
|
||||||
|
if (obfuscatedNames != null)
|
||||||
|
return obfuscatedNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(Remap.Type type, String name, String obfuscated) {
|
||||||
|
mappings.computeIfAbsent(type, t -> new HashMap<>())
|
||||||
|
.computeIfAbsent(name, n -> new ArrayList<>())
|
||||||
|
.add(obfuscated);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Remaps {
|
||||||
|
|
||||||
|
Remap[] value();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.bgsoftware.wildloaders.nms.mapping;
|
||||||
|
|
||||||
|
import com.bgsoftware.common.reflection.ReflectField;
|
||||||
|
import com.bgsoftware.common.reflection.ReflectMethod;
|
||||||
|
import com.google.common.reflect.ClassPath;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class TestRemaps {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger("TestRemaps");
|
||||||
|
|
||||||
|
private static final ReflectField<Field> REFLECT_FIELD_INNER_FIELD = new ReflectField<>(ReflectField.class, Field.class, "field");
|
||||||
|
private static final ReflectField<Method> REFLECT_METHOD_INNER_METHOD = new ReflectField<>(ReflectMethod.class, Method.class, "method");
|
||||||
|
|
||||||
|
private TestRemaps() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public static void testRemapsForClassesInPackage(File mappingsFile, ClassLoader classLoader, String packageName) throws
|
||||||
|
IllegalAccessException, NullPointerException, IOException, RemapFailure {
|
||||||
|
Class<?>[] classes = ClassPath.from(classLoader)
|
||||||
|
.getAllClasses()
|
||||||
|
.stream()
|
||||||
|
.filter(clazz -> clazz.getPackageName().startsWith(packageName))
|
||||||
|
.map(ClassPath.ClassInfo::load)
|
||||||
|
.toArray((IntFunction<Class<?>[]>) Class[]::new);
|
||||||
|
testRemapsForClasses(mappingsFile, classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testRemapsForClasses(File mappingsFile, Class<?>... classes) throws
|
||||||
|
IllegalAccessException, NullPointerException, IOException, RemapFailure {
|
||||||
|
for (Class<?> clazz : classes) {
|
||||||
|
logger.info("Starting remaps test for " + clazz.getName());
|
||||||
|
|
||||||
|
Map<String, Remapped> remappedMap = MappingParser.parseRemappedMap(mappingsFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
|
Remap[] remaps = field.getAnnotationsByType(Remap.class);
|
||||||
|
if (remaps.length > 0) {
|
||||||
|
logger.info("Testing field " + field.getName());
|
||||||
|
for (Remap remap : remaps) {
|
||||||
|
try {
|
||||||
|
testRemap(remappedMap, remap, getRemappedName(field));
|
||||||
|
} catch (Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Method method : clazz.getDeclaredMethods()) {
|
||||||
|
Remap[] remaps = method.getAnnotationsByType(Remap.class);
|
||||||
|
if (remaps.length > 0) {
|
||||||
|
logger.info("Testing method " + method.getName());
|
||||||
|
for (Remap remap : remaps) {
|
||||||
|
try {
|
||||||
|
testRemap(remappedMap, remap, null);
|
||||||
|
} catch (Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable error) {
|
||||||
|
logger.info("Failed remaps test for " + clazz.getName() + ":");
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Finished remaps tests for " + clazz.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String getRemappedName(Field field) throws IllegalAccessException {
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object fieldValue = field.get(null);
|
||||||
|
|
||||||
|
if (fieldValue instanceof ReflectField) {
|
||||||
|
Field innerField = REFLECT_FIELD_INNER_FIELD.get(fieldValue);
|
||||||
|
if (innerField != null)
|
||||||
|
return innerField.getName();
|
||||||
|
} else if (fieldValue instanceof ReflectMethod) {
|
||||||
|
Method innerMethod = REFLECT_METHOD_INNER_METHOD.get(fieldValue);
|
||||||
|
if (innerMethod != null)
|
||||||
|
return innerMethod.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testRemap(Map<String, Remapped> remappedMap, Remap remap, @Nullable String remappedName) {
|
||||||
|
String classPath = remap.classPath();
|
||||||
|
|
||||||
|
Remapped remapped = remappedMap.get(classPath);
|
||||||
|
|
||||||
|
if (remapped == null)
|
||||||
|
throw new NullPointerException("Cannot find remapped object for classPath " + classPath);
|
||||||
|
|
||||||
|
String name = remap.name();
|
||||||
|
Remap.Type type = remap.type();
|
||||||
|
|
||||||
|
List<String> obfuscatedNames = remapped.getObfuscatedNames(name, type);
|
||||||
|
|
||||||
|
if (obfuscatedNames.isEmpty())
|
||||||
|
throw new NullPointerException("Cannot find obfuscated name for " + name + ":" + type);
|
||||||
|
|
||||||
|
String remappedNameOrDefault = remappedName == null ? remap.remappedName() : remappedName;
|
||||||
|
|
||||||
|
if (!obfuscatedNames.contains(remappedNameOrDefault))
|
||||||
|
throw new RemapFailure("Incorrect remap: Expected " + obfuscatedNames + ", found " + remappedNameOrDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user