Java 如何从铸造对象反射API调用方法

Java 如何从铸造对象反射API调用方法,java,reflection,bukkit,Java,Reflection,Bukkit,我需要在Java中使用铸造类型的方法的帮助。如果没有反射,它看起来像PlayerConnection con=((CraftPlayer)player).getHandle().PlayerConnection,但由于我在这个程序/插件中使用的API,包后缀会随着版本号的变化而变化,所以我试图找出一些反射来让它工作。在后面的代码中,我尝试使用con变量将其作为数据包发送,使用PlayerConnection类型中的方法。因此,如果没有反射,它看起来像con.sendPacket(packet)数

我需要在Java中使用铸造类型的方法的帮助。如果没有反射,它看起来像
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();
}