带有 NMS 和反射的 ClassCastException
ClassCastException with NMS and reflection
我一直在尝试将反射与 Net Minecraft Server classes 一起使用,因为它们依赖于版本。我制作了一个模仿 PacketPlayOutWorldParticles
的 class,但我想做更多。因为我需要让 Chest
看起来是开放的,所以我首先要确保数据包可以正常工作。然后我做了这个:
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");
否则如果 Blocks.CHEST
是一个静态字段(这也适用于枚举值,但看起来不太好):
nmsChest = getNMSClass("Blocks").getField("CHEST").get(null);
我一直在尝试将反射与 Net Minecraft Server classes 一起使用,因为它们依赖于版本。我制作了一个模仿 PacketPlayOutWorldParticles
的 class,但我想做更多。因为我需要让 Chest
看起来是开放的,所以我首先要确保数据包可以正常工作。然后我做了这个:
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");
否则如果
Blocks.CHEST
是一个静态字段(这也适用于枚举值,但看起来不太好):nmsChest = getNMSClass("Blocks").getField("CHEST").get(null);