mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-12-28 03:57:39 +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.OfflineRedstoneListener;
|
||||||
import world.bentobox.bentobox.listeners.flags.worldsettings.PistonPushListener;
|
import world.bentobox.bentobox.listeners.flags.worldsettings.PistonPushListener;
|
||||||
import world.bentobox.bentobox.listeners.flags.worldsettings.RemoveMobsListener;
|
import world.bentobox.bentobox.listeners.flags.worldsettings.RemoveMobsListener;
|
||||||
|
import world.bentobox.bentobox.listeners.flags.worldsettings.TreesGrowingOutsideRangeListener;
|
||||||
import world.bentobox.bentobox.managers.RanksManager;
|
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.
|
* Enables toggling for removal of the end exit island. May not be required on some servers, e.g. PaperSpigot.
|
||||||
* @since 1.3.0
|
* @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();
|
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.
|
* Provides a list of all the Flag instances contained in this class using reflection.
|
||||||
* @return List of all the flags in this class
|
* @return List of all the flags in this class
|
||||||
|
@ -790,6 +790,16 @@ protection:
|
|||||||
description: "Toggle access"
|
description: "Toggle access"
|
||||||
name: "Trap doors"
|
name: "Trap doors"
|
||||||
hint: "No trapdoor use"
|
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:
|
TURTLE_EGGS:
|
||||||
description: "Toggle crushing"
|
description: "Toggle crushing"
|
||||||
name: "Turtle Eggs"
|
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