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.
This commit is contained in:
tastybento 2022-12-30 09:37:18 -08:00 committed by GitHub
parent 18983e5570
commit 36ae34da5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 15 deletions

View File

@ -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<Island> 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> 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<Island> 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> island = getIslands().getProtectedIslandAt(e.getBlock().getLocation());
if (island.isEmpty() || !island.equals(optionalProtectedIsland)) {
e.setCancelled(true);
}
}

View File

@ -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());
}
}