diff --git a/README.md b/README.md index f4ee1cf17..56f7e8300 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ BentoBox BentoBox is an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland. Admins can assemble the game or games how they like with a variety of add-ons. These include: -BSkyBlock - the successor to the popular ASkyBlock. Don't fall! -AcidIsland - you are marooned in a sea of acid! -Level - an add-on to calculate your island level and show a top ten -Challenges - an add-on that gives you challenges to accomplish -Welcome WarpSigns - an add-on that enables players to plant a warp sign +* BSkyBlock - the successor to the popular ASkyBlock. Don't fall! +* AcidIsland - you are marooned in a sea of acid! +* Level - an add-on to calculate your island level and show a top ten +* Challenges - an add-on that gives you challenges to accomplish +* Welcome WarpSigns - an add-on that enables players to plant a warp sign Bentobox represents a turning point on ASkyBlock's history : Tastybento and Poslovitch thought up and designed this complete rewrite in order to provide a whole new way to play Skyblock and other island-style games. diff --git a/pom.xml b/pom.xml index c71283a8c..99fb047bc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ world.bentobox bentobox - FC-1 + 0.9.0-SNAPSHOT BentoBox BentoBox is an expandable Minecraft Spigot plugin for island-type games like ASkyBlock or AcidIsland. diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index 4c452a00a..693350100 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -12,6 +12,7 @@ import world.bentobox.bentobox.api.user.Notifier; import world.bentobox.bentobox.commands.BentoBoxCommand; import world.bentobox.bentobox.listeners.BannedVisitorCommands; import world.bentobox.bentobox.listeners.BlockEndDragon; +import world.bentobox.bentobox.listeners.DeathListener; import world.bentobox.bentobox.listeners.JoinLeaveListener; import world.bentobox.bentobox.listeners.NetherPortals; import world.bentobox.bentobox.listeners.ObsidianToLava; @@ -156,6 +157,8 @@ public class BentoBox extends JavaPlugin { manager.registerEvents(new BlockEndDragon(this), this); // Banned visitor commands manager.registerEvents(new BannedVisitorCommands(this), this); + // Death counter + manager.registerEvents(new DeathListener(this), this); } @Override diff --git a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java index c7e2b7bb4..b1f1269aa 100644 --- a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java +++ b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java @@ -38,7 +38,8 @@ public class CycleClick implements PanelItem.ClickHandler { return true; } String reqPerm = plugin.getIWM().getPermissionPrefix(Util.getWorld(user.getWorld())) + ".settings." + id; - if (!user.hasPermission(reqPerm)) { + String allPerms = plugin.getIWM().getPermissionPrefix(Util.getWorld(user.getWorld())) + ".settings.*"; + if (!user.hasPermission(reqPerm) && !user.hasPermission(allPerms)) { user.sendMessage("general.errors.no-permission", TextVariables.PERMISSION, reqPerm); user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); return true; diff --git a/src/main/java/world/bentobox/bentobox/listeners/DeathListener.java b/src/main/java/world/bentobox/bentobox/listeners/DeathListener.java new file mode 100644 index 000000000..943c6a75f --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/listeners/DeathListener.java @@ -0,0 +1,33 @@ +/** + * + */ +package world.bentobox.bentobox.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; + +import world.bentobox.bentobox.BentoBox; + +/** + * Counts deaths in game worlds + * @author tastybento + * + */ +public class DeathListener implements Listener { + + private BentoBox plugin; + + public DeathListener(BentoBox plugin) { + super(); + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerDeathEvent(PlayerDeathEvent e) { + if (plugin.getIWM().inWorld(e.getEntity().getLocation())) { + plugin.getPlayers().addDeath(e.getEntity().getWorld(), e.getEntity().getUniqueId()); + } + } +} diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/BlockInteractionListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/BlockInteractionListener.java index 866751139..cdd2a8319 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/BlockInteractionListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/BlockInteractionListener.java @@ -1,8 +1,12 @@ package world.bentobox.bentobox.listeners.flags; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.PlayerInteractEvent; import world.bentobox.bentobox.api.flags.AbstractFlagListener; @@ -23,136 +27,8 @@ public class BlockInteractionListener extends AbstractFlagListener { if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { return; } - switch (e.getClickedBlock().getType()) { - case ANVIL: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.ANVIL); - break; - case BEACON: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.BEACON); - break; - case BLACK_BED: - case BLUE_BED: - case BROWN_BED: - case CYAN_BED: - case GRAY_BED: - case GREEN_BED: - case LIGHT_BLUE_BED: - case LIGHT_GRAY_BED: - case LIME_BED: - case MAGENTA_BED: - case ORANGE_BED: - case PINK_BED: - case PURPLE_BED: - case RED_BED: - case WHITE_BED: - case YELLOW_BED: + checkClickedBlock(e, e.getClickedBlock().getLocation(), e.getClickedBlock().getType()); - checkIsland(e, e.getClickedBlock().getLocation(), Flags.BED); - break; - case BREWING_STAND: - case CAULDRON: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.BREWING); - break; - case CHEST: - case CHEST_MINECART: - case TRAPPED_CHEST: - case BLACK_SHULKER_BOX: - case BLUE_SHULKER_BOX: - case BROWN_SHULKER_BOX: - case CYAN_SHULKER_BOX: - case GRAY_SHULKER_BOX: - case GREEN_SHULKER_BOX: - case LIGHT_BLUE_SHULKER_BOX: - case LIME_SHULKER_BOX: - case PINK_SHULKER_BOX: - case MAGENTA_SHULKER_BOX: - case ORANGE_SHULKER_BOX: - case PURPLE_SHULKER_BOX: - case RED_SHULKER_BOX: - case LIGHT_GRAY_SHULKER_BOX: - case WHITE_SHULKER_BOX: - case YELLOW_SHULKER_BOX: - case DISPENSER: - case DROPPER: - case HOPPER: - case HOPPER_MINECART: - - checkIsland(e, e.getClickedBlock().getLocation(), Flags.CHEST); - break; - - case ACACIA_DOOR: - case BIRCH_DOOR: - case DARK_OAK_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case SPRUCE_DOOR: - case OAK_DOOR: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.DOOR); - break; - case ACACIA_TRAPDOOR: - case BIRCH_TRAPDOOR: - case DARK_OAK_TRAPDOOR: - case OAK_TRAPDOOR: - case JUNGLE_TRAPDOOR: - case SPRUCE_TRAPDOOR: - case IRON_TRAPDOOR: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.TRAPDOOR); - break; - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case SPRUCE_FENCE_GATE: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.GATE); - break; - - case FURNACE: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.FURNACE); - break; - case ENCHANTING_TABLE: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.ENCHANTING); - break; - case ENDER_CHEST: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.ENDER_CHEST); - break; - case JUKEBOX: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.JUKEBOX); - break; - case NOTE_BLOCK: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.NOTE_BLOCK); - break; - case CRAFTING_TABLE: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.CRAFTING); - break; - case STONE_BUTTON: - case ACACIA_BUTTON: - case BIRCH_BUTTON: - case DARK_OAK_BUTTON: - case JUNGLE_BUTTON: - case OAK_BUTTON: - case SPRUCE_BUTTON: - - checkIsland(e, e.getClickedBlock().getLocation(), Flags.BUTTON); - break; - case LEVER: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.LEVER); - break; - case REPEATER: - case COMPARATOR: - case DAYLIGHT_DETECTOR: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.REDSTONE); - break; - case DRAGON_EGG: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.BREAK_BLOCKS); - break; - case END_PORTAL_FRAME: - checkIsland(e, e.getClickedBlock().getLocation(), Flags.PLACE_BLOCKS); - break; - default: - break; - - } // Now check for in-hand items if (e.getItem() != null) { switch (e.getItem().getType()) { @@ -218,4 +94,149 @@ public class BlockInteractionListener extends AbstractFlagListener { } } } + + /** + * Check if an action can occur on a clicked block + * @param e - event called + * @param loc - location of clicked block + * @param type - material type of clicked block + */ + private void checkClickedBlock(Event e, Location loc, Material type) { + switch (type) { + case ANVIL: + checkIsland(e, loc, Flags.ANVIL); + break; + case BEACON: + checkIsland(e, loc, Flags.BEACON); + break; + case BLACK_BED: + case BLUE_BED: + case BROWN_BED: + case CYAN_BED: + case GRAY_BED: + case GREEN_BED: + case LIGHT_BLUE_BED: + case LIGHT_GRAY_BED: + case LIME_BED: + case MAGENTA_BED: + case ORANGE_BED: + case PINK_BED: + case PURPLE_BED: + case RED_BED: + case WHITE_BED: + case YELLOW_BED: + checkIsland(e, loc, Flags.BED); + break; + case BREWING_STAND: + case CAULDRON: + checkIsland(e, loc, Flags.BREWING); + break; + case CHEST: + case CHEST_MINECART: + case TRAPPED_CHEST: + case BLACK_SHULKER_BOX: + case BLUE_SHULKER_BOX: + case BROWN_SHULKER_BOX: + case CYAN_SHULKER_BOX: + case GRAY_SHULKER_BOX: + case GREEN_SHULKER_BOX: + case LIGHT_BLUE_SHULKER_BOX: + case LIME_SHULKER_BOX: + case PINK_SHULKER_BOX: + case MAGENTA_SHULKER_BOX: + case ORANGE_SHULKER_BOX: + case PURPLE_SHULKER_BOX: + case RED_SHULKER_BOX: + case LIGHT_GRAY_SHULKER_BOX: + case WHITE_SHULKER_BOX: + case YELLOW_SHULKER_BOX: + case DISPENSER: + case DROPPER: + case HOPPER: + case HOPPER_MINECART: + checkIsland(e, loc, Flags.CHEST); + break; + case ACACIA_DOOR: + case BIRCH_DOOR: + case DARK_OAK_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case SPRUCE_DOOR: + case OAK_DOOR: + checkIsland(e, loc, Flags.DOOR); + break; + case ACACIA_TRAPDOOR: + case BIRCH_TRAPDOOR: + case DARK_OAK_TRAPDOOR: + case OAK_TRAPDOOR: + case JUNGLE_TRAPDOOR: + case SPRUCE_TRAPDOOR: + case IRON_TRAPDOOR: + checkIsland(e, loc, Flags.TRAPDOOR); + break; + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case SPRUCE_FENCE_GATE: + checkIsland(e, loc, Flags.GATE); + break; + case FURNACE: + checkIsland(e, loc, Flags.FURNACE); + break; + case ENCHANTING_TABLE: + checkIsland(e, loc, Flags.ENCHANTING); + break; + case ENDER_CHEST: + checkIsland(e, loc, Flags.ENDER_CHEST); + break; + case JUKEBOX: + checkIsland(e, loc, Flags.JUKEBOX); + break; + case NOTE_BLOCK: + checkIsland(e, loc, Flags.NOTE_BLOCK); + break; + case CRAFTING_TABLE: + checkIsland(e, loc, Flags.CRAFTING); + break; + case STONE_BUTTON: + case ACACIA_BUTTON: + case BIRCH_BUTTON: + case DARK_OAK_BUTTON: + case JUNGLE_BUTTON: + case OAK_BUTTON: + case SPRUCE_BUTTON: + checkIsland(e, loc, Flags.BUTTON); + break; + case LEVER: + checkIsland(e, loc, Flags.LEVER); + break; + case REPEATER: + case COMPARATOR: + case DAYLIGHT_DETECTOR: + checkIsland(e, loc, Flags.REDSTONE); + break; + case DRAGON_EGG: + checkIsland(e, loc, Flags.BREAK_BLOCKS); + break; + case END_PORTAL_FRAME: + checkIsland(e, loc, Flags.PLACE_BLOCKS); + break; + default: + break; + + } + + } + + /** + * Prevents blocks that are protected from being broken, which would bypass the protection + * + * @param e - event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockBreak(final BlockBreakEvent e) { + checkClickedBlock(e, e.getBlock().getLocation(), e.getBlock().getType()); + } } diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/EndermanListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/EndermanListener.java index eb43e8170..a3bdf742f 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/EndermanListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/EndermanListener.java @@ -3,14 +3,10 @@ */ package world.bentobox.bentobox.listeners.flags; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; import org.bukkit.entity.Enderman; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.inventory.ItemStack; import world.bentobox.bentobox.api.flags.AbstractFlagListener; import world.bentobox.bentobox.lists.Flags; @@ -36,25 +32,4 @@ public class EndermanListener extends AbstractFlagListener { } } - /** - * Drops the Enderman's block when he dies if he has one - * - * @param e - event - */ - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onEndermanDeath(final EntityDeathEvent e) { - if (!(e.getEntity() instanceof Enderman) - || !getIWM().inWorld(e.getEntity().getLocation()) - || !Flags.ENDERMAN_DEATH_DROP.isSetForWorld(e.getEntity().getWorld())) { - return; - } - // Get the block the enderman is holding - Enderman ender = (Enderman) e.getEntity(); - BlockData m = ender.getCarriedBlock(); - if (m != null && !m.getMaterial().equals(Material.AIR)) { - // Drop the item - e.getEntity().getWorld().dropItemNaturally(e.getEntity().getLocation(), new ItemStack(m.getMaterial())); - } - } - } diff --git a/src/main/java/world/bentobox/bentobox/lists/Flags.java b/src/main/java/world/bentobox/bentobox/lists/Flags.java index ae822afad..70e007f62 100644 --- a/src/main/java/world/bentobox/bentobox/lists/Flags.java +++ b/src/main/java/world/bentobox/bentobox/lists/Flags.java @@ -176,10 +176,6 @@ public class Flags { .listener(new EndermanListener()) .build(); - public static final Flag ENDERMAN_DEATH_DROP = new FlagBuilder().id("ENDERMAN_DEATH_DROP").icon(Material.END_ROD) - .allowedByDefault(true).type(Type.WORLD_SETTING) - .build(); - public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.WORLD_SETTING) .listener(new EnterExitListener()) .build(); diff --git a/src/main/java/world/bentobox/bentobox/managers/RanksManager.java b/src/main/java/world/bentobox/bentobox/managers/RanksManager.java index b67219afa..ff886f69d 100644 --- a/src/main/java/world/bentobox/bentobox/managers/RanksManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/RanksManager.java @@ -72,6 +72,9 @@ public class RanksManager { */ public boolean addRank(String reference, int value) { if (reference.equalsIgnoreCase(OWNER_RANK_REF) + || reference.equalsIgnoreCase(SUB_OWNER_RANK_REF) + || reference.equalsIgnoreCase(TRUSTED_RANK_REF) + || reference.equalsIgnoreCase(COOP_RANK_REF) || reference.equalsIgnoreCase(MEMBER_RANK_REF) || reference.equalsIgnoreCase(VISITOR_RANK_REF) || reference.equalsIgnoreCase(BANNED_RANK_REF) @@ -100,6 +103,9 @@ public class RanksManager { */ public boolean removeRank(String reference) { return !reference.equalsIgnoreCase(OWNER_RANK_REF) + && !reference.equalsIgnoreCase(SUB_OWNER_RANK_REF) + && !reference.equalsIgnoreCase(TRUSTED_RANK_REF) + && !reference.equalsIgnoreCase(COOP_RANK_REF) && !reference.equalsIgnoreCase(MEMBER_RANK_REF) && !reference.equalsIgnoreCase(VISITOR_RANK_REF) && !reference.equalsIgnoreCase(BANNED_RANK_REF) diff --git a/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java b/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java index 8df58b969..7294a1348 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java @@ -8,6 +8,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.World.Environment; +import org.bukkit.util.Vector; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.events.IslandBaseEvent; @@ -141,6 +142,10 @@ public class NewIsland { if (island.getSpawnPoint(Environment.NORMAL) != null) { plugin.getPlayers().setHomeLocation(user, island.getSpawnPoint(Environment.NORMAL), 1); } + // Stop the player from falling or moving if they are + user.getPlayer().setVelocity(new Vector(0,0,0)); + user.getPlayer().setFallDistance(0F); + // Teleport player after this island is built plugin.getIslands().homeTeleport(world, user.getPlayer(), true); }); diff --git a/src/main/java/world/bentobox/bentobox/schems/Clipboard.java b/src/main/java/world/bentobox/bentobox/schems/Clipboard.java index 0f04b2688..2329f3483 100644 --- a/src/main/java/world/bentobox/bentobox/schems/Clipboard.java +++ b/src/main/java/world/bentobox/bentobox/schems/Clipboard.java @@ -186,7 +186,11 @@ public class Clipboard { // Calculate location for pasting Location loc = island.getCenter().toVector().subtract(off).toLocation(world); // Paste - blockConfig.getConfigurationSection(BLOCK).getKeys(false).forEach(b -> pasteBlock(world, island, loc, blockConfig.getConfigurationSection(BLOCK + "." + b))); + if (blockConfig.contains(BLOCK)) { + blockConfig.getConfigurationSection(BLOCK).getKeys(false).forEach(b -> pasteBlock(world, island, loc, blockConfig.getConfigurationSection(BLOCK + "." + b))); + } else { + plugin.logError("Clipboard has no block data in it to paste!"); + } // Run follow on task if it exists if (task != null) { Bukkit.getScheduler().runTaskLater(plugin, task, 2L); @@ -198,8 +202,11 @@ public class Clipboard { * @param location - location */ public void pasteClipboard(Location location) { - blockConfig.getConfigurationSection(BLOCK).getKeys(false).forEach(b -> pasteBlock(location.getWorld(), null, location, blockConfig.getConfigurationSection(BLOCK + "." + b))); - + if (blockConfig.contains(BLOCK)) { + blockConfig.getConfigurationSection(BLOCK).getKeys(false).forEach(b -> pasteBlock(location.getWorld(), null, location, blockConfig.getConfigurationSection(BLOCK + "." + b))); + } else { + plugin.logError("Clipboard has no block data in it to paste!"); + } } private void writeSign(Island island, Block block, List lines) { @@ -238,10 +245,13 @@ public class Clipboard { if (config.getBoolean(ATTACHED)) { plugin.getServer().getScheduler().runTask(plugin, () -> setBlock(island, block, config, blockData)); } else { - setBlock(island, block, config, blockData); } } + // Entities + if (config.isConfigurationSection(ENTITY)) { + setEntity(island, block.getLocation(), config); + } } private void setBlock(Island island, Block block, ConfigurationSection config, String blockData) { @@ -249,10 +259,6 @@ public class Clipboard { block.setBlockData(Bukkit.createBlockData(blockData)); // Set the block state for chests, signs and mob spawners setBlockState(island, block, config); - // Set entities - if (config.isConfigurationSection(ENTITY)) { - setEntity(island, block.getLocation(), config); - } } /** @@ -266,7 +272,7 @@ public class Clipboard { en.getKeys(false).forEach(k -> { ConfigurationSection ent = en.getConfigurationSection(k); Location center = location.add(new Vector(0.5, 0.0, 0.5)); - LivingEntity e = (LivingEntity)island.getWorld().spawnEntity(center, EntityType.valueOf(ent.getString("type", "PIG"))); + LivingEntity e = (LivingEntity)location.getWorld().spawnEntity(center, EntityType.valueOf(ent.getString("type", "PIG"))); if (e != null) { e.setCustomName(ent.getString("name")); } diff --git a/src/test/java/world/bentobox/bentobox/listeners/DeathListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/DeathListenerTest.java new file mode 100644 index 000000000..dbacfbc54 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/listeners/DeathListenerTest.java @@ -0,0 +1,68 @@ +package world.bentobox.bentobox.listeners; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.PlayerDeathEvent; +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.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.PlayersManager; +import world.bentobox.bentobox.util.Util; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({BentoBox.class, Util.class, Bukkit.class }) +public class DeathListenerTest { + + + @Test + public void testDeathListener() { + assertNotNull(new DeathListener(mock(BentoBox.class))); + } + + @Test + public void testOnPlayerDeathEvent() { + // Set up plugin + BentoBox plugin = mock(BentoBox.class); + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + // Island World Manager + IslandWorldManager iwm = mock(IslandWorldManager.class); + when(iwm.inWorld(Mockito.any())).thenReturn(true); + when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("bskyblock"); + when(iwm.getVisitorBannedCommands(Mockito.any())).thenReturn(new ArrayList<>()); + when(plugin.getIWM()).thenReturn(iwm); + + // Player + Player player = mock(Player.class); + World world = mock(World.class); + when(player.getWorld()).thenReturn(world); + when(player.getLocation()).thenReturn(mock(Location.class)); + UUID uuid = UUID.randomUUID(); + when(player.getUniqueId()).thenReturn(uuid); + + PlayersManager pm = mock(PlayersManager.class); + when(plugin.getPlayers()).thenReturn(pm); + + // Test + DeathListener dl = new DeathListener(plugin); + + PlayerDeathEvent e = new PlayerDeathEvent(player, new ArrayList<>(), 0, 0, 0, 0, "died"); + dl.onPlayerDeathEvent(e); + Mockito.verify(pm).addDeath(world, uuid); + } + +} diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/EndermanListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/EndermanListenerTest.java index fe932d0a0..14a055070 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/EndermanListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/EndermanListenerTest.java @@ -9,7 +9,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -26,7 +25,6 @@ import org.bukkit.block.data.BlockData; import org.bukkit.entity.Enderman; import org.bukkit.entity.Slime; import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginManager; @@ -137,9 +135,6 @@ public class EndermanListenerTest { when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); // Not allowed to start Flags.ENDERMAN_GRIEFING.setSetting(world, false); - // Allowed to start - Flags.ENDERMAN_DEATH_DROP.setSetting(world, true); - } @@ -197,66 +192,4 @@ public class EndermanListenerTest { assertTrue(e.isCancelled()); } - /** - * Test method for {@link world.bentobox.bentobox.listeners.flags.EndermanListener#onEndermanDeath(org.bukkit.event.entity.EntityDeathEvent)}. - */ - @Test - public void testOnNotEndermanDeath() { - EndermanListener listener = new EndermanListener(); - EntityDeathEvent e = new EntityDeathEvent(slime, new ArrayList<>()); - listener.onEndermanDeath(e); - Mockito.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); - - } - - /** - * Test method for {@link world.bentobox.bentobox.listeners.flags.EndermanListener#onEndermanDeath(org.bukkit.event.entity.EntityDeathEvent)}. - */ - @Test - public void testOnEndermanDeathCarryAir() { - when(bd.getMaterial()).thenReturn(Material.AIR); - EndermanListener listener = new EndermanListener(); - EntityDeathEvent e = new EntityDeathEvent(enderman, new ArrayList<>()); - listener.onEndermanDeath(e); - Mockito.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); - } - - /** - * Test method for {@link world.bentobox.bentobox.listeners.flags.EndermanListener#onEndermanDeath(org.bukkit.event.entity.EntityDeathEvent)}. - */ - @Test - public void testOnEndermanDeathNotInWorld() { - when(iwm.inWorld(Mockito.any())).thenReturn(false); - EndermanListener listener = new EndermanListener(); - EntityDeathEvent e = new EntityDeathEvent(enderman, new ArrayList<>()); - listener.onEndermanDeath(e); - Mockito.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); - - } - - /** - * Test method for {@link world.bentobox.bentobox.listeners.flags.EndermanListener#onEndermanDeath(org.bukkit.event.entity.EntityDeathEvent)}. - */ - @Test - public void testOnEndermanDeathNoFlag() { - Flags.ENDERMAN_DEATH_DROP.setSetting(world, false); - EndermanListener listener = new EndermanListener(); - EntityDeathEvent e = new EntityDeathEvent(enderman, new ArrayList<>()); - listener.onEndermanDeath(e); - Mockito.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); - - } - - /** - * Test method for {@link world.bentobox.bentobox.listeners.flags.EndermanListener#onEndermanDeath(org.bukkit.event.entity.EntityDeathEvent)}. - */ - @Test - public void testOnEndermanDeath() { - EndermanListener listener = new EndermanListener(); - EntityDeathEvent e = new EntityDeathEvent(enderman, new ArrayList<>()); - listener.onEndermanDeath(e); - Mockito.verify(world).dropItemNaturally(Mockito.any(), Mockito.any()); - - } - } diff --git a/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java index f15f69269..9081a633e 100644 --- a/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java @@ -55,7 +55,7 @@ public class RanksManagerTest { */ @Test public void testRemoveRank() { - ranksManager.addRank("test.rank.reference2", 650); + assertTrue(ranksManager.addRank("test.rank.reference2", 650)); assertTrue(ranksManager.removeRank("test.rank.reference2")); // Second time should fail assertFalse(ranksManager.removeRank("test.rank.reference2")); diff --git a/src/test/java/world/bentobox/bentobox/schems/ClipboardTest.java b/src/test/java/world/bentobox/bentobox/schems/ClipboardTest.java new file mode 100644 index 000000000..056809897 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/schems/ClipboardTest.java @@ -0,0 +1,352 @@ +package world.bentobox.bentobox.schems; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Chest; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Cow; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Horse.Color; +import org.bukkit.entity.Horse.Style; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Pig; +import org.bukkit.entity.Player; +import org.bukkit.entity.Sheep; +import org.bukkit.inventory.HorseInventory; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.util.Vector; +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 world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class}) +public class ClipboardTest { + + private BentoBox plugin; + private File schemFolder; + private Location loc; + private User user; + private Location loc2; + private Sheep sheep; + private Horse horse; + private Block block; + private World world; + private BukkitScheduler sched; + + @Before + public void setUp() throws Exception { + plugin = mock(BentoBox.class); + schemFolder = mock(File.class); + when(schemFolder.exists()).thenReturn(true); + loc = mock(Location.class); + world = mock(World.class); + block = mock(Block.class); + when(block.getType()).thenReturn(Material.GRASS); + when(block.getLocation()).thenReturn(loc); + + BlockData bd = mock(BlockData.class); + when(bd.getAsString()).thenReturn("Block_data"); + when(block.getBlockData()).thenReturn(bd); + when(world.getBlockAt(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(block); + when(loc.getWorld()).thenReturn(world); + when(loc.getBlockX()).thenReturn(1); + when(loc.getBlockY()).thenReturn(2); + when(loc.getBlockZ()).thenReturn(3); + when(loc.getBlock()).thenReturn(block); + when(loc.toVector()).thenReturn(new Vector(1,2,3)); + + loc2 = mock(Location.class); + when(loc2.getWorld()).thenReturn(world); + when(loc2.getBlockX()).thenReturn(2); + when(loc2.getBlockY()).thenReturn(3); + when(loc2.getBlockZ()).thenReturn(4); + when(loc2.getBlock()).thenReturn(block); + // Living entities + + List ents = new ArrayList<>(); + Pig pig = mock(Pig.class); + Player player = mock(Player.class); + Cow cow = mock(Cow.class); + Creeper creeper = mock(Creeper.class); + sheep = mock(Sheep.class); + horse = mock(Horse.class); + when(pig.getLocation()).thenReturn(loc); + when(cow.getLocation()).thenReturn(loc); + when(creeper.getLocation()).thenReturn(loc); + when(player.getLocation()).thenReturn(loc); + when(sheep.getLocation()).thenReturn(loc); + when(horse.getLocation()).thenReturn(loc); + + when(pig.getType()).thenReturn(EntityType.PIG); + when(player.getType()).thenReturn(EntityType.PLAYER); + when(cow.getType()).thenReturn(EntityType.COW); + when(creeper.getType()).thenReturn(EntityType.CREEPER); + when(sheep.getType()).thenReturn(EntityType.SHEEP); + when(sheep.getColor()).thenReturn(DyeColor.LIGHT_BLUE); + when(horse.getType()).thenReturn(EntityType.HORSE); + when(horse.getColor()).thenReturn(Color.CREAMY); + when(horse.getStyle()).thenReturn(Style.BLACK_DOTS); + + HorseInventory inv = mock(HorseInventory.class); + when(horse.getInventory()).thenReturn(inv); + + // UUIDs (I'm going to assume these will all be unique (prays to god of randomness) + when(creeper.getUniqueId()).thenReturn(UUID.randomUUID()); + when(player.getUniqueId()).thenReturn(UUID.randomUUID()); + when(cow.getUniqueId()).thenReturn(UUID.randomUUID()); + when(pig.getUniqueId()).thenReturn(UUID.randomUUID()); + when(sheep.getUniqueId()).thenReturn(UUID.randomUUID()); + when(horse.getUniqueId()).thenReturn(UUID.randomUUID()); + + ents.add(creeper); + ents.add(player); + ents.add(cow); + ents.add(pig); + ents.add(sheep); + ents.add(horse); + when(world.getLivingEntities()).thenReturn(ents); + + user = mock(User.class); + User.setPlugin(plugin); + when(user.getLocation()).thenReturn(loc); + + // Scheduler + PowerMockito.mockStatic(Bukkit.class); + sched = mock(BukkitScheduler.class); + when(Bukkit.getScheduler()).thenReturn(sched); + + } + + @Test + public void testClipboard() { + when(schemFolder.exists()).thenReturn(false); + new Clipboard(plugin, schemFolder); + Mockito.verify(schemFolder).mkdirs(); + + } + + @Test + public void testSetGetPos1() { + Clipboard cb = new Clipboard(plugin, schemFolder); + assertNull(cb.getPos1()); + cb.setPos1(loc); + assertEquals(loc, cb.getPos1()); + assertNull(cb.getOrigin()); + } + + @Test + public void testSetGetPos2() { + Clipboard cb = new Clipboard(plugin, schemFolder); + assertNull(cb.getPos2()); + cb.setPos2(loc); + assertEquals(loc, cb.getPos2()); + } + + @Test + public void testSetGetOrigin() { + Clipboard cb = new Clipboard(plugin, schemFolder); + assertNull(cb.getOrigin()); + cb.setOrigin(loc); + assertEquals(loc, cb.getOrigin()); + } + + @Test + public void testCopyNoPos1Pos2() { + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.copy(user, false); + Mockito.verify(user).sendMessage(Mockito.eq("commands.admin.schem.need-pos1-pos2")); + } + + @Test + public void testCopyNoPos2() { + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.copy(user, false); + Mockito.verify(user).sendMessage(Mockito.eq("commands.admin.schem.need-pos1-pos2")); + } + + @Test + public void testCopy() { + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "8"); + } + + @Test + public void testCopySigns() { + when(block.getType()).thenReturn(Material.SIGN); + Sign bs = mock(Sign.class); + String[] lines = {"line1", "line2", "line3", "line4"}; + when(bs.getLines()).thenReturn(lines); + when(block.getState()).thenReturn(bs); + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "8"); + // Every block is a sign, so this should be called 8 times + Mockito.verify(bs, Mockito.times(8)).getLines(); + } + + @Test + public void testCopyChests() { + when(block.getType()).thenReturn(Material.CHEST); + Chest bs = mock(Chest.class); + Inventory inv = mock(Inventory.class); + ItemStack[] contents = { new ItemStack(Material.ACACIA_BOAT, 1), new ItemStack(Material.GLASS, 23)}; + when(inv.getContents()).thenReturn(contents); + when(bs.getInventory()).thenReturn(inv); + when(block.getState()).thenReturn(bs); + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "8"); + // Every block is a sign, so this should be called 8 times + Mockito.verify(bs, Mockito.times(8)).getInventory(); + } + + @Test + public void testCopyCreatureSpawners() { + when(block.getType()).thenReturn(Material.SPAWNER); + CreatureSpawner bs = mock(CreatureSpawner.class); + when(bs.getSpawnedType()).thenReturn(EntityType.CAVE_SPIDER); + when(block.getState()).thenReturn(bs); + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "8"); + // Every block is a sign, so this should be called 8 times + Mockito.verify(bs, Mockito.times(8)).getMaxNearbyEntities(); + } + + @Test + public void testCopyAir() { + // No entities + when(world.getLivingEntities()).thenReturn(new ArrayList<>()); + when(block.getType()).thenReturn(Material.AIR); + BlockState bs = mock(BlockState.class); + when(block.getState()).thenReturn(bs); + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + // Do not copy air + cb.copy(user, false); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "0"); + cb.copy(user, true); + Mockito.verify(user).sendMessage("commands.admin.schem.copied-blocks", TextVariables.NUMBER, "8"); + } + + + @Test + public void testPasteIslandNoData() { + Clipboard cb = new Clipboard(plugin, schemFolder); + Island island = mock(Island.class); + when(island.getCenter()).thenReturn(loc); + cb.pasteIsland(world, island, () -> {}); + Mockito.verify(plugin).logError(Mockito.eq("Clipboard has no block data in it to paste!")); + // Verify the task is run + Mockito.verify(sched).runTaskLater(Mockito.eq(plugin), Mockito.any(Runnable.class), Mockito.eq(2L)); + } + + @Test + public void testPasteIslandWithData() { + Clipboard cb = new Clipboard(plugin, schemFolder); + Island island = mock(Island.class); + when(island.getCenter()).thenReturn(loc); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + cb.pasteIsland(world, island, () -> {}); + // This is set just once because the coords of the block are always the same + Mockito.verify(block).setBlockData(Mockito.any()); + // Verify the entities are spawned + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.PIG)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.CREEPER)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.HORSE)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.SHEEP)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.COW)); + // Player should NOT spawn!! + Mockito.verify(world, Mockito.never()).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.PLAYER)); + + // Verify the task is run + Mockito.verify(sched).runTaskLater(Mockito.eq(plugin), Mockito.any(Runnable.class), Mockito.eq(2L)); + } + + @Test + public void testPasteClipboardNoData() { + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.pasteClipboard(loc); + Mockito.verify(plugin).logError(Mockito.eq("Clipboard has no block data in it to paste!")); + } + + @Test + public void testPasteClipboard() { + Clipboard cb = new Clipboard(plugin, schemFolder); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + cb.pasteClipboard(loc); + // This is set just once because the coords of the block are always the same + Mockito.verify(block).setBlockData(Mockito.any()); + // Verify the entities are spawned + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.PIG)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.CREEPER)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.HORSE)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.SHEEP)); + Mockito.verify(world).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.COW)); + // Player should NOT spawn!! + Mockito.verify(world, Mockito.never()).spawnEntity(Mockito.eq(null), Mockito.eq(EntityType.PLAYER)); + } + + @Test + public void testIsFull() { + Clipboard cb = new Clipboard(plugin, schemFolder); + assertFalse(cb.isFull()); + cb.setPos1(loc); + cb.setPos2(loc2); + cb.copy(user, false); + assertTrue(cb.isFull()); + } + + /* + * Will not test the file system methods + */ + +}