support 1.18.2 (#41)

This commit is contained in:
Pierre Maurice Schwang 2022-06-04 00:12:36 +02:00 committed by GitHub
parent b0986504b1
commit 910e7080ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 13 deletions

View File

@ -1,6 +1,8 @@
package de.gerrygames.viarewind.legacysupport.injector;
import com.viaversion.viaversion.api.Via;
import de.gerrygames.viarewind.legacysupport.reflection.MethodSignature;
import de.gerrygames.viarewind.legacysupport.reflection.ReflectionAPI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -120,7 +122,11 @@ public class NMSReflection {
.orElseThrow(() -> new ReflectiveOperationException("Failed to find PlayerConnection field in EntityPlayer"));
}
Object playerConnection = playerConnectionField.get(nmsPlayer);
playerConnection.getClass().getMethod("sendPacket", getPacketClass()).invoke(playerConnection, packet);
ReflectionAPI.pickMethod(
playerConnection.getClass(),
new MethodSignature("sendPacket", getPacketClass()),
new MethodSignature("a", getPacketClass())
).invoke(playerConnection, packet);
} catch (Exception ex) {
ex.printStackTrace();
}

View File

@ -3,6 +3,8 @@ package de.gerrygames.viarewind.legacysupport.listener;
import com.viaversion.viaversion.api.Via;
import de.gerrygames.viarewind.legacysupport.BukkitPlugin;
import de.gerrygames.viarewind.legacysupport.injector.NMSReflection;
import de.gerrygames.viarewind.legacysupport.reflection.MethodSignature;
import de.gerrygames.viarewind.legacysupport.reflection.ReflectionAPI;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
@ -98,20 +100,26 @@ public class SoundListener implements Listener {
if (blockPositionClass != null) {
blockPosition = blockPositionClass.getConstructor(int.class, int.class, int.class).newInstance(block.getX(), block.getY(), block.getZ());
}
Object blockData = nmsWorld.getClass().getSuperclass().getMethod("getType", blockPositionClass).invoke(nmsWorld, blockPosition);
Method getBlock = blockData.getClass().getMethod("getBlock");
Method getTypeMethod = ReflectionAPI.pickMethod(
nmsWorld.getClass(),
new MethodSignature("getType", blockPositionClass),
new MethodSignature("a_", blockPositionClass) // 1.18.2
);
Object blockData = getTypeMethod.invoke(nmsWorld, blockPosition);
Method getBlock = ReflectionAPI.pickMethod(
blockData.getClass(),
new MethodSignature("getBlock"),
new MethodSignature("b") // 1.18.2
);
getBlock.setAccessible(true);
Object nmsBlock = getBlock.invoke(blockData);
Method getStepSound;
try {
getStepSound = nmsBlock.getClass().getMethod("getStepSound", blockData.getClass());
} catch (NoSuchMethodException ex) {
try {
getStepSound = nmsBlock.getClass().getMethod("getStepSound");
} catch (NoSuchMethodException ex2) {
getStepSound = nmsBlock.getClass().getMethod("w");
}
}
Method getStepSound = ReflectionAPI.pickMethod(
nmsBlock.getClass(),
new MethodSignature("m", blockData.getClass()), // 1.18.2
new MethodSignature("w"), // 1.18?
new MethodSignature("getStepSound", blockData.getClass()), // 1.17
new MethodSignature("getStepSound") // pre 1.17
);
Object soundType;
if (getStepSound.getParameterCount() == 0) {

View File

@ -0,0 +1,31 @@
package de.gerrygames.viarewind.legacysupport.reflection;
import java.util.Arrays;
import java.util.StringJoiner;
public class MethodSignature {
private final String name;
private final Class<?>[] parameterTypes;
public MethodSignature(String name, Class<?>... parameterTypes) {
this.name = name;
this.parameterTypes = parameterTypes;
}
public String name() {
return name;
}
public Class<?>[] parameterTypes() {
return parameterTypes;
}
@Override
public String toString() {
return new StringJoiner(", ", MethodSignature.class.getSimpleName() + "[", "]")
.add("name='" + name + "'")
.add("parameterTypes=" + Arrays.toString(parameterTypes))
.toString();
}
}

View File

@ -7,6 +7,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -23,6 +24,34 @@ public class ReflectionAPI {
}
}
public static Method pickMethod(Class<?> holder, String... names) {
return pickMethod(holder, Arrays.stream(names).map(MethodSignature::new).toArray(MethodSignature[]::new));
}
/**
* Recursively searches for (declared) methods at a specific class and all it's superclasses
* @param holder The base class where to start searching
* @param signatures Possible method signatures consisting of method name and parameters
* @return The found {@link Method} or {@code null}
* @throws RuntimeException If no method was found
*/
public static Method pickMethod(Class<?> holder, MethodSignature... signatures) {
Class<?> depth = holder;
do {
for (MethodSignature signature : signatures) {
try {
Method method = depth.getDeclaredMethod(signature.name(), signature.parameterTypes());
if (!method.isAccessible()) {
method.setAccessible(true);
}
return method;
} catch (NoSuchMethodException ignored) {
}
}
} while ((depth = depth.getSuperclass()) != null);
throw new RuntimeException("Failed to resolve method in " + holder + " using " + Arrays.toString(signatures));
}
public static Field getField(Class clazz, String fieldname) {
String key = clazz.getName() + ":" + fieldname;
Field field = null;