Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите Открытие книги

Метки:
Теги Теги
book help player
Статус
Закрыто для дальнейших ответов.

sweettie

Активный участник
Пользователь
Баллы
66
Имя в Minecraft
_Sweettie_
Я перелазил пол интернета, и никак не мог найти ответ на свою проблему. У меня есть заготовленная книга (ItemStack) которую надо открыть игроку. Как это можно реализовать (версия 1.12.2)
 
Общий принцип таков:
  1. Сохранить старый предмет в руке игрока
  2. Установить в руку книгу
  3. Открыть книгу
  4. Вернуть старый предмет на место

Вот например (для версий 1.8+ вроде):
Нужно подключить NMS!
Код:
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.*********ventory.ItemStack;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;

public class FakeBook {
    private static final String serverVersion = Bukkit.getServer().getClass().getPackage().getName().substring(23);
    private static Method getHandle;
    private static Method openBook;
    private static Method asNMSCopy;
    private static Object enumHand_MAIN_HAND;
    private static boolean ready;

    static {
        try {
            getHandle = getCraftBukkitClass("entity", "CraftPlayer").getDeclaredMethod("getHandle");
            asNMSCopy = getCraftBukkitClass("inventory", "CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class);
            enumHand_MAIN_HAND = getNMSClass("EnumHand").getEnumConstants()[0];
            /*
               In Minecraft 1.14.3 and lower method that opens the book called "a",
               but in version 1.14.4 it was renamed into "openBook".

               The code below tries to get the "openBook" method,
               but if this is not possible, it gets the "a" method.

               It is impossible to establish dependencies on the version
               stored in the {serverVersion}, since all versions 1.14.* are named "v1_14_R1".
            */
            try {openBook = getNMSClass("EntityPlayer").getDeclaredMethod("openBook", getNMSClass("ItemStack"), getNMSClass("EnumHand"));}
            catch (NoSuchMethodException e) {openBook = getNMSClass("EntityPlayer").getDeclaredMethod("a", getNMSClass("ItemStack"), getNMSClass("EnumHand"));}
            ready = true;
        } catch (NoSuchMethodException | ClassNotFoundException e) {
            Bukkit.getLogger().log(Level.SEVERE, "Required class or method not found");
            ready = false;
        }
    }

    private static Class<?> getNMSClass(String name) throws ClassNotFoundException {
        return Class.forName("net.minecraft.server." + serverVersion + "." + name);
    }

    private static Class<?> getCraftBukkitClass(String pack, String name) throws ClassNotFoundException {
        return Class.forName("org.bukkit.craftbukkit." + serverVersion + "." + pack + "." + name);
    }

    /**
     * Shows the "fake" book to the player
     *
     * @param target the player to whom the book should be displayed
     * @param book book (with configured BookMeta)
     * @return true, if book opening was successful,
     * else - false
     */
    public static boolean openBook(Player target, ItemStack book) {
        if (!ready) return false;
        boolean success;

        ItemStack oldItem = target.getInventory().getItemInMainHand();
        target.getInventory().setItemInMainHand(book);
        try {
            Object entityPlayer = getHandle.invoke(target);
            Object nmsBook = asNMSCopy.invoke(getCraftBukkitClass("entity", "CraftPlayer"), book);
            openBook.invoke(entityPlayer, nmsBook, enumHand_MAIN_HAND);
            success = true;
        } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
            e.printStackTrace();
            success = false;
        }
        target.getInventory().setItemInMainHand(oldItem);
        return success;
    }
}
Использование:
Код:
FakeBook.openBook(player, bookItemsStack);

Вот тот же код, но без рефлексии (для 1.16.2, для других версий нужно менять иморты):
Код:
import net.minecraft.server.v1_16_R2.EntityPlayer;
import net.minecraft.server.v1_16_R2.EnumHand;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.*********ventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

/**
* This is a FakeBook class without reflection
* Target version: v1_16_R2 (Minecraft 1.16.2)
*/
public class FakeBookTest {
    @TestOnly
    public static void openBook(@NotNull Player target, @NotNull ItemStack book) {
        EntityPlayer ePlayer = ((CraftPlayer) target).getHandle();
        ItemStack oldItem = target.getInventory().getItemInMainHand();

        target.getInventory().setItemInMainHand(book);
        ePlayer.openBook(CraftItemStack.asNMSCopy(book), EnumHand.MAIN_HAND);

        target.getInventory().setItemInMainHand(oldItem);
    }
}

В новых версиях есть метод player.openBook(ItemStack book), он без NMS

Надеюсь, помог, сам когда то этим занимался)
 
Общий принцип таков:
  1. Сохранить старый предмет в руке игрока
  2. Установить в руку книгу
  3. Открыть книгу
  4. Вернуть старый предмет на место

Вот например (для версий 1.8+ вроде):
Нужно подключить NMS!
Код:
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.*********ventory.ItemStack;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;

public class FakeBook {
    private static final String serverVersion = Bukkit.getServer().getClass().getPackage().getName().substring(23);
    private static Method getHandle;
    private static Method openBook;
    private static Method asNMSCopy;
    private static Object enumHand_MAIN_HAND;
    private static boolean ready;

    static {
        try {
            getHandle = getCraftBukkitClass("entity", "CraftPlayer").getDeclaredMethod("getHandle");
            asNMSCopy = getCraftBukkitClass("inventory", "CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class);
            enumHand_MAIN_HAND = getNMSClass("EnumHand").getEnumConstants()[0];
            /*
               In Minecraft 1.14.3 and lower method that opens the book called "a",
               but in version 1.14.4 it was renamed into "openBook".

               The code below tries to get the "openBook" method,
               but if this is not possible, it gets the "a" method.

               It is impossible to establish dependencies on the version
               stored in the {serverVersion}, since all versions 1.14.* are named "v1_14_R1".
            */
            try {openBook = getNMSClass("EntityPlayer").getDeclaredMethod("openBook", getNMSClass("ItemStack"), getNMSClass("EnumHand"));}
            catch (NoSuchMethodException e) {openBook = getNMSClass("EntityPlayer").getDeclaredMethod("a", getNMSClass("ItemStack"), getNMSClass("EnumHand"));}
            ready = true;
        } catch (NoSuchMethodException | ClassNotFoundException e) {
            Bukkit.getLogger().log(Level.SEVERE, "Required class or method not found");
            ready = false;
        }
    }

    private static Class<?> getNMSClass(String name) throws ClassNotFoundException {
        return Class.forName("net.minecraft.server." + serverVersion + "." + name);
    }

    private static Class<?> getCraftBukkitClass(String pack, String name) throws ClassNotFoundException {
        return Class.forName("org.bukkit.craftbukkit." + serverVersion + "." + pack + "." + name);
    }

    /**
     * Shows the "fake" book to the player
     *
     * @param target the player to whom the book should be displayed
     * @param book book (with configured BookMeta)
     * @return true, if book opening was successful,
     * else - false
     */
    public static boolean openBook(Player target, ItemStack book) {
        if (!ready) return false;
        boolean success;

        ItemStack oldItem = target.getInventory().getItemInMainHand();
        target.getInventory().setItemInMainHand(book);
        try {
            Object entityPlayer = getHandle.invoke(target);
            Object nmsBook = asNMSCopy.invoke(getCraftBukkitClass("entity", "CraftPlayer"), book);
            openBook.invoke(entityPlayer, nmsBook, enumHand_MAIN_HAND);
            success = true;
        } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
            e.printStackTrace();
            success = false;
        }
        target.getInventory().setItemInMainHand(oldItem);
        return success;
    }
}
Использование:
Код:
FakeBook.openBook(player, bookItemsStack);

Вот тот же код, но без рефлексии (для 1.16.2, для других версий нужно менять иморты):
Код:
import net.minecraft.server.v1_16_R2.EntityPlayer;
import net.minecraft.server.v1_16_R2.EnumHand;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.*********ventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

/**
* This is a FakeBook class without reflection
* Target version: v1_16_R2 (Minecraft 1.16.2)
*/
public class FakeBookTest {
    @TestOnly
    public static void openBook(@NotNull Player target, @NotNull ItemStack book) {
        EntityPlayer ePlayer = ((CraftPlayer) target).getHandle();
        ItemStack oldItem = target.getInventory().getItemInMainHand();

        target.getInventory().setItemInMainHand(book);
        ePlayer.openBook(CraftItemStack.asNMSCopy(book), EnumHand.MAIN_HAND);

        target.getInventory().setItemInMainHand(oldItem);
    }
}

В новых версиях есть метод player.openBook(ItemStack book), он без NMS

Надеюсь, помог, сам когда то этим занимался)

Спасибо большое, очень выручил. Теперь надо это где-то сохранить и не забыть. Тема закрыта!
 
Статус
Закрыто для дальнейших ответов.

Поделиться этой страницей

Назад
Верх