bukkit
NMS
수색…
소개
NMS, 또한 N 외라고도. M inecraft. S erver는 핵심 Minecraft 서버 코드가 포함 된 패키지입니다. 이 패키지의 클래스는 Mojang (Bukkit 아님)에 의해 작성되었으므로 대부분이 난독 화되어 사용되거나 변경되지 않습니다. 그러나이 수준에서 Minecraft 서버 코드와 상호 작용하면 거의 모든 측면을 수정할 수 있습니다. 이는 Bukkit이 지원하지 않는 많은 수정이 있었기 때문에 중요합니다.
비고
Bukkit API는 플러그인 개발자가 내부 코드베이스의 변경 사항을 염려하지 않고 서버와 상호 작용할 수있게 해주는 NMS 용 래퍼 또는 추상화 계층입니다.
NMS 코드의 사용은 Minecraft 버전 변경 사이에 자주 중단되고 Bukkit 또는 Spigot이이를 작성, 소유 또는 유지 관리하지 않으므로 지원되지 않습니다.
현재 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
그리고 'org.bukkit.craftbukkit'다음에 오는 인덱스 23에서 시작하는 패키지 이름의 하위 문자열을 가져옵니다. (길이는 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가 업데이트 할 때마다 코드가 확실히 깨지지 않을 것입니다.
플레이어의 핑 받기
Bukkit이 지원하지 않는 NMS로 할 수있는 아주 간단한 일은 플레이어의 핑을 얻는 것입니다. 이것은 다음과 같이 할 수 있습니다 :
/**
* 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 인스턴스의 인스턴스를 Object로 반환합니다. 다음과 같이 리플렉션을 사용하여 버전 종속 클래스를 가져 오지 않고 데이터에 액세스 할 수 있습니다.
/**
* 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);
}
}