Поиск…


Вступление

NMS, также известный как N et. M inecraft. S erver - это пакет, содержащий основной код сервера Minecraft. Классы в этом пакете были сделаны Mojang (не Bukkit) и поэтому в основном запутываются и не предназначены для использования или изменения. Однако взаимодействие с кодом сервера Minecraft на этом уровне позволяет вам модифицировать почти все его аспекты. Это важно, поскольку существуют многочисленные модификации, которые Bukkit не поддерживает.

замечания

API Bukkit - это слой обертки или абстракции для NMS, который позволяет разработчикам плагина взаимодействовать с сервером, не беспокоясь об изменениях, внесенных во внутреннюю кодовую базу.

Использование кода NMS не рекомендуется, поскольку он часто прерывается между изменениями версии Minecraft и не может поддерживаться Bukkit или Spigot, поскольку они не создают, не владеют или не поддерживают его.

Доступ к текущей версии Minecraft

Одной из наиболее важных частей работы с кодом NMS является поддержка версий Mulitple 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 для извлечения экземпляра CraftPlayer (который является классом NMS) в любой версии Minecraft.

/**
 * 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.

Получение пинга игрока

Одна очень простая вещь, которую вы можете захотеть сделать с NMS, которую Bukkit не поддерживает, - это получить пинг игрока. Это можно сделать следующим образом:

/**
 * Gets the players ping by using NMS to access the internal 'ping' field in
 * EntityPlayer
 * 
 * @param player
 *            the player whose ping to get
 * @return the player's ping
 */
public static int getPing(Player player) {
    EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
    return entityPlayer.ping;
}

Если вы используете метод getCraftPlayer (Player), который возвращает экземпляр соответствующего экземпляра CraftPlayer Player как объекта. Вы можете получить доступ к данным, не импортируя классы, зависящие от версии, с помощью отражения следующим образом:

/**
 * Gets the player's ping using reflection to avoid breaking on a Minecraft
 * update
 * 
 * @param player
 *            the player whose ping to get
 * @return the player's ping
 */
public static int getPing(Player player) {
    try {
        Object craftPlayer = getCraftPlayer(player);
        return (int) craftPlayer.getClass().getField("ping").get(craftPlayer);
    } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
        throw new Error(e);
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow