I have written the following Reflection code:
static Class<?> craftWorld;
static Class<?> worldServer;
static Class<?> movingObjPosClass;
static Class<?> blockPosClass;
static Class<?> vec3DClass;
static Class<?> genAccessClass;
static Class<?> craftBlockClass;
static boolean use112 = false;
public GetTargetBlock113() {
try {
craftWorld = Class.forName("org.bukkit.craftbukkit." + Main.m.getServerVersion() + "CraftWorld");
worldServer = Class.forName("net.minecraft.server." + Main.m.getServerVersion() + "WorldServer");
movingObjPosClass = Class
.forName("net.minecraft.server." + getServerVersion() + "MovingObjectPosition");
blockPosClass = Class
.forName("net.minecraft.server." + getServerVersion() + "BlockPosition");
vec3DClass = Class.forName("net.minecraft.server." + Main.m.getServerVersion() + "Vec3D");
try {
genAccessClass = Class
.forName("net.minecraft.server." + getServerVersion() + "GeneratorAccess");
} catch (ClassNotFoundException e) {
//Error is thrown if on older Minecraft versions
//Ignore as error is expected.
}
craftBlockClass = Class
.forName("org.bukkit.craftbukkit." + Main.m.getServerVersion() + "block.CraftBlock");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Block getBlockLookingAt(Player player, int reach) {
if (player == null) {
throw new IllegalArgumentException("player cannot be null");
}
if (reach < 1 || reach > 120) {
throw new IllegalArgumentException("reach must be between 1-120");
}
Location startLoc = player.getLocation().add(0, player.getEyeHeight(), 0);
Vector start = startLoc.toVector();
Vector direction = startLoc.getDirection().normalize().multiply(reach);
Vector end = start.clone().add(direction);
try {
Constructor<?> con = vec3DClass.getConstructor(double.class, double.class, double.class);
Object from = con.newInstance(start.getX(), start.getY(), start.getZ());
Object to = con.newInstance(end.getX(), end.getY(), end.getZ());
Object converted = craftWorld.cast(player.getWorld());
Method handle = converted.getClass().getMethod("getHandle");
Object worldServObj = handle.invoke(converted);
Object convertedToWorldServer = worldServer.cast(worldServObj);
Class<?>[] rayTraceArgs = new Class<?>[] { vec3DClass, vec3DClass };
Method pingField = convertedToWorldServer.getClass().getMethod("rayTrace", rayTraceArgs);
Object[] args = new Object[] { from, to };
Object movingObjPos = pingField.invoke(worldServObj, args);
if (movingObjPos == null) {
return null;
}
Method getBlockPos = movingObjPosClass.getMethod("a");
Object blockPos = getBlockPos.invoke(movingObjPos);
Block b;
if (genAccessClass != null && !use112) {
Class<?>[] worldPos = new Class<?>[] { genAccessClass, blockPosClass };
Method blockAt = craftBlockClass.getMethod("at", worldPos);
Object[] args2 = new Object[] { worldServObj, blockPos };
b = (Block) blockAt.invoke(blockPos, args2);
}else {
Method getBlockPos1 = blockPosClass.getMethod("getX");
Method getBlockPos2 = blockPosClass.getMethod("getY");
Method getBlockPos3 = blockPosClass.getMethod("getZ");
b = new Location(player.getWorld(), (int) getBlockPos1.invoke(blockPos), (int) getBlockPos2.invoke(blockPos), (int) getBlockPos3.invoke(blockPos)).getBlock();
}
//System.out.println("Found block: " + b.getType());
return b;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
/* WorldServer world = ((CraftWorld) player.getWorld()).getHandle();
MovingObjectPosition rayTrace = world.rayTrace( new Vec3D(start.getX(),
start.getY(), start.getZ()), new Vec3D(end.getX(), end.getY(), end.getZ()));
BlockPosition pos = rayTrace.a();
pos.
return rayTrace == null ? null :
CraftBlock.at(world, pos);*/
}
The purpose of it is to get the target block in a Minecraft Bukkit plugin. It is necessary to do this with Reflection due to the varying class names of new versions, and the impossibility of importing them all.
However, this code is quite laggy.
How could the code to be optimised to be more efficient?