[Snippet] Interactive Books

Discussion in 'Spigot Plugin Development' started by gigosaurus, May 9, 2015.

  1. gigosaurus

    Supporter

    To go on http://www.spigotmc.org/wiki/plugin-snippets/, posted here for peer reviewing.

    This is how you can create a book with click and hover events.

    Creating the Book

    To begin with, we will need to obtain the BookMeta from a ItemStack. Only an ItemStack with Material.BOOK_AND_QUILL or Material.WRITTEN_BOOK have this.
    Code (Java):
    ItemStack book = new ItemStack(Material.WRITTEN_BOOK);
    BookMeta bookMeta = (BookMeta) book.getItemMeta();

    Getting the Pages

    BookMeta is the Bukkit interface for the CraftMetaBook object in CraftBukkit. As of when this guide was written, the BookMeta interface does not have a method to obtain the pages as a list of IChatBaseComponent objects (which is what is stored in CraftMetaBook). This means we will have to get the pages using reflection. Here is an example of how you can do that.
    Code (Java):
    List<IChatBaseComponent> pages = (List<IChatBaseComponent>) CraftMetaBook.class.getDeclaredField("pages").get(bookMeta);
    Any changes we make to this list will update the book and so there is no need to set the field back after we are done with it.


    Creating a Page With Click/Hover Events

    Using the BungeeCord chat component API (which is included in the spigot server jar) you can produce an IChatBaseComponent which contains click and hover events.
    Alternatively you could generate your own jsonString which will enable you to use book specific events.
    Code (Java):
    BaseComponent text; //this is the base component we will be turning into a page

    //convert the base component into a json string
    String pageJson = ComponentSerializer.toString(text);

    //get an IChatBaseComponent object which represents this json string
    IChatBaseComponent page = IChatBaseComponent.ChatSerializer.a(pageJson);

    //add this page to the pages list
    pages.add(page);

    Finish Creating the ItemStack

    Once you've finished adding the pages, don't forget to add this new BookMeta to the original ItemStack! You can also set a title and an author for the book.
    Code (Java):
    bookMeta.setTitle("Interactive Book");
    bookMeta.setAuthor("gigosaurus");

    book.setItemMeta(bookMeta);

    An Example Book

    Code (Java):
    //create the book
    ItemStack book = new ItemStack(Material.WRITTEN_BOOK);
    BookMeta bookMeta = (BookMeta) book.getItemMeta();
    List<IChatBaseComponent> pages;

    //get the pages
    try {
        pages = (List<IChatBaseComponent>) CraftMetaBook.class.getDeclaredField("pages").get(bookMeta);
    } catch (ReflectiveOperationException ex) {
        ex.printStackTrace();
        return;
    }

    //create a page
    TextComponent text = new TextComponent("Click me");
    text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "http://spigotmc.org"));
    text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Goto the spigot website!").create()));

    //add the page to the list of pages
    IChatBaseComponent page = ChatSerializer.a(ComponentSerializer.toString(text));
    pages.add(page);

    //set the title and author of this book
    bookMeta.setTitle("Interactive Book");
    bookMeta.setAuthor("gigosaurus");

    //update the ItemStack with this new meta
    book.setItemMeta(bookMeta);
     
    • Like Like x 2
  2. Wow thank you guy! I was wondering how to do it! ;)
     
  3. Nice tutorial! :)
     
  4. Can you give an example class? baceuse I keep getting error's :/

    EDIT: example error:
    Code (Text):
    CraftMetaBook cannot be resolved to a type
     
  5. You need to compile against CraftBukkit/Spigot for OBC; you're compiling against the API.
     
  6. Do you also know how to make it that if someone clicks on the text, it opens another page?
     
  7. And how to make multiple click/hover-able texts on 1 page?