bukkit
NMS
Suche…
Einführung
NMS, auch bekannt als N et. M inCraft. S erver ist das Paket , das Kernmineserver - Code enthält. Die Kurse in diesem Paket wurden von Mojang (nicht Bukkit) erstellt und sind daher meist verschleiert und nicht dazu gedacht, verwendet oder geändert zu werden. Durch die Interaktion mit dem Minecraft-Servercode auf dieser Ebene können Sie jedoch fast jeden Aspekt davon ändern. Dies ist wichtig, da es zahlreiche Modifikationen gibt, die Bukkit nicht unterstützt.
Bemerkungen
Die Bukkit-API ist eine Wrapper- oder Abstraktionsschicht für NMS, mit der Plug-in-Entwickler mit dem Server interagieren können, ohne sich um Änderungen an der internen Codebase kümmern zu müssen.
Von der Verwendung von NMS-Code wird abgeraten, da er häufig zwischen Änderungen der Minecraft-Version abbricht und nicht von Bukkit oder Spigot unterstützt werden kann, da sie ihn nicht erstellen, besitzen oder verwalten.
Zugriff auf die aktuelle Minecraft-Version
Einer der wichtigsten Aspekte im Umgang mit NMS-Code ist die Unterstützung mehrerer Minecraft-Versionen. Es gibt zahlreiche Möglichkeiten, dies zu tun, aber eine einfache Lösung besteht darin, die Version mit diesem Code als öffentliches statisches Feld zu speichern:
public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().substring(23);
Dieses Code-Snippet funktioniert mit der CraftServer-Klasse:
org.bukkit.craftbukkit.VERSION.CraftServer.class
Das Paket erhalten:
org.bukkit.craftbukkit.VERSION
Und nehmen Sie den Teilstring des Paketnamens ab Index 23, der immer nach 'org.bukkit.craftbukkit' liegt. (mit einer Länge von 23 Zeichen). Ergebnis der letzten VERSION-Zeichenfolge:
VERSION
Es gibt mehrere Gründe, warum es so wichtig ist, auf die aktuelle Minecraft-Version zugreifen zu können. Meistens weil jeder Zugriff auf eine Klasse auf einem Server, auf dem eine andere Minecraft-Version ausgeführt wird als das Plugin, mit dem programmiert wurde, einen Fehler auslöst.
Hier ein Beispiel, das zeigt, wie Sie dieses Problem lösen können, indem Sie das Feld NMS_VERSION
verwenden, um eine Instanz von CraftPlayer (einer NMS-Klasse) in einer beliebigen Minecraft-Version abzurufen.
/**
* 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);
}
}
Das resultierende Objekt kann dann mithilfe von Reflection bearbeitet werden, um NMS-basierte Aufgaben auszuführen, ohne sich darüber Gedanken machen zu müssen, auf die falsche Version der Klasse zuzugreifen.
Selbst diese Methode ist jedoch nicht narrensicher, da sich die Namen von NMS-Feldern und -Methoden leicht ändern. Das einzige, was Sie dadurch garantieren, ist, dass Ihr Code nicht bei jeder Minecraft-Aktualisierung definitiv bricht.
Ping eines Spielers erhalten
Eine sehr einfache Sache, die Sie möglicherweise mit NMS tun möchten, die Bukkit nicht unterstützt, ist der Ping des Spielers. Das kann so gemacht werden:
/**
* 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;
}
Wenn Sie eine Methode wie getCraftPlayer (Player) verwenden, wird eine Instanz der entsprechenden CraftPlayer-Instanz des Players als Objekt zurückgegeben. Sie können auf die Daten zugreifen, ohne die versionsabhängigen Klassen zu importieren, indem Sie Reflection wie folgt verwenden:
/**
* 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);
}
}