Java 如何从铸造对象反射API调用方法
我需要在Java中使用铸造类型的方法的帮助。如果没有反射,它看起来像Java 如何从铸造对象反射API调用方法,java,reflection,bukkit,Java,Reflection,Bukkit,我需要在Java中使用铸造类型的方法的帮助。如果没有反射,它看起来像PlayerConnection con=((CraftPlayer)player).getHandle().PlayerConnection,但由于我在这个程序/插件中使用的API,包后缀会随着版本号的变化而变化,所以我试图找出一些反射来让它工作。在后面的代码中,我尝试使用con变量将其作为数据包发送,使用PlayerConnection类型中的方法。因此,如果没有反射,它看起来像con.sendPacket(packet)数
PlayerConnection con=((CraftPlayer)player).getHandle().PlayerConnection代码>,但由于我在这个程序/插件中使用的API,包后缀会随着版本号的变化而变化,所以我试图找出一些反射来让它工作。在后面的代码中,我尝试使用con
变量将其作为数据包发送,使用PlayerConnection
类型中的方法。因此,如果没有反射,它看起来像con.sendPacket(packet)代码>数据包变量我想我知道了
关于背景代码信息,我已经创建了一个方法来获取服务器的版本,并创建了另一个方法来获取类。因此,不显示Class.forName()
可以键入getClass(“”),方法返回Class,并且已经在其中添加了包名。有关更多信息,请参见以下示例:
input:
getClass("Packet");
output:
net.minecraft.1_8R2.Packet;
它将返回该包的类。您可以使用
然后,要获得玩家的控制权,您可以使用:
Class<?> craftplayer = getClass("CraftPlayer");
//make another method that chooses the org.bukkit.* class
//instead of the net.minecraft.server.* class, and use that here
//in place of getClass()
Method getHandle = craftplayer.getMethod("getHandle");
Object nms = getHandle.invoke(player);
接下来,您可以使用以下方法获得sendPacket()
方法:
Field connfield = nms.getClass().getField("playerConnection");
Object connection = connfield.get(nms);
Method sendPacket = connection.getClass().getMethod("sendPacket", clazz);
//clazz is getClass("Packet");
然后,您可以使用以下命令使用数据包调用它:
sendPacket.invoke(connection, packet);
//packet is getClass("Packet").newInstance()
所以,你可以用这样的方法:
try{
Class<?> clazz = getClass("Packet");
Object packet = clazz.newInstance();
Class<?> craftplayer = getClass("CraftPlayer");
//make another method that chooses the org.bukkit.* class instead of the net.minecraft.server.* class, and use that here
Method getHandle = craftplayer.getMethod("getHandle");
Object nms = getHandle.invoke(player);
Field connfield = nms.getClass().getField("playerConnection");
Object connection = connfield.get(nms);
Method sendPacket = connection.getClass().getMethod("sendPacket", clazz);
sendPacket.invoke(connection, packet);
}
catch(Exception ex){
//an error occurred, and the packet could not be sent.
ex.printStackTrace();
}
试试看{
clazz类=getClass(“数据包”);
对象包=clazz.newInstance();
Class-craftplayer=getClass(“craftplayer”);
//制作另一个选择org.bukkit.*类而不是net.minecraft.server.*类的方法,并在此处使用它
方法getHandle=craftplayer.getMethod(“getHandle”);
对象nms=getHandle.invoke(播放器);
Field connfield=nms.getClass().getField(“playerConnection”);
对象连接=connfield.get(nms);
方法sendPacket=connection.getClass().getMethod(“sendPacket”,clazz);
调用(连接,数据包);
}
捕获(例外情况除外){
//发生错误,无法发送数据包。
例如printStackTrace();
}
我想您正在实现“Decorator”模式。接着是[link][1][1]:但人们认为PlayerConnection
和CraftPlayer
都来自net.minecraft.18r1代码>包。所以我需要第二到最后一行是动态的。如果我不清楚,很抱歉。如果我错了,请纠正我,但是如果你只使用((CraftPlayer)player.getHandle().playerConnection.sendpack(packet)
我认为你不必导入任何内容…CraftPlayer
必须导入才能将其转换为player
@dennisoficial我刚刚编辑了答案,您只需要创建另一个方法,比如getClass()
,除了让它获取org.bukkit.
classes而不是net.minecraft.server.*
classes,并使用它代替getClass()
用于getClass(“CraftPlayer”)
try{
Class<?> clazz = getClass("Packet");
Object packet = clazz.newInstance();
Class<?> craftplayer = getClass("CraftPlayer");
//make another method that chooses the org.bukkit.* class instead of the net.minecraft.server.* class, and use that here
Method getHandle = craftplayer.getMethod("getHandle");
Object nms = getHandle.invoke(player);
Field connfield = nms.getClass().getField("playerConnection");
Object connection = connfield.get(nms);
Method sendPacket = connection.getClass().getMethod("sendPacket", clazz);
sendPacket.invoke(connection, packet);
}
catch(Exception ex){
//an error occurred, and the packet could not be sent.
ex.printStackTrace();
}