java - 使用 NMS 和反射的 ClassCastException

标签 java reflection bukkit

我一直在尝试将反射与Net Minecraft Server 类结合使用,因为它们与版本相关。我已经创建了一个模拟 PacketPlayOutWorldParticles 的类,但我想做更多。由于我需要让箱子看起来是打开的,因此,首先我确保该数据包能够正常工作。然后我做了这个:

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);
        }
    }
}

第 54 行,即

newInstance(new Object[] { nmsBlockPos, nmsChest, Integer.valueOf(1), Integer.valueOf(open) });

它给了我一个错误:

Error: java.lang.IllegalArgumentException: java.lang.ClassCastException@61f9358b

而且我实际上不知道是什么原因造成的。另外,我还包含了没有反射的数据包以供引用。

最佳答案

nmsChest 的类型为 java.lang.reflect.Field,而不是 whatever.Block。要获取该字段的值,您必须执行以下操作:

  • 如果Blocks.CHEST是一个枚举值(或者是Blocks.Chest?你似乎把它们搞混了):

    nmsChest = Enum.valueOf((Class<Enum>) getNMSClass("Blocks"), "CHEST");
    
  • else if Blocks.CHEST 是一个静态字段(这也适用于枚举值,但看起来不太好):

    nmsChest = getNMSClass("Blocks").getField("CHEST").get(null);
    

关于java - 使用 NMS 和反射的 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37622370/

相关文章:

c# - 在 IL Emit 中将对象添加到循环列表 - 公共(public)语言运行时检测到无效程序

java - Intellij 开始以奇怪的方式显示文件?

java - 错误 : Class is not abstract and does not override abstract method

java - 需要帮助将不同的纹理添加到 JOGL 中的不同对象

java - IOS HMAC-SHA1 不同于标准 Java HMAC-SHA1

java - 使用 OpenID Connect 配置单点登录

java - 关于java泛型的问题

java - "if (rs.next())"是什么意思?

java - 通过反射访问classLoader字段

java - HashMap<UUID,ArrayList<>>, arraylist 不会存储值