Util Force open a book

Discussion in 'Resources' started by PhantomUnicorns, Apr 21, 2018.

Thread Status:
Not open for further replies.
  1. Offline

    PhantomUnicorns

    I was roaming the internet for an actual util to open a book that's non-version dependent, clear to read, and would run the best. I couldn't find one that fit all three, so I made a one. Here's the code, the usable part is one method that accepts a player and itemstack and opens the book. (If you're wondering why I use the depreciated methods it's for backwards compatibility. If you would like to remove them, just add Main when you get and set the main hand.)
    Code (open)

    Code:
    import java.lang.reflect.Method;
    
    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    
    public class OpenBook {
    
        private static Class<?> _CRAFTPLAYER_CLASS;
        private static Method _GETHANDLE_METHOD, _A_METHOD;
        private static Object _ITEMSTACK, _MAIN_HAND;
    
        static {
            String name = Bukkit.getServer().getClass().getName();
            name = name.substring(name.indexOf("craftbukkit.") + "craftbukkit.".length());
            final String _VERSION = name.substring(0, name.indexOf("."));
            try {
                _CRAFTPLAYER_CLASS = Class.forName("org.bukkit.craftbukkit." + _VERSION + ".entity.CraftPlayer");
                Class<?> _ITEMSTACK_CLASS = Class.forName("net.minecraft.server." + _VERSION + ".ItemStack");
                Class<?> _ENUMHAND_ENUM = Class.forName("net.minecraft.server." + _VERSION + ".EnumHand");
    
                _GETHANDLE_METHOD = _CRAFTPLAYER_CLASS.getMethod("getHandle");
                _A_METHOD = Class.forName("net.minecraft.server." + _VERSION + ".EntityPlayer").getMethod("a",
                        _ITEMSTACK_CLASS, _ENUMHAND_ENUM);
    
                for (Object obj : _ENUMHAND_ENUM.getEnumConstants()) {
                    if (obj.toString().equals("MAIN_HAND")) {
                        _MAIN_HAND = obj;
                        break;
                    }
                }
    
                _ITEMSTACK = _ITEMSTACK_CLASS.getConstructor(Class.forName("net.minecraft.server." + _VERSION + ".Item"))
                        .newInstance(Class.forName("net.minecraft.server." + _VERSION + ".Items").getField("WRITTEN_BOOK")
                                .get(null));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        @SuppressWarnings("deprecation")
        public static void openBook(Player player, ItemStack book) {
            ItemStack itemInHand = player.getInventory().getItemInHand();
            player.getInventory().setItemInHand(book);
            try {
                Object craftPlayer = _CRAFTPLAYER_CLASS.cast(player);
                Object entityPlayer = _GETHANDLE_METHOD.invoke(craftPlayer);
                _A_METHOD.invoke(entityPlayer, _ITEMSTACK, _MAIN_HAND);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            player.getInventory().setItemInHand(itemInHand);
        }
    }
    

    Any questions or suggestions would be appreciated.

    UPDATE: I changed the some of the fields in the class so it doesn't waste as much ram.
     
    Last edited: May 3, 2018
    Zombie_Striker likes this.
Thread Status:
Not open for further replies.

Share This Page