vendredi 3 juin 2016

ClassCastException with NMS and reflection

I've been trying to use reflection with Net Minecraft Server classes since they are version dependent. I've made a class that emulates the PacketPlayOutWorldParticles, but I wanted to do more. Since I needed to make a Chest look open and so, first I made sure that the packet would work. Then I made this:

public class ChestReflection {
// Reference
// PacketPlayOutBlockAction packet = new PacketPlayOutBlockAction(new
// BlockPosition(x, y, z), BlockChest, 1, 1);

private Class<?> getNMSClass(String nmsClassString) throws ClassNotFoundException {
    String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3] + ".";
    String name = "net.minecraft.server." + version + nmsClassString;
    Class<?> nmsClass = Class.forName(name);
    return nmsClass;
}

private Object getConnection(Player player) throws SecurityException, NoSuchMethodException, NoSuchFieldException,
        IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    Method getHandle = player.getClass().getMethod("getHandle");
    Object nmsPlayer = getHandle.invoke(player);
    Field conField = nmsPlayer.getClass().getField("playerConnection");
    Object con = conField.get(nmsPlayer);
    return con;
}

private Object getBlockPosition(Location loc)
        throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
        InvocationTargetException, NoSuchMethodException, SecurityException {
    Class<?> nmsBlockPosition = getNMSClass("BlockPosition");
    Object nmsBlockPositionInstance = nmsBlockPosition
            .getConstructor(new Class[] { Double.TYPE, Double.TYPE, Double.TYPE })
            .newInstance(new Object[] { loc.getX(), loc.getY(), loc.getZ() });

    return nmsBlockPositionInstance;
}

public void setChest(Player player, int open, Location loc) {
    try {
        Class<?> nmsBlockPositionClass = getNMSClass("BlockPosition");
        Object nmsBlockPos = getBlockPosition(loc);
        Class<?> nmsPacketBlockAction = getNMSClass("PacketPlayOutBlockAction");
        Class<?> nmsBlock = getNMSClass("Block");
        Object nmsChest = getNMSClass("Blocks").getField("Chest");
        Class<?> nmsPacket = getNMSClass("Packet");

        Object nmsPackInstance = nmsPacketBlockAction
                .getConstructor(new Class[] { nmsBlockPositionClass, nmsBlock, Integer.TYPE, Integer.TYPE })
                .newInstance(new Object[] { nmsBlockPos, nmsChest, Integer.valueOf(1), Integer.valueOf(open) });
        Method sendPacket = getConnection(player).getClass().getMethod("sendPacket", nmsPacket);
        sendPacket.invoke(new Object[] { nmsPackInstance });

    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
            | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException e) {
        e.printStackTrace();
    }
    -this is the reference-
    new PacketPlayOutBlockAction(new BlockPosition(loc.getX(), loc.getY(), loc.getZ()), Blocks.CHEST, 1, 0);
}

public void setChestOpenForEveryone(int open, Location loc) {
    for (Player player : Bukkit.getOnlinePlayers()) {
        setChest(player, open, loc);
    }
}

}

And it gives me an error, at line 54 wich is .newInstance(new Object[] { nmsBlockPos, nmsChest, Integer.valueOf(1), Integer.valueOf(open) }); Error: java.lang.IllegalArgumentException: java.lang.ClassCastException@61f9358b

And I don't actually know what is causing it. Also I have included the packet without reflection for reference.

Sorry if this is formatted badly, but I could not get all the code in the 'code' cointainer.





Aucun commentaire:

Enregistrer un commentaire