- Баллы
- 66
- Имя в Minecraft
- _Sweettie_
Я перелазил пол интернета, и никак не мог найти ответ на свою проблему. У меня есть заготовленная книга (ItemStack) которую надо открыть игроку. Как это можно реализовать (версия 1.12.2)
Следуйте инструкциям в видео ниже, чтобы узнать, как установить наш сайт как веб-приложение на главный экран вашего устройства.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
У меня нет CraftPlayer и ByteBuf, так что да:/Ну вот например первый результат по "open book spigot": https://www.spigotmc.org/threads/open-book-to-a-player-in-1-14.371118/
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);
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);
}
}
Общий принцип таков:
- Сохранить старый предмет в руке игрока
- Установить в руку книгу
- Открыть книгу
- Вернуть старый предмет на место
Вот например (для версий 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
Надеюсь, помог, сам когда то этим занимался)