수색…


소개

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


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow