访问当前的 Minecraft 版本
处理 NMS 代码最关键的部分之一是能够支持多种 Minecraft 版本。有很多方法可以做到这一点,但一个简单的解决方案是使用此代码将版本存储为公共静态字段:
public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().substring(23);
此代码段通过获取 CraftServer 类来工作:
org.bukkit.craftbukkit.VERSION.CraftServer.class
获得它的包裹:
org.bukkit.craftbukkit.VERSION
并从索引 23 开始获取包名称的子字符串,该索引始终位于’org.bukkit.craftbukkit’之后。 (长度为 23 个字符)。导致最终的 VERSION 字符串:
VERSION
有许多原因导致能够访问当前的 Minecraft 版本如此重要。主要是因为在运行与插件编码的不同的 Minecraft 版本的服务器上的任何类访问都将引发错误。
下面是一个演示如何通过使用 NMS_VERSION
字段在任何 Minecraft 版本上检索 CraftPlayer 实例(这是一个 NMS 类)来解决该问题的示例。
/**
* Invokes the getHandle() method on the player's CraftPlayer instance to
* retrieve the EntityPlayer representation of the player as an Object to
* avoid package version change issues
*
* @param player
* the player to cast
* @return the NMS EnityPlayer representation of the player
*/
public static Object getCraftPlayer(Player player) {
try {
return Class.forName("org.bukkit.craftbukkit." + NMS_VERSION + ".entity.CraftPlayer")
.getMethod("getHandle")
.invoke(player);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException e) {
throw new Error(e);
}
}
然后,可以使用反射来操作生成的对象,以执行基于 NMS 的任务,而无需担心尝试访问类的错误版本。
即使这种方法也不是万无一失,因为 NMS 字段和方法名称很容易改变,所以你唯一要做的就是保证每次 Minecraft 更新时你的代码都不会破坏。