Ricerca…


introduzione

NMS, noto anche come N et. M inecraft. S erver è il pacchetto che contiene il codice del server Minecraft di base. Le classi in questo pacchetto sono state fatte da Mojang (non Bukkit) e sono quindi per lo più offuscate e non destinate a essere utilizzate o modificate. Tuttavia, l'interazione con il codice del server Minecraft a questo livello ti consente di modificarne quasi ogni aspetto. Questo è significativo perché ci sono numerose modifiche che Bukkit non supporta.

Osservazioni

L'API Bukkit è un wrapper o un livello di astrazione per NMS che consente agli sviluppatori di plug-in di interagire con il server senza doversi preoccupare delle modifiche apportate alla base di codice interna.

L'uso del codice NMS è sconsigliato poiché si interrompe spesso tra le modifiche alle versioni di Minecraft e non può essere supportato da Bukkit o Spigot poiché non lo creano, non lo possiedono o lo mantengono.

Accesso alla versione corrente di Minecraft

Una delle parti più critiche nell'affrontare il codice NMS è essere in grado di supportare versioni multiple di Minecraft. Esistono numerosi modi per farlo, ma una soluzione semplice consiste nell'utilizzare questo codice per memorizzare la versione come campo statico pubblico:

public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().substring(23);

Questo frammento di codice funziona prendendo la classe CraftServer:

org.bukkit.craftbukkit.VERSION.CraftServer.class

Ottenere il suo pacchetto:

org.bukkit.craftbukkit.VERSION

E prendendo la sottostringa del nome del pacchetto a partire dall'indice 23 che sarà sempre dopo 'org.bukkit.craftbukkit.' (che ha una lunghezza di 23 caratteri). Risultante nella stringa VERSION finale:

VERSION

Ci sono una serie di motivi per cui è così importante poter accedere alla versione corrente di Minecraft. Principalmente perché qualsiasi accesso a una classe su un server che esegue una versione di Minecraft diversa da quella con cui il plugin stava codificando genererà un errore.

Ecco un esempio che dimostra come risolvere il problema utilizzando il campo NMS_VERSION per recuperare un'istanza di CraftPlayer (che è una classe NMS) su qualsiasi versione di 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);
    }
}

L'oggetto risultante può quindi essere manipolato utilizzando la reflection per eseguire attività basate su NMS senza preoccuparsi di provare ad accedere alla versione errata della classe.

Anche questo metodo non è infallibile, tuttavia, poiché i nomi dei campi e dei metodi NMS cambiano facilmente, quindi l'unica cosa che garantisci è che il tuo codice non si rompe ogni volta che si aggiorna Minecraft.

Ottenere un ping del giocatore

Una cosa molto semplice che potresti voler fare con NMS che Bukkit non supporta è ottenere il ping del giocatore. Questo può essere fatto in questo modo:

/**
 * 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;
}

Se stai usando un metodo come getCraftPlayer (Player) che restituisce un'istanza dell'istanza di CraftPlayer corrispondente del Player come Object. È possibile accedere ai dati senza importare le classi dipendenti dalla versione utilizzando la riflessione come questa:

/**
 * 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow