我一直在尝试使用 Net Minecraft Server类进行反射,因为它们依赖于版本。我创建了一个模拟PacketPlayOutWorldParticles
的课程,但我想做更多。因为我需要让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
我实际上并不知道是什么导致了它。此外,我还包含没有反射的数据包供参考。
答案 0 :(得分:0)
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);