mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-11-30 14:43:49 +01:00
Added Flags#LIQUIDS_FLOWING_OUT
Also fixed some Javadoc in Flags, and I've also done my very first test unit! #511
This commit is contained in:
parent
30fb7820fc
commit
1c06584131
@ -0,0 +1,44 @@
|
|||||||
|
package world.bentobox.bentobox.listeners.flags.worldsettings;
|
||||||
|
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.block.BlockFromToEvent;
|
||||||
|
import world.bentobox.bentobox.api.flags.FlagListener;
|
||||||
|
import world.bentobox.bentobox.lists.Flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles {@link world.bentobox.bentobox.lists.Flags#LIQUIDS_FLOWING_OUT}.
|
||||||
|
* @author Poslovitch
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
public class LiquidsFlowingOutListener extends FlagListener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.NORMAL)
|
||||||
|
public void onLiquidFlow(BlockFromToEvent e) {
|
||||||
|
Block from = e.getBlock();
|
||||||
|
if (!from.isLiquid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block to = e.getToBlock();
|
||||||
|
if (!getIWM().inWorld(from.getLocation()) || Flags.LIQUIDS_FLOWING_OUT.isSetForWorld(from.getWorld())) {
|
||||||
|
// We do not want to run any check if this is not the right world or if it is allowed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make a less restrictive check - try to see where the border is, so that
|
||||||
|
// water can still flows sideways.
|
||||||
|
// see: https://github.com/BentoBoxWorld/BentoBox/issues/511#issuecomment-460040287
|
||||||
|
// Time to do some maths! We've got the vector FromTo, let's check if its y coordinate is different from zero.
|
||||||
|
if (to.getLocation().toVector().subtract(from.getLocation().toVector()).getY() != 0) {
|
||||||
|
// We do not run any checks if this is a vertical flow - would be too much resource consuming.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only prevent if it is flowing into the area between islands.
|
||||||
|
if (!getIslands().getProtectedIslandAt(to.getLocation()).isPresent()) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import org.bukkit.Material;
|
|||||||
import world.bentobox.bentobox.api.flags.Flag;
|
import world.bentobox.bentobox.api.flags.Flag;
|
||||||
import world.bentobox.bentobox.api.flags.Flag.Type;
|
import world.bentobox.bentobox.api.flags.Flag.Type;
|
||||||
import world.bentobox.bentobox.api.flags.clicklisteners.CycleClick;
|
import world.bentobox.bentobox.api.flags.clicklisteners.CycleClick;
|
||||||
|
import world.bentobox.bentobox.listeners.flags.worldsettings.LiquidsFlowingOutListener;
|
||||||
import world.bentobox.bentobox.listeners.flags.worldsettings.ObsidianScoopingListener;
|
import world.bentobox.bentobox.listeners.flags.worldsettings.ObsidianScoopingListener;
|
||||||
import world.bentobox.bentobox.listeners.flags.protection.BlockInteractionListener;
|
import world.bentobox.bentobox.listeners.flags.protection.BlockInteractionListener;
|
||||||
import world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener;
|
import world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener;
|
||||||
@ -73,7 +74,7 @@ public final class Flags {
|
|||||||
public static final Flag PLACE_BLOCKS = new Flag.Builder("PLACE_BLOCKS", Material.GRASS).listener(new PlaceBlocksListener()).build();
|
public static final Flag PLACE_BLOCKS = new Flag.Builder("PLACE_BLOCKS", Material.GRASS).listener(new PlaceBlocksListener()).build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents players from generated Frosted Ice on one's island using boots enchanted with "Frost Walker".
|
* Prevents players from generating Frosted Ice on one's island using "Frost Walker" enchanted boots.
|
||||||
* @see PlaceBlocksListener
|
* @see PlaceBlocksListener
|
||||||
*/
|
*/
|
||||||
public static final Flag FROST_WALKER = new Flag.Builder("FROST_WALKER", Material.ICE).build();
|
public static final Flag FROST_WALKER = new Flag.Builder("FROST_WALKER", Material.ICE).build();
|
||||||
@ -129,7 +130,7 @@ public final class Flags {
|
|||||||
// Throwing things
|
// Throwing things
|
||||||
public static final Flag EGGS = new Flag.Builder("EGGS", Material.EGG).listener(new EggListener()).build();
|
public static final Flag EGGS = new Flag.Builder("EGGS", Material.EGG).listener(new EggListener()).build();
|
||||||
/**
|
/**
|
||||||
* Prevents players from throwing potions / exp bottles.
|
* Prevents players from throwing potions / experience bottles.
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
public static final Flag POTION_THROWING = new Flag.Builder("POTION_THROWING", Material.SPLASH_POTION).listener(new ThrowingListener()).build();
|
public static final Flag POTION_THROWING = new Flag.Builder("POTION_THROWING", Material.SPLASH_POTION).listener(new ThrowingListener()).build();
|
||||||
@ -271,6 +272,14 @@ public final class Flags {
|
|||||||
public static final Flag OBSIDIAN_SCOOPING = new Flag.Builder("OBSIDIAN_SCOOPING", Material.OBSIDIAN).type(Type.WORLD_SETTING)
|
public static final Flag OBSIDIAN_SCOOPING = new Flag.Builder("OBSIDIAN_SCOOPING", Material.OBSIDIAN).type(Type.WORLD_SETTING)
|
||||||
.listener(new ObsidianScoopingListener()).defaultSetting(true).build();
|
.listener(new ObsidianScoopingListener()).defaultSetting(true).build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevents liquids from flowing outside the protection range, in order to avoid cobblestone/stone/obsidian being generated and remaining unbreakable by players.
|
||||||
|
* @since 1.3.0
|
||||||
|
* @see LiquidsFlowingOutListener
|
||||||
|
*/
|
||||||
|
public static final Flag LIQUIDS_FLOWING_OUT = new Flag.Builder("LIQUIDS_FLOWING_OUT", Material.WATER_BUCKET).type(Type.WORLD_SETTING)
|
||||||
|
.listener(new LiquidsFlowingOutListener()).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
|
||||||
|
@ -651,6 +651,14 @@ protection:
|
|||||||
description: "Toggle use"
|
description: "Toggle use"
|
||||||
name: "Lever use"
|
name: "Lever use"
|
||||||
hint: "No lever use"
|
hint: "No lever use"
|
||||||
|
LIQUIDS_FLOWING_OUT:
|
||||||
|
name: "Liquids flowing outside islands"
|
||||||
|
description: |-
|
||||||
|
&aToggle whether liquids can flow outside
|
||||||
|
&aof the island's protection range.
|
||||||
|
&aDisabling it helps avoiding lava and water
|
||||||
|
&agenerating cobblestone in the area between
|
||||||
|
&atwo islands.
|
||||||
LOCK:
|
LOCK:
|
||||||
description: "Toggle lock"
|
description: "Toggle lock"
|
||||||
name: "Lock island"
|
name: "Lock island"
|
||||||
|
@ -0,0 +1,184 @@
|
|||||||
|
package world.bentobox.bentobox.listeners.flags;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.block.BlockFromToEvent;
|
||||||
|
import org.junit.Before;
|
||||||
|
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.listeners.flags.worldsettings.LiquidsFlowingOutListener;
|
||||||
|
import world.bentobox.bentobox.lists.Flags;
|
||||||
|
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||||
|
import world.bentobox.bentobox.managers.IslandsManager;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
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 world.bentobox.bentobox.listeners.flags.worldsettings.LiquidsFlowingOutListener}.
|
||||||
|
* @author Poslovitch
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@RunWith(PowerMockRunner.class)
|
||||||
|
@PrepareForTest({BentoBox.class})
|
||||||
|
public class LiquidsFlowingOutListenerTest {
|
||||||
|
|
||||||
|
/* IslandWorldManager */
|
||||||
|
private IslandWorldManager iwm;
|
||||||
|
|
||||||
|
/* Blocks */
|
||||||
|
private Block from;
|
||||||
|
private Block to;
|
||||||
|
|
||||||
|
/* Event */
|
||||||
|
private BlockFromToEvent event;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
from = mock(Block.class);
|
||||||
|
when(from.isLiquid()).thenReturn(true);
|
||||||
|
to = mock(Block.class);
|
||||||
|
|
||||||
|
/* World */
|
||||||
|
world = mock(World.class);
|
||||||
|
when(from.getWorld()).thenReturn(world);
|
||||||
|
|
||||||
|
// Give them locations
|
||||||
|
Location fromLocation = new Location(world, 0, 0, 0);
|
||||||
|
when(from.getLocation()).thenReturn(fromLocation);
|
||||||
|
|
||||||
|
Location toLocation = new Location(world, 1, 0, 0);
|
||||||
|
when(to.getLocation()).thenReturn(toLocation);
|
||||||
|
|
||||||
|
/* Event */
|
||||||
|
event = new BlockFromToEvent(from, to);
|
||||||
|
|
||||||
|
/* 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.LIQUIDS_FLOWING_OUT.setSetting(world, false);
|
||||||
|
|
||||||
|
/* Islands */
|
||||||
|
islandsManager = mock(IslandsManager.class);
|
||||||
|
when(plugin.getIslands()).thenReturn(islandsManager);
|
||||||
|
// By default, there should be no island's protection range at toLocation.
|
||||||
|
when(islandsManager.getProtectedIslandAt(toLocation)).thenReturn(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is never cancelled when the 'from' block is not liquid.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFromIsNotLiquid() {
|
||||||
|
// The 'from' block is not liquid
|
||||||
|
when(from.isLiquid()).thenReturn(false);
|
||||||
|
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertFalse(event.isCancelled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is never cancelled when the 'from' block is not in the world.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFromIsNotInWorld() {
|
||||||
|
// Not in world
|
||||||
|
when(iwm.inWorld(any(World.class))).thenReturn(false);
|
||||||
|
when(iwm.inWorld(any(Location.class))).thenReturn(false);
|
||||||
|
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertFalse(event.isCancelled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is never cancelled when {@link Flags#LIQUIDS_FLOWING_OUT} is allowed.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFlagIsAllowed() {
|
||||||
|
// Allowed
|
||||||
|
Flags.LIQUIDS_FLOWING_OUT.setSetting(world, true);
|
||||||
|
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertFalse(event.isCancelled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is never cancelled when the liquid flows vertically.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLiquidFlowsVertically() {
|
||||||
|
// "To" is at (1,0,0)
|
||||||
|
// Set "from" at (1,1,0) so that the vector's y coordinate != 0, which means the liquid flows vertically.
|
||||||
|
when(from.getLocation()).thenReturn(new Location(world, 1, 1, 0));
|
||||||
|
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertFalse(event.isCancelled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is never cancelled when the liquid flows to a location in an island's protection range.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLiquidFlowsToLocationInIslandProtectionRange() {
|
||||||
|
// There's a protected island at the "to"
|
||||||
|
Island island = mock(Island.class);
|
||||||
|
when(islandsManager.getProtectedIslandAt(to.getLocation())).thenReturn(Optional.of(island));
|
||||||
|
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertFalse(event.isCancelled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the event is cancelled with the default configuration provided in {@link LiquidsFlowingOutListenerTest#setUp()}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLiquidFlowIsBlocked() {
|
||||||
|
// Run
|
||||||
|
new LiquidsFlowingOutListener().onLiquidFlow(event);
|
||||||
|
assertTrue(event.isCancelled());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user