mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-12-27 11:37:36 +01:00
parent
69ca910df4
commit
b8afd1919f
@ -0,0 +1,33 @@
|
||||
package world.bentobox.bentobox.listeners.flags.worldsettings;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import world.bentobox.bentobox.api.flags.FlagListener;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
|
||||
/**
|
||||
* Handles {@link world.bentobox.bentobox.lists.Flags#TREES_GROWING_OUTSIDE_RANGE}.
|
||||
* @author Poslovitch
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class TreesGrowingOutsideRangeListener extends FlagListener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onTreeGrow(StructureGrowEvent e) {
|
||||
if (!getIWM().inWorld(e.getWorld()) || Flags.TREES_GROWING_OUTSIDE_RANGE.isSetForWorld(e.getWorld())) {
|
||||
// We do not want to run any check if this is not the right world or if it is allowed.
|
||||
return;
|
||||
}
|
||||
|
||||
// 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()).isPresent()) {
|
||||
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()).isPresent()).forEach(blockState -> blockState.setType(Material.AIR));
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@ import world.bentobox.bentobox.listeners.flags.worldsettings.ObsidianScoopingLis
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.OfflineRedstoneListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.PistonPushListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.RemoveMobsListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.TreesGrowingOutsideRangeListener;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
|
||||
/**
|
||||
@ -291,9 +292,20 @@ public final class Flags {
|
||||
/**
|
||||
* Enables toggling for removal of the end exit island. May not be required on some servers, e.g. PaperSpigot.
|
||||
* @since 1.3.0
|
||||
* @see world.bentobox.bentobox.listeners.BlockEndDragon
|
||||
*/
|
||||
public static final Flag REMOVE_END_EXIT_ISLAND = new Flag.Builder("REMOVE_END_EXIT_ISLAND", Material.DRAGON_HEAD).type(Type.WORLD_SETTING).defaultSetting(true).build();
|
||||
|
||||
/**
|
||||
* Toggles whether trees can grow outside an island's protection range or not.
|
||||
* Not only will it prevent saplings placed outside an island's protection range from growing, but it will also block generation of leaves/logs outside of it, thus "cutting" the tree.
|
||||
* It is disabled by default in order to avoid leaves/logs being generated outside an island's protection range and remaining unbreakable by players.
|
||||
*
|
||||
* @since 1.3.0
|
||||
* @see TreesGrowingOutsideRangeListener
|
||||
*/
|
||||
public static final Flag TREES_GROWING_OUTSIDE_RANGE = new Flag.Builder("TREES_GROWING_OUTSIDE_RANGE", Material.OAK_SAPLING).type(Type.WORLD_SETTING).listener(new TreesGrowingOutsideRangeListener()).build();
|
||||
|
||||
/**
|
||||
* Provides a list of all the Flag instances contained in this class using reflection.
|
||||
* @return List of all the flags in this class
|
||||
|
@ -790,6 +790,16 @@ protection:
|
||||
description: "Toggle access"
|
||||
name: "Trap doors"
|
||||
hint: "No trapdoor use"
|
||||
TREES_GROWING_OUTSIDE_RANGE:
|
||||
name: "Trees growing outside range"
|
||||
description: |-
|
||||
&aToggle whether trees can grow outside an
|
||||
&aisland's protection range or not.
|
||||
&aNot only will it prevent saplings placed
|
||||
&aoutside an island's protection range from
|
||||
&agrowing, but it will also block generation
|
||||
&aof leaves/logs outside of the island, thus
|
||||
&acutting the tree.
|
||||
TURTLE_EGGS:
|
||||
description: "Toggle crushing"
|
||||
name: "Turtle Eggs"
|
||||
|
@ -0,0 +1,199 @@
|
||||
package world.bentobox.bentobox.listeners.flags.worldsettings;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests {@link TreesGrowingOutsideRangeListener}.
|
||||
* @author Poslovitch
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({BentoBox.class})
|
||||
public class TreesGrowingOutsideRangeListenerTest {
|
||||
|
||||
/* IslandWorldManager */
|
||||
private IslandWorldManager iwm;
|
||||
|
||||
/* Event */
|
||||
private StructureGrowEvent event;
|
||||
|
||||
/* Block */
|
||||
private Block sapling;
|
||||
private List<BlockState> blockStates;
|
||||
|
||||
/* World */
|
||||
private World world;
|
||||
|
||||
/* Islands */
|
||||
private IslandsManager islandsManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// Set up plugin
|
||||
BentoBox plugin = mock(BentoBox.class);
|
||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||
|
||||
/* Blocks */
|
||||
sapling = mock(Block.class);
|
||||
when(sapling.getType()).thenReturn(Material.OAK_SAPLING);
|
||||
when(sapling.getLocation()).thenReturn(new Location(world, 2, 0, 2));
|
||||
|
||||
blockStates = new ArrayList<>();
|
||||
populateBlockStatesList();
|
||||
|
||||
/* Event */
|
||||
event = new StructureGrowEvent(sapling.getLocation(), TreeType.TREE, false, null, blockStates);
|
||||
|
||||
/* World */
|
||||
world = mock(World.class);
|
||||
|
||||
/* Island World Manager */
|
||||
iwm = mock(IslandWorldManager.class);
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
|
||||
// WorldSettings and World Flags
|
||||
WorldSettings ws = mock(WorldSettings.class);
|
||||
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws);
|
||||
Map<String, Boolean> worldFlags = new HashMap<>();
|
||||
when(ws.getWorldFlags()).thenReturn(worldFlags);
|
||||
|
||||
// By default everything is in world
|
||||
when(iwm.inWorld(any(World.class))).thenReturn(true);
|
||||
when(iwm.inWorld(any(Location.class))).thenReturn(true);
|
||||
|
||||
/* Flags */
|
||||
// By default, it is not allowed
|
||||
Flags.TREES_GROWING_OUTSIDE_RANGE.setSetting(world, false);
|
||||
|
||||
/* Islands */
|
||||
islandsManager = mock(IslandsManager.class);
|
||||
when(plugin.getIslands()).thenReturn(islandsManager);
|
||||
// By default, there should be an island.
|
||||
Island island = mock(Island.class);
|
||||
when(islandsManager.getProtectedIslandAt(Mockito.any())).thenReturn(Optional.of(island));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@link TreesGrowingOutsideRangeListenerTest#blockStates} with a tree schema.
|
||||
*/
|
||||
private void populateBlockStatesList() {
|
||||
// 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));
|
||||
blockStates.add(logState);
|
||||
}
|
||||
|
||||
// Basic leaves pattern
|
||||
for (int x = 0; x < 5 ; x++) {
|
||||
for (int y = 0; y < 5; y++) {
|
||||
for (int z = 0; z < 5; z++) {
|
||||
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));
|
||||
blockStates.add(leafState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that no interaction is done to the event when it does not happen in the world.
|
||||
*/
|
||||
@Test
|
||||
public void testNotInWorld() {
|
||||
// Not in world
|
||||
when(iwm.inWorld(any(World.class))).thenReturn(false);
|
||||
when(iwm.inWorld(any(Location.class))).thenReturn(false);
|
||||
|
||||
// Run
|
||||
new TreesGrowingOutsideRangeListener().onTreeGrow(event);
|
||||
assertEquals(blockStates, event.getBlocks());
|
||||
assertFalse(event.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that no interaction is done to the event when {@link Flags#TREES_GROWING_OUTSIDE_RANGE} is allowed.
|
||||
*/
|
||||
@Test
|
||||
public void testFlagIsAllowed() {
|
||||
// Allowed
|
||||
Flags.TREES_GROWING_OUTSIDE_RANGE.setSetting(world, true);
|
||||
|
||||
// Run
|
||||
new TreesGrowingOutsideRangeListener().onTreeGrow(event);
|
||||
assertEquals(blockStates, event.getBlocks());
|
||||
assertFalse(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.
|
||||
*/
|
||||
@Test
|
||||
public void testSaplingOutsideIsland() {
|
||||
// No protected island at the sapling's location
|
||||
when(islandsManager.getProtectedIslandAt(sapling.getLocation())).thenReturn(Optional.empty());
|
||||
|
||||
// Run
|
||||
new TreesGrowingOutsideRangeListener().onTreeGrow(event);
|
||||
assertEquals(blockStates, event.getBlocks());
|
||||
assertTrue(event.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that no interaction is done to the event when everything's inside an island.
|
||||
*/
|
||||
@Test
|
||||
public void testTreeFullyInsideIsland() {
|
||||
// Run
|
||||
new TreesGrowingOutsideRangeListener().onTreeGrow(event);
|
||||
assertEquals(blockStates, event.getBlocks());
|
||||
assertFalse(event.isCancelled());
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testTreePartiallyOutsideIsland() {
|
||||
//FIXME
|
||||
|
||||
// Run
|
||||
new TreesGrowingOutsideRangeListener().onTreeGrow(event);
|
||||
assertFalse(event.isCancelled());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user