From 36ae34da5d08c7e4f6262c1c80e892ec47bf2c50 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 30 Dec 2022 09:37:18 -0800 Subject: [PATCH] 2049 trees growing outside range (#2050) * Fixes #2046. Handles null players for placeholders. * Remove unused import * Fixes #2049 for adjacent island spaces This also deletes blocks in the event rather than setting them to AIR as was done previously. --- .../TreesGrowingOutsideRangeListener.java | 22 +++++++----- .../TreesGrowingOutsideRangeListenerTest.java | 36 +++++++++++++++---- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListener.java index 9f77ec728..04ba4b8f6 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListener.java @@ -1,5 +1,7 @@ package world.bentobox.bentobox.listeners.flags.worldsettings; +import java.util.Optional; + import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -7,6 +9,7 @@ import org.bukkit.event.block.BlockSpreadEvent; import org.bukkit.event.world.StructureGrowEvent; import world.bentobox.bentobox.api.flags.FlagListener; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; /** @@ -24,15 +27,16 @@ public class TreesGrowingOutsideRangeListener extends FlagListener { } // If there is no protected island at the location of the sapling, just cancel the event (prevents the sapling from growing). - if (getIslands().getProtectedIslandAt(e.getLocation()).isEmpty()) { + Optional optionalProtectedIsland = getIslands().getProtectedIslandAt(e.getLocation()); + if (optionalProtectedIsland.isEmpty()) { e.setCancelled(true); return; } - - // Now, run through all the blocks that will be generated and if there is no protected island at their location, turn them into AIR. - e.getBlocks().stream() - .filter(blockState -> getIslands().getProtectedIslandAt(blockState.getLocation()).isEmpty()) - .forEach(blockState -> blockState.setType(Material.AIR)); + // Now, run through all the blocks that will be generated and if there is no protected island at their location, or the protected island is not the same as the one growing the tree then turn them into AIR. + e.getBlocks().removeIf(blockState -> { + Optional island = getIslands().getProtectedIslandAt(blockState.getLocation()); + return island.isEmpty() || !island.equals(optionalProtectedIsland); + }); } @EventHandler(priority = EventPriority.HIGH) @@ -45,13 +49,15 @@ public class TreesGrowingOutsideRangeListener extends FlagListener { } // If there is no protected island at the location of the chorus flower, just cancel the event (prevents the flower from growing). - if (getIslands().getProtectedIslandAt(e.getSource().getLocation()).isEmpty()) { + Optional optionalProtectedIsland = getIslands().getProtectedIslandAt(e.getSource().getLocation()); + if (optionalProtectedIsland.isEmpty()) { e.setCancelled(true); return; } // Now prevent the flower to grow if this is growing outside the island - if (getIslands().getProtectedIslandAt(e.getBlock().getLocation()).isEmpty()) { + Optional island = getIslands().getProtectedIslandAt(e.getBlock().getLocation()); + if (island.isEmpty() || !island.equals(optionalProtectedIsland)) { e.setCancelled(true); } } diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListenerTest.java index 0ca893840..655ef53f3 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/TreesGrowingOutsideRangeListenerTest.java @@ -5,7 +5,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; @@ -70,6 +69,8 @@ public class TreesGrowingOutsideRangeListenerTest { @Mock private Island island; + @Mock + private Island anotherIsland; @Mock private BlockState firstBlock; @@ -127,13 +128,16 @@ public class TreesGrowingOutsideRangeListenerTest { * Populates {@link TreesGrowingOutsideRangeListenerTest#blockStates} with a tree schema. */ private void populateBlockStatesList() { - //when(firstBlock.getLocation()).thenReturn(new Location(world, 2, 0, 2)); + Location a = new Location(world, 2, 0, 2); + + when(firstBlock.getLocation()).thenReturn(a); blockStates.add(firstBlock); // Tree logs for (int i = 0; i < 3; i++) { BlockState logState = mock(BlockState.class); when(logState.getType()).thenReturn(Material.OAK_LOG); - when(logState.getLocation()).thenReturn(new Location(world, 2, i, 2)); + Location trunk = new Location(world, 2, i, 2); + when(logState.getLocation()).thenReturn(trunk); blockStates.add(logState); } @@ -144,13 +148,14 @@ public class TreesGrowingOutsideRangeListenerTest { if (x != 2 && y >= 3 && z != 2) { BlockState leafState = mock(BlockState.class); when(leafState.getType()).thenReturn(Material.OAK_LEAVES); - when(leafState.getLocation()).thenReturn(new Location(world, x, y, z)); + Location l = new Location(world, x, y, z); + when(leafState.getLocation()).thenReturn(l); blockStates.add(leafState); } } } } - //when(lastBlock.getLocation()).thenReturn(new Location(world, 2, 0, 2)); + when(lastBlock.getLocation()).thenReturn(new Location(world, 2, 0, 2)); blockStates.add(lastBlock); } @@ -197,6 +202,23 @@ public class TreesGrowingOutsideRangeListenerTest { assertTrue(event.isCancelled()); } + /** + * Asserts that the event is cancelled and that there is no interaction with the blocks list when the sapling is outside an island but inside another island. + */ + @Test + public void testSaplingOutsideIslandButInAnotherIsland() { + // Sapling is on the island, but some leaves are in another island. For simplicity + for (BlockState b: blockStates) { + if (b.getLocation().getBlockY() == 4) { + when(islandsManager.getProtectedIslandAt(b.getLocation())).thenReturn(Optional.of(anotherIsland)); + } + } + // Run + new TreesGrowingOutsideRangeListener().onTreeGrow(event); + // Some blocks should have become air only 21 are left + assertEquals(21, event.getBlocks().size()); + } + /** * Asserts that no interaction is done to the event when everything's inside an island. */ @@ -219,7 +241,7 @@ public class TreesGrowingOutsideRangeListenerTest { // Run new TreesGrowingOutsideRangeListener().onTreeGrow(event); assertFalse(event.isCancelled()); - verify(firstBlock, Mockito.never()).setType(Material.AIR); - verify(lastBlock).setType(Material.AIR); + // Some blocks should have become air only 21 are left + assertEquals(2, event.getBlocks().size()); } }