Added Piston Push setting.

Allows/Disallows piston pushing outside an island.
This is a worldwide setting for admins.

https://github.com/tastybento/bskyblock/projects/3#card-10260101
This commit is contained in:
tastybento 2018-06-04 19:24:11 -07:00
parent 5904ef9194
commit aed648e6e7
5 changed files with 178 additions and 4 deletions

View File

@ -343,6 +343,11 @@ protection:
RIDING: "RIDING"
MUSIC: "MUSIC"
CHEST: "CHEST"
PISTON_PUSH:
name: "Piston Push"
description: |
&aAllow pistons to push
&ablocks outside island
PLACE_BLOCKS: "PLACE_BLOCKS"
PORTAL: "PORTAL"
PRESSURE_PLATE: "PRESSURE_PLATE"

View File

@ -0,0 +1,32 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPistonExtendEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Prevents pistons from pushing blocks outside island protection range
* @author tastybento
*
*/
public class PistonPushListener extends AbstractFlagListener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPistonExtend(BlockPistonExtendEvent e) {
// Only process if flag is active
if (Flags.PISTON_PUSH.isSet(e.getBlock().getWorld())) {
getIslands().getProtectedIslandAt(e.getBlock().getLocation()).ifPresent(i ->
e.setCancelled(
// Run through the location of all the relative blocks and see if they are outside the island
!e.getBlocks().stream()
.map(b -> b.getRelative(e.getDirection()).getLocation())
// All blocks must be on the island, otherwise the event is cancelled
.allMatch(i::onIsland)));
}
}
}

View File

@ -25,6 +25,7 @@ import us.tastybento.bskyblock.listeners.flags.LeashListener;
import us.tastybento.bskyblock.listeners.flags.LockAndBanListener;
import us.tastybento.bskyblock.listeners.flags.PVPListener;
import us.tastybento.bskyblock.listeners.flags.PhysicalInteractionListener;
import us.tastybento.bskyblock.listeners.flags.PistonPushListener;
import us.tastybento.bskyblock.listeners.flags.PlaceBlocksListener;
import us.tastybento.bskyblock.listeners.flags.PortalListener;
import us.tastybento.bskyblock.listeners.flags.SettingsToggleClickListener;
@ -134,13 +135,19 @@ public class Flags {
public static final Flag PVP_NETHER = new FlagBuilder().id("PVP_NETHER").icon(Material.IRON_AXE).type(Type.SETTING).build();
public static final Flag PVP_END = new FlagBuilder().id("PVP_END").icon(Material.END_CRYSTAL).type(Type.SETTING).build();
// Others
public static final Flag ANIMAL_SPAWN = new FlagBuilder().id("ANIMAL_SPAWN").icon(Material.APPLE).allowedByDefault(true).type(Type.SETTING).build();
public static final Flag MONSTER_SPAWN = new FlagBuilder().id("MONSTER_SPAWN").icon(Material.MOB_SPAWNER).allowedByDefault(true).type(Type.SETTING).build();
public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.FIREWORK_CHARGE).type(Type.SETTING).build();
// Global flags (apply to every island)
public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.SETTING)
.listener(new EnterExitListener())
.onClick(new SettingsToggleClickListener("ENTER_EXIT_MESSAGES"))
.build();
public static final Flag ANIMAL_SPAWN = new FlagBuilder().id("ANIMAL_SPAWN").icon(Material.APPLE).allowedByDefault(true).type(Type.SETTING).build();
public static final Flag MONSTER_SPAWN = new FlagBuilder().id("MONSTER_SPAWN").icon(Material.MOB_SPAWNER).allowedByDefault(true).type(Type.SETTING).build();
public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.FIREWORK_CHARGE).type(Type.SETTING).build();
public static final Flag PISTON_PUSH = new FlagBuilder().id("PISTON_PUSH").icon(Material.PISTON_BASE).allowedByDefault(true).type(Type.SETTING)
.listener(new PistonPushListener())
.onClick(new SettingsToggleClickListener("PISTON_PUSH"))
.build();
/**
* @return List of all the flags in this class

View File

@ -100,7 +100,7 @@ public class EnterExitListenerTest {
notifier = mock(Notifier.class);
when(plugin.getNotifier()).thenReturn(notifier);
// Island Banned list initialization
// Island initialization
island = mock(Island.class);
Location loc = mock(Location.class);
when(loc.getWorld()).thenReturn(world);

View File

@ -0,0 +1,130 @@
package us.tastybento.bskyblock.listeners.flags;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.IslandsManager;
import us.tastybento.bskyblock.util.Util;
@RunWith(PowerMockRunner.class)
@PrepareForTest({BSkyBlock.class, Util.class })
public class PistonPushListenerTest {
private Island island;
private IslandsManager im;
private World world;
private Location inside;
private UUID uuid;
private Block block;
private List<Block> blocks;
private Block blockPushed;
@Before
public void setUp() throws Exception {
// Set up plugin
BSkyBlock plugin = mock(BSkyBlock.class);
Whitebox.setInternalState(BSkyBlock.class, "instance", plugin);
// World
world = mock(World.class);
// Owner
uuid = UUID.randomUUID();
// Island initialization
island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid);
im = mock(IslandsManager.class);
when(plugin.getIslands()).thenReturn(im);
when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island);
inside = mock(Location.class);
Optional<Island> opIsland = Optional.ofNullable(island);
when(im.getProtectedIslandAt(Mockito.eq(inside))).thenReturn(opIsland);
// Blocks
block = mock(Block.class);
when(block.getWorld()).thenReturn(world);
when(block.getLocation()).thenReturn(inside);
blockPushed = mock(Block.class);
when(block.getRelative(Mockito.any(BlockFace.class))).thenReturn(blockPushed);
// The blocks in the pushed list are all inside the island
when(blockPushed.getLocation()).thenReturn(inside);
// Make a list of ten blocks
blocks = new ArrayList<>();
for (int i = 0; i < 10; i++) {
blocks.add(block);
}
PowerMockito.mockStatic(Util.class);
when(Util.getWorld(Mockito.any())).thenReturn(world);
Flags.PISTON_PUSH.setSetting(world, true);
}
@Test
public void testOnPistonExtendFlagNotSet() {
Flags.PISTON_PUSH.setSetting(world, false);
BlockPistonExtendEvent e = new BlockPistonExtendEvent(block, blocks, BlockFace.EAST);
new PistonPushListener().onPistonExtend(e);
// Should fail because flag is not set
assertFalse(e.isCancelled());
}
@Test
public void testOnPistonExtendFlagSetOnIsland() {
// The blocks in the pushed list are all inside the island
when(island.onIsland(Mockito.any())).thenReturn(true);
BlockPistonExtendEvent e = new BlockPistonExtendEvent(block, blocks, BlockFace.EAST);
new PistonPushListener().onPistonExtend(e);
// Should fail because on island
assertFalse(e.isCancelled());
}
@Test
public void testOnPistonExtendFlagSetOffIsland() {
// The blocks in the pushed list are all outside the island
when(island.onIsland(Mockito.any())).thenReturn(false);
BlockPistonExtendEvent e = new BlockPistonExtendEvent(block, blocks, BlockFace.EAST);
new PistonPushListener().onPistonExtend(e);
// Should fail because on island
assertTrue(e.isCancelled());
}
}