Zoeken…


Invoering

NMS, ook bekend als N et. M inecraft. S erver is het pakket dat de kern Minecraft-servercode bevat. De klassen in dit pakket zijn gemaakt door Mojang (niet Bukkit) en zijn daarom meestal onduidelijk en niet bedoeld om te worden gebruikt of gewijzigd. Door interactie met de Minecraft-servercode op dit niveau kunt u echter bijna elk aspect ervan wijzigen. Dit is belangrijk omdat er tal van wijzigingen zijn die Bukkit niet ondersteunt.

Opmerkingen

De Bukkit API is een wrapper- of abstractielaag voor NMS waarmee ontwikkelaars van plug-ins kunnen communiceren met de server zonder zich zorgen te hoeven maken over wijzigingen in de interne codebase.

Het gebruik van NMS-code wordt afgeraden omdat deze vaak wordt onderbroken tussen Minecraft-versiewijzigingen en niet kan worden ondersteund door Bukkit of Spigot omdat deze deze niet maken, bezitten of onderhouden.

Toegang tot de huidige Minecraft-versie

Een van de belangrijkste aspecten van het omgaan met NMS-code is het ondersteunen van meerdere Minecraft-versies. Er zijn talloze manieren om dit te doen, maar een eenvoudige oplossing is om deze code te gebruiken om de versie op te slaan als een publiek statisch veld:

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

Dit codefragment werkt met de CraftServer-klasse:

org.bukkit.craftbukkit.VERSION.CraftServer.class

Het pakket ophalen:

org.bukkit.craftbukkit.VERSION

En neem de substring van de pakketnaam beginnend bij index 23 die altijd achter 'org.bukkit.craftbukkit' staat. (met een lengte van 23 tekens). Met als resultaat de laatste VERSION-reeks:

VERSION

Er zijn een aantal redenen waarom het zo belangrijk is om toegang te hebben tot de huidige Minecraft-versie. Vooral omdat toegang tot een klasse op een server met een andere Minecraft-versie dan waarmee de plug-in codeerde, een foutmelding geeft.

Hier is een voorbeeld dat laat zien hoe u dat probleem kunt oplossen door het veld NMS_VERSION te gebruiken om een instantie van CraftPlayer (wat een NMS-klasse is) op te halen bij elke Minecraft-versie.

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

Het resulterende object kan vervolgens worden gemanipuleerd met behulp van reflectie om op NMS gebaseerde taken uit te voeren zonder zich zorgen te maken over toegang tot de verkeerde versie van de klasse.

Zelfs deze methode is echter niet onfeilbaar, omdat NMS-veld en methodenamen gemakkelijk veranderen, dus het enige dat u hiermee kunt garanderen, is dat uw code niet zeker zal breken telkens wanneer Minecraft-updates worden uitgevoerd.

De ping van een speler krijgen

Een heel eenvoudig ding dat je misschien wilt doen met NMS dat Bukkit niet ondersteunt, is de ping van de speler krijgen. Dit kan als volgt worden gedaan:

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

Als u een methode zoals getCraftPlayer (Player) gebruikt, die een instantie van de overeenkomstige CraftPlayer-instantie van de Player retourneert als een Object. U kunt toegang krijgen tot de gegevens zonder de versie-afhankelijke klassen te importeren door reflectie zoals deze te gebruiken:

/**
 * 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow