Resource Force a Player to Open a Book Server Side (with ProtocolLib, no NMS needed)

Discussion in 'Spigot Plugin Development' started by connection_lost, Apr 24, 2017.

  1. Tested and working on 1.9~1.11.2.
    Originally invented by MysteX [here] (NMS version, does not require ProtocolLib).

    Intro
    Yes there is a way. You may force a player to open a book server side. The key to the problem is that server can ask a client to open a book on his hand. If you want the player to open any book, just set that book on his hand briefly and put the original item back.

    Prerequisite
    1. ProtocolLib
    2. You have a book as an ItemStack. The following code will have a book ItemStack defined as "bookitem".

    Code
    Code (Text):
    int slot = p.getInventory().getHeldItemSlot();
    ItemStack old = p.getInventory().getItem(slot);
    p.getInventory().setItem(slot, bookitem);
    try {
        PacketContainer pc = ProtocolLibrary.getProtocolManager().
            createPacket(PacketType.Play.Server.CUSTOM_PAYLOAD);
        pc.getModifier().writeDefaults();
        ByteBuf bf = Unpooled.buffer(256); // note 1
        bf.setByte(0, (byte)0); // note 2
        bf.writerIndex(1);
        pc.getModifier().write(1, MinecraftReflection.getPacketDataSerializer(bf));
        pc.getStrings().write(0, "MC|BOpen");
        ProtocolLibrary.getProtocolManager().sendServerPacket(p, pc);
    } catch (Exception e) {
        e.printStackTrace();
    }
    p.getInventory().setItem(slot, old);
    * note 1: ButeBuf is a class from Netty.
    * note 2: The second argument, (byte)0 refers to open the book on which hand. If you want the player to open the book on his offhand for any reason, use (byte)1.
     
    #1 connection_lost, Apr 24, 2017
    Last edited: Apr 24, 2017
    • Like Like x 1
    • Useful Useful x 1
  2. FrostedSnowman

    Resource Staff

    i dont see a reason to use protocollib, here's the one i use, without:

    Code (Java):

    int slot = player.getInventory().getHeldItemSlot();
    ItemStack original = player.getInventory().getItem(slot);
    player.getInventory().setItem(slot, ItemStack);

    ByteBuf buf = Unpooled.buffer(256);
    buf.setByte(0, (byte) 0);
    buf.writerIndex(1);

    PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf));
    ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);

    player.getInventory().setItem(slot, original);
     
    • Like Like x 2
  3. No NMS or reflection needed is the only reason.
     
    • Agree Agree x 2
    • Like Like x 1