使用Reflection,BukkitAPI时的Java NoSuchFieldError

时间:2017-02-04 19:47:37

标签: bukkit

我正在尝试制作数据包(在bukkit API中)。但是我得到了NoSuchFieldException。

public class PacketPlayOutPlayerInfo {
private static final Class<?> packetClass = Reflections.getCraftClass("PacketPlayOutPlayerInfo");
private static final Class<?>[] typesClass = new Class<?>[]{ String.class, boolean.class, int.class };
private static int type = 0;

static {
    try {
        if (packetClass.getConstructor(typesClass) == null) {
            type = 1;
        }
    } catch (Exception e) {
        type = 1;
    }
}

public static Object getPacket(String s, boolean b, int i) {
    try {
        if (type == 0) {
            return packetClass.getConstructor(typesClass).newInstance(s, b, i);
        }
        else if (type == 1) {
            Class<?> clazz = Reflections.getCraftClass("PacketPlayOutPlayerInfo");
            Object packet = packetClass.getConstructor().newInstance();
            Reflections.getPrivateField(clazz, "username").set(packet, s);
            Reflections.getPrivateField(clazz, "gamemode").set(packet, 1);
            Reflections.getPrivateField(clazz, "ping").set(packet, i);
            Reflections.getPrivateField(clazz, "player").set(packet, new OfflineUser(s).getProfile());
            if (!b) {
                Reflections.getPrivateField(clazz, "action").set(packet, 4);
            }
            return packet;
        }
    } catch (Exception e) {
        if (FunnyGuilds.exception(e.getCause())) {
            e.printStackTrace();
        }
    }
    return null;
}

}

这是完整的错误:

[20:25:43] [IndependentThread/WARN]: java.lang.NoSuchFieldException: username
[20:25:43] [IndependentThread/WARN]:    at java.lang.Class.getDeclaredField(Unknown Source)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.reflect.Reflections.getPrivateField(Reflections.java:123)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.reflect.transition.PacketPlayOutPlayerInfo.getPacket(PacketPlayOutPlayerInfo.java:31)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.packets(PlayerListManager.java:88)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.send(PlayerListManager.java:67)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerList.send(PlayerList.java:160)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.updatePlayers(PlayerListManager.java:24)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.Action.execute(Action.java:37)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.IndependentThread.execute(IndependentThread.java:43)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.IndependentThread.run(IndependentThread.java:28)
[20:25:43] [IndependentThread/WARN]: java.lang.NullPointerException
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.reflect.transition.PacketPlayOutPlayerInfo.getPacket(PacketPlayOutPlayerInfo.java:31)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.packets(PlayerListManager.java:88)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.send(PlayerListManager.java:67)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerList.send(PlayerList.java:160)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.element.PlayerListManager.updatePlayers(PlayerListManager.java:24)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.Action.execute(Action.java:37)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.IndependentThread.execute(IndependentThread.java:43)
[20:25:43] [IndependentThread/WARN]:    at net.dzikoysk.funnyguilds.util.thread.IndependentThread.run(IndependentThread.java:28)

PS:抱歉我的英语不好。

2 个答案:

答案 0 :(得分:1)

由于PacketPlayOutPlayerInfo未定义您尝试访问的字段,因此异常似乎是合适的。鉴于字段名称的选择,我认为您可能正在尝试为PacketPlayOutPlayerInfo.PlayerInfoData设置值;即便如此,它的字段名称也是混淆的,除非你将信息作为构造函数的一部分传递,否则必须这样做。

由于此问题涉及访问反编译的专有代码,我将向您提出以下建议:

  • 熟悉ProtocolLib,因为在管理和调整数据包时,它已经完成了大部分工作。
  • 如果你仍然想弄脏自己的手和DIY,请在GitHub上仔细阅读ProtocolLib的来源。
  • 如果您想了解有关Minecraft课程的详细信息,我建议您使用Spigot BuildTool,如果您还没有。构建过程的副作用是反编译的Minecraft类(请参阅下面的work/decompileXXX/net/minecraft/server目录。此信息将帮助您正确实现反射调用以实例化类和修改的字段。
  

在较旧版本的bukkitapi(1.6-1.7)中,此代码效果很好。

     

要使用ProtocolLib,我必须编辑许多代码。这个类或其他类引起了异常吗?

PacketPlayOutPlayerInfo在1.8中已更改并继续更改。我看了1.8(我可以回去的最远)和1.11.2版本,并且有一个不同的世界。这是使用不属于API的类的问题。他们会随意改变,如果代码在Minecraft之外发生,没有人会流下眼泪。

虽然ProtocolLib也可能破解,但其知识渊博且经验丰富的开发人员会快速解决它。他们必须,因为许多插件使用它来避免新Minecraft版本的令人讨厌的意外。如果ProtocolLib不是你的茶,那么我建议你使用BuildTools,检查反编译类并相应地调整你的代码。点击Minecraft Modern也是件好事。

答案 1 :(得分:0)

我认为你应该检查请求对象变量名称(你的变量应该是camel case)。因为在api调用中,您必须使用api doc中的名称进行请求。