diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java index b8c5f6471..3098b654a 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java @@ -237,7 +237,6 @@ public class BlockInteractionListener extends FlagListener { case ITEM_FRAME: checkIsland(e, player, loc, Flags.ITEM_FRAME); break; - case LECTERN: case SWEET_BERRY_BUSH: checkIsland(e, player, loc, Flags.BREAK_BLOCKS); break; diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LecternListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LecternListener.java new file mode 100644 index 000000000..ba4ca43a0 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LecternListener.java @@ -0,0 +1,31 @@ +package world.bentobox.bentobox.listeners.flags.protection; + +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerTakeLecternBookEvent; +import world.bentobox.bentobox.api.flags.FlagListener; +import world.bentobox.bentobox.lists.Flags; + +/** + * Prevents players from taking books out of a lectern. + * @author Poslovitch + * @since 1.10.0 + */ +public class LecternListener extends FlagListener { + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerTakeBookFromLectern(PlayerTakeLecternBookEvent e) { + checkIsland(e, e.getPlayer(), e.getLectern().getLocation(), Flags.LECTERN); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlaceBooksOnLectern(BlockPlaceEvent e) { + if (e.getItemInHand().getType().equals(Material.WRITABLE_BOOK) + || e.getItemInHand().getType().equals(Material.WRITTEN_BOOK)) { + // Books can only be placed on lecterns and as such are protected by the LECTERN flag. + checkIsland(e, e.getPlayer(), e.getBlock().getLocation(), Flags.LECTERN); + } + } +} diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java index f5e4c2e3a..df6e7613a 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java @@ -26,7 +26,10 @@ public class PlaceBlocksListener extends FlagListener { */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockPlace(final BlockPlaceEvent e) { - if (e.getBlock().getType().equals(Material.FIRE)) { + if (e.getBlock().getType().equals(Material.FIRE) + || e.getItemInHand().getType().equals(Material.WRITABLE_BOOK) + || e.getItemInHand().getType().equals(Material.WRITTEN_BOOK)) { + // Books can only be placed on lecterns and as such are protected by the LECTERN flag. return; } checkIsland(e, e.getPlayer(), e.getBlock().getLocation(), Flags.PLACE_BLOCKS); diff --git a/src/main/java/world/bentobox/bentobox/lists/Flags.java b/src/main/java/world/bentobox/bentobox/lists/Flags.java index b970fec95..07dab573f 100644 --- a/src/main/java/world/bentobox/bentobox/lists/Flags.java +++ b/src/main/java/world/bentobox/bentobox/lists/Flags.java @@ -26,6 +26,7 @@ import world.bentobox.bentobox.listeners.flags.protection.HurtingListener; import world.bentobox.bentobox.listeners.flags.protection.InventoryListener; import world.bentobox.bentobox.listeners.flags.protection.ItemDropPickUpListener; import world.bentobox.bentobox.listeners.flags.protection.LeashListener; +import world.bentobox.bentobox.listeners.flags.protection.LecternListener; import world.bentobox.bentobox.listeners.flags.protection.LockAndBanListener; import world.bentobox.bentobox.listeners.flags.protection.PhysicalInteractionListener; import world.bentobox.bentobox.listeners.flags.protection.PlaceBlocksListener; @@ -117,6 +118,12 @@ public final class Flags { * @see BreakBlocksListener */ public static final Flag DRAGON_EGG = new Flag.Builder("DRAGON_EGG", Material.DRAGON_EGG).build(); + /** + * Prevents players from placing a book on a lectern or taking the book from it. + * @since 1.10.0 + * @see LecternListener + */ + public static final Flag LECTERN = new Flag.Builder("LECTERN", Material.LECTERN).listener(new LecternListener()).build(); // Entity interactions public static final Flag ARMOR_STAND = new Flag.Builder("ARMOR_STAND", Material.ARMOR_STAND).listener(new EntityInteractListener()).mode(Flag.Mode.ADVANCED).build(); diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index d0a4dff5e..c78edf760 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -929,6 +929,15 @@ protection: LEASH: description: "Toggle use" name: "Leash use" + LECTERN: + name: "Lecterns" + description: |- + &a Allow to place books on a lectern + &a or to take books from it. + + &c It does not prevent players from + &c reading the books. + hint: "cannot place a book on a lectern or take a book from it." LEVER: description: "Toggle use" name: "Lever use" diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java index 68f342c74..8f1e75373 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.when; import java.util.Arrays; @@ -218,6 +219,7 @@ public class PlaceBlocksListenerTest { BlockState replacedBlockState = mock(BlockState.class); Block placedAgainst = mock(Block.class); ItemStack itemInHand = mock(ItemStack.class); + when(itemInHand.getType()).thenReturn(Material.STONE); EquipmentSlot hand = EquipmentSlot.HAND; BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); pbl.onBlockPlace(e); @@ -236,6 +238,7 @@ public class PlaceBlocksListenerTest { BlockState replacedBlockState = mock(BlockState.class); Block placedAgainst = mock(Block.class); ItemStack itemInHand = mock(ItemStack.class); + when(itemInHand.getType()).thenReturn(Material.STONE); EquipmentSlot hand = EquipmentSlot.HAND; BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); pbl.onBlockPlace(e); @@ -243,6 +246,33 @@ public class PlaceBlocksListenerTest { Mockito.verify(notifier).notify(Mockito.any(), Mockito.eq("protection.protected")); } + /** + * Test method for {@link PlaceBlocksListener#onBlockPlace(org.bukkit.event.block.BlockPlaceEvent)}. + * Ensures that books are not protected by this listener. + */ + @Test + public void testOnBlockPlaceBook() { + when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); + Block placedBlock = mock(Block.class); + when(placedBlock.getType()).thenReturn(Material.LECTERN); + when(placedBlock.getLocation()).thenReturn(location); + BlockState replacedBlockState = mock(BlockState.class); + Block placedAgainst = mock(Block.class); + ItemStack itemInHand = mock(ItemStack.class); + when(itemInHand.getType()).thenReturn(Material.WRITTEN_BOOK); + EquipmentSlot hand = EquipmentSlot.HAND; + BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); + pbl.onBlockPlace(e); + assertFalse(e.isCancelled()); + Mockito.verify(notifier, never()).notify(Mockito.any(), Mockito.eq("protection.protected")); + + // With a WRITABLE BOOK now + when(itemInHand.getType()).thenReturn(Material.WRITABLE_BOOK); + pbl.onBlockPlace(e); + assertFalse(e.isCancelled()); + Mockito.verify(notifier, never()).notify(Mockito.any(), Mockito.eq("protection.protected")); + } + /** * Test method for {@link PlaceBlocksListener#onPlayerHitItemFrame(org.bukkit.event.player.PlayerInteractEntityEvent)}. */ @@ -319,15 +349,4 @@ public class PlaceBlocksListenerTest { } Mockito.verify(notifier, Mockito.times(7)).notify(Mockito.any(), Mockito.eq("protection.protected")); } - - /** - * Test method for {@link PlaceBlocksListener#onBlockForm(org.bukkit.event.block.EntityBlockFormEvent)}. - */ - @Test - @Ignore("Unfinished") - public void testOnBlockForm() { - // TODO - } - - }