diff --git a/src/main/java/net/coreprotect/bukkit/BukkitAdapter.java b/src/main/java/net/coreprotect/bukkit/BukkitAdapter.java index 78b61eb5..3b26fae2 100644 --- a/src/main/java/net/coreprotect/bukkit/BukkitAdapter.java +++ b/src/main/java/net/coreprotect/bukkit/BukkitAdapter.java @@ -9,6 +9,7 @@ import org.bukkit.Tag; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; @@ -16,6 +17,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.LivingEntity; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.meta.ItemMeta; @@ -217,4 +219,14 @@ public boolean isChiseledBookshelf(Material material) { return false; } + @Override + public boolean isBookshelfBook(Material material) { + return false; + } + + @Override + public ItemStack getChiseledBookshelfBook(BlockState blockState, PlayerInteractEvent event) { + return null; + } + } diff --git a/src/main/java/net/coreprotect/bukkit/BukkitInterface.java b/src/main/java/net/coreprotect/bukkit/BukkitInterface.java index f28962ae..7797fcc6 100644 --- a/src/main/java/net/coreprotect/bukkit/BukkitInterface.java +++ b/src/main/java/net/coreprotect/bukkit/BukkitInterface.java @@ -6,11 +6,13 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.meta.ItemMeta; @@ -69,4 +71,8 @@ public interface BukkitInterface { public boolean isChiseledBookshelf(Material material); + public boolean isBookshelfBook(Material material); + + public ItemStack getChiseledBookshelfBook(BlockState blockState, PlayerInteractEvent event); + } diff --git a/src/main/java/net/coreprotect/bukkit/Bukkit_v1_20.java b/src/main/java/net/coreprotect/bukkit/Bukkit_v1_20.java index 0561b80d..e9e001b8 100644 --- a/src/main/java/net/coreprotect/bukkit/Bukkit_v1_20.java +++ b/src/main/java/net/coreprotect/bukkit/Bukkit_v1_20.java @@ -7,13 +7,19 @@ import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.Tag; +import org.bukkit.block.BlockState; +import org.bukkit.block.ChiseledBookshelf; import org.bukkit.block.Sign; import org.bukkit.block.sign.Side; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; import net.coreprotect.model.BlockGroup; public class Bukkit_v1_20 extends Bukkit_v1_19 implements BukkitInterface { + private Boolean hasClickedPosition = null; + public Bukkit_v1_20() { BlockGroup.CONTAINERS = new HashSet<>(Arrays.asList(Material.JUKEBOX, Material.DISPENSER, Material.CHEST, Material.FURNACE, Material.BREWING_STAND, Material.TRAPPED_CHEST, Material.HOPPER, Material.DROPPER, Material.ARMOR_STAND, Material.ITEM_FRAME, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX, Material.BARREL, Material.BLAST_FURNACE, Material.SMOKER, Material.LECTERN, Material.CHISELED_BOOKSHELF)); BlockGroup.UPDATE_STATE = new HashSet<>(Arrays.asList(Material.TORCH, Material.WALL_TORCH, Material.REDSTONE_WIRE, Material.RAIL, Material.POWERED_RAIL, Material.DETECTOR_RAIL, Material.FURNACE, Material.BLAST_FURNACE, Material.SMOKER, Material.LEVER, Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH, Material.GLOWSTONE, Material.JACK_O_LANTERN, Material.REPEATER, Material.REDSTONE_LAMP, Material.BEACON, Material.COMPARATOR, Material.DAYLIGHT_DETECTOR, Material.REDSTONE_BLOCK, Material.HOPPER, Material.CHEST, Material.TRAPPED_CHEST, Material.ACTIVATOR_RAIL, Material.SOUL_TORCH, Material.SOUL_WALL_TORCH, Material.SHROOMLIGHT, Material.RESPAWN_ANCHOR, Material.CRYING_OBSIDIAN, Material.TARGET, Material.SMALL_AMETHYST_BUD, Material.MEDIUM_AMETHYST_BUD, Material.LARGE_AMETHYST_BUD, Material.AMETHYST_CLUSTER, Material.CAVE_VINES, Material.CAVE_VINES_PLANT, Material.GLOW_LICHEN, Material.LIGHT, Material.LAVA_CAULDRON, Material.CHISELED_BOOKSHELF)); @@ -109,4 +115,30 @@ public boolean isChiseledBookshelf(Material material) { return material == Material.CHISELED_BOOKSHELF; } + @Override + public boolean isBookshelfBook(Material material) { + return Tag.ITEMS_BOOKSHELF_BOOKS.isTagged(material); + } + + @Override + public ItemStack getChiseledBookshelfBook(BlockState blockState, PlayerInteractEvent event) { + try { + if (hasClickedPosition == null) { + hasClickedPosition = true; + PlayerInteractEvent.class.getMethod("getClickedPosition"); // Bukkit 1.20.1+ + } + else if (Boolean.FALSE.equals(hasClickedPosition)) { + return null; + } + + ChiseledBookshelf chiseledBookshelf = (ChiseledBookshelf) blockState; + ItemStack book = chiseledBookshelf.getInventory().getItem(chiseledBookshelf.getSlot(event.getClickedPosition())); + return book == null ? new ItemStack(Material.AIR) : book; + } + catch (Exception e) { + hasClickedPosition = false; + return null; + } + } + } diff --git a/src/main/java/net/coreprotect/listener/player/PlayerInteractListener.java b/src/main/java/net/coreprotect/listener/player/PlayerInteractListener.java index b79b5c95..a382f3ee 100755 --- a/src/main/java/net/coreprotect/listener/player/PlayerInteractListener.java +++ b/src/main/java/net/coreprotect/listener/player/PlayerInteractListener.java @@ -687,7 +687,41 @@ else if (event.getHand().equals(EquipmentSlot.OFF_HAND) && offHand != null && Ta else if (BukkitAdapter.ADAPTER.isChiseledBookshelf(type)) { BlockState blockState = block.getState(); if (blockState instanceof BlockInventoryHolder) { - InventoryChangeListener.inventoryTransaction(player.getName(), blockState.getLocation(), null); + ItemStack book = BukkitAdapter.ADAPTER.getChiseledBookshelfBook(blockState, event); + if (book != null) { + ItemStack oldItemState = book.clone(); + ItemStack newItemState = new ItemStack(Material.AIR); + + if (book.getType() == Material.AIR) { + ItemStack handItem = null; + ItemStack mainHand = player.getInventory().getItemInMainHand(); + ItemStack offHand = player.getInventory().getItemInOffHand(); + + if (event.getHand().equals(EquipmentSlot.HAND) && mainHand != null && BukkitAdapter.ADAPTER.isBookshelfBook(mainHand.getType())) { + handItem = mainHand; + } + else if (event.getHand().equals(EquipmentSlot.OFF_HAND) && offHand != null && BukkitAdapter.ADAPTER.isBookshelfBook(offHand.getType())) { + handItem = offHand; + } + else { + return; + } + + oldItemState = new ItemStack(Material.AIR); + newItemState = handItem.clone(); + } + + if (!oldItemState.equals(newItemState)) { + if (Config.getConfig(player.getWorld()).PLAYER_INTERACTIONS) { + Queue.queuePlayerInteraction(player.getName(), blockState, type); + } + + InventoryChangeListener.inventoryTransaction(player.getName(), blockState.getLocation(), null); + } + } + else { // fallback if unable to determine bookshelf slot + InventoryChangeListener.inventoryTransaction(player.getName(), blockState.getLocation(), null); + } } } else if (type == Material.DRAGON_EGG) {