1
    public static void setMOTD(final String motd) throws Exception {
    final Field field = MinecraftServer.class.getDeclaredField("motd");
    final Field server = CraftServer.class.getDeclaredField("console");
    field.setAccessible(true);
    server.setAccessible(true);
    MinecraftServer instance = (MinecraftServer) server.get(CraftServer.class);
    field.set(instance, motd);
}

我的目标是更改我的世界服务器上的每日消息(运行craftbukkit)。为此,我需要更改一个非静态字段 motd。我正在使用插件完成所有这些操作,因此无法获取 MinecraftServer 的实例。最后第二行是我尝试通过反射来做到这一点,但它失败了。我无权更改 MinecraftServer 类或 CraftServer,因为它们位于外部库中。

motd 和 console 都是非静态字段。

motd 是一个带有修饰符 public final 的字符串。

console 是 MinecraftServer 的一个实例,带有修饰符 protected final。

这是我得到的错误(在 setMOTD 的倒数第二行):

2012-07-22 22:16:31 [SEVERE] java.lang.IllegalArgumentException: Can not set final net.minecraft.server.MinecraftServer field org.bukkit.craftbukkit.CraftServer.console to java.lang.Class
4

3 回答 3

2

重新阅读错误消息,它似乎与您的代码不一致。该错误消息似乎暗示您正在尝试成员变量设置为console无效的对象类型。请确认您实际测试的代码。

于 2012-07-23T03:30:07.803 回答
2

通过获取扩展 CraftServer 的 bukkit 实例解决

    public static void setServerMOTD(final String motd) throws Exception {
    final Field field = MinecraftServer.class.getDeclaredField("motd");
    final Field server = CraftServer.class.getDeclaredField("console");
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    field.setAccessible(true);
    server.setAccessible(true);
    modifiersField.setInt(server, server.getModifiers() & ~Modifier.FINAL);
    MinecraftServer instance = (MinecraftServer) server.get(Bukkit.getServer());
    field.set(instance, motd);
}
于 2012-07-23T04:22:02.883 回答
0

根据错误消息,字段控制台在 CraftServer 类中似乎被标记为“最终”。

这意味着一旦设置,您将无法更改它,这将在反射有机会修改它之前发生。

如果 CraftServer 是库的一部分,您可能无法更改此行为

于 2012-07-23T03:00:27.150 回答