1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем sweettie, 28 июл 2021.

Метки:
Статус темы:
Закрыта.
  1. Автор темы
    sweettie

    sweettie Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    _Sweettie_
    Я перелазил пол интернета, и никак не мог найти ответ на свою проблему. У меня есть заготовленная книга (ItemStack) которую надо открыть игроку. Как это можно реализовать (версия 1.12.2)
     
  2. HauserGrim

    HauserGrim Активный участник Пользователь

    Баллы:
    96
  3. Автор темы
    sweettie

    sweettie Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    _Sweettie_
  4. __Void__

    __Void__ Участник Пользователь

    Баллы:
    36
    Общий принцип таков:
    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

    Надеюсь, помог, сам когда то этим занимался)
     
  5. Автор темы
    sweettie

    sweettie Активный участник Пользователь

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

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