diff --git a/pom.xml b/pom.xml index 79dc81a..276e803 100644 --- a/pom.xml +++ b/pom.xml @@ -41,13 +41,9 @@ - - codemc-snapshots - https://repo.codemc.org/repository/maven-snapshots - - - codemc-releases - https://repo.codemc.org/repository/maven-releases + + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ @@ -58,17 +54,17 @@ 2.0.9 - 1.20.1-R0.1-SNAPSHOT + 1.21.3-R0.1-SNAPSHOT - 1.20.1-R0.1-SNAPSHOT - 1.24.1-SNAPSHOT + 1.21.3-R0.1-SNAPSHOT + 2.7.1-SNAPSHOT ${build.version}-SNAPSHOT -LOCAL - 1.3.0 + 1.4.0 bentobox-world https://sonarcloud.io @@ -124,6 +120,10 @@ papermc https://repo.papermc.io/repository/maven-public/ + + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ + codemc https://repo.codemc.org/repository/maven-snapshots/ diff --git a/src/main/java/world/bentobox/parkour/Parkour.java b/src/main/java/world/bentobox/parkour/Parkour.java index f8ba2b8..4c8e943 100644 --- a/src/main/java/world/bentobox/parkour/Parkour.java +++ b/src/main/java/world/bentobox/parkour/Parkour.java @@ -1,5 +1,6 @@ package world.bentobox.parkour; +import java.util.ArrayList; import java.util.HashMap; import org.bukkit.Material; @@ -91,7 +92,7 @@ public void setup() { adminCommand = new DefaultAdminCommand(this) { }; - parkourRunRecord = new ParkourRunRecord(new HashMap<>(), new HashMap<>()); + parkourRunRecord = new ParkourRunRecord(new HashMap<>(), new HashMap<>(), new ArrayList<>()); registerFlag(PARKOUR_CREATIVE); diff --git a/src/main/java/world/bentobox/parkour/ParkourRunRecord.java b/src/main/java/world/bentobox/parkour/ParkourRunRecord.java index 82240f9..797ddac 100644 --- a/src/main/java/world/bentobox/parkour/ParkourRunRecord.java +++ b/src/main/java/world/bentobox/parkour/ParkourRunRecord.java @@ -1,11 +1,12 @@ package world.bentobox.parkour; +import java.util.List; import java.util.Map; import java.util.UUID; import org.bukkit.Location; -public record ParkourRunRecord(Map checkpoints, Map timers) { +public record ParkourRunRecord(Map checkpoints, Map timers, List currentlyTeleporting) { /** * Clears any current times or checkpoints * @param uuid UUID of runner @@ -13,6 +14,7 @@ public record ParkourRunRecord(Map checkpoints, Map public void clear(UUID uuid) { checkpoints.remove(uuid); timers.remove(uuid); + currentlyTeleporting.remove(uuid); } } diff --git a/src/main/java/world/bentobox/parkour/Settings.java b/src/main/java/world/bentobox/parkour/Settings.java index 6d14156..43d82f8 100644 --- a/src/main/java/world/bentobox/parkour/Settings.java +++ b/src/main/java/world/bentobox/parkour/Settings.java @@ -14,6 +14,7 @@ import com.google.common.base.Enums; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.configuration.ConfigComment; import world.bentobox.bentobox.api.configuration.ConfigEntry; import world.bentobox.bentobox.api.configuration.StoreAt; @@ -138,6 +139,15 @@ public class Settings implements WorldSettings { @ConfigEntry(path = "world.max-areas") private int maxIslands = -1; + @ConfigComment("The number of concurrent areas a player can have") + @ConfigComment("A value of 0 will use the BentoBox config.yml default") + @ConfigEntry(path = "world.concurrent-area") + private int concurrentIslands = 0; + + @ConfigComment("Disallow team members from having their own area.") + @ConfigEntry(path = "world.disallow-team-member-areas") + private boolean disallowTeamMemberIslands = true; + @ConfigComment("The default game mode for this world. Players will be set to this mode when they create") @ConfigComment("a new area for example. Options are SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR") @ConfigEntry(path = "world.default-game-mode") @@ -148,7 +158,7 @@ public class Settings implements WorldSettings { private Biome defaultBiome = Biome.PLAINS; @ConfigComment("The default biome for the nether world (this may affect what mobs can spawn)") @ConfigEntry(path = "world.default-nether-biome") - private Biome defaultNetherBiome = Enums.getIfPresent(Biome.class, "NETHER").or(Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.BADLANDS)); + private Biome defaultNetherBiome = Biome.NETHER_WASTES; @ConfigComment("The default biome for the end world (this may affect what mobs can spawn)") @ConfigEntry(path = "world.default-end-biome") private Biome defaultEndBiome = Biome.THE_END; @@ -1721,4 +1731,36 @@ public Biome getDefaultEndBiome() { public void setDefaultEndBiome(Biome defaultEndBiome) { this.defaultEndBiome = defaultEndBiome; } + + /** + * @return the concurrentIslands + */ + @Override + public int getConcurrentIslands() { + if (concurrentIslands <= 0) { + return BentoBox.getInstance().getSettings().getIslandNumber(); + } + return concurrentIslands; + } + + /** + * @param concurrentIslands the concurrentIslands to set + */ + public void setConcurrentIslands(int concurrentIslands) { + this.concurrentIslands = concurrentIslands; + } + + /** + * @return the disallowTeamMemberIslands + */ + public boolean isDisallowTeamMemberIslands() { + return disallowTeamMemberIslands; + } + + /** + * @param disallowTeamMemberIslands the disallowTeamMemberIslands to set + */ + public void setDisallowTeamMemberIslands(boolean disallowTeamMemberIslands) { + this.disallowTeamMemberIslands = disallowTeamMemberIslands; + } } diff --git a/src/main/java/world/bentobox/parkour/commands/ClearTopCommand.java b/src/main/java/world/bentobox/parkour/commands/ClearTopCommand.java index 4ecb899..53b2afc 100644 --- a/src/main/java/world/bentobox/parkour/commands/ClearTopCommand.java +++ b/src/main/java/world/bentobox/parkour/commands/ClearTopCommand.java @@ -61,7 +61,8 @@ public boolean canExecute(User user, String label, List args) { Island island = getIslands().getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Check the name of the score to clear diff --git a/src/main/java/world/bentobox/parkour/commands/RemoveWarpCommand.java b/src/main/java/world/bentobox/parkour/commands/RemoveWarpCommand.java index a6ba496..b72c4da 100644 --- a/src/main/java/world/bentobox/parkour/commands/RemoveWarpCommand.java +++ b/src/main/java/world/bentobox/parkour/commands/RemoveWarpCommand.java @@ -7,6 +7,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.parkour.Parkour; import world.bentobox.parkour.ParkourManager; @@ -39,7 +40,7 @@ public boolean canExecute(User user, String label, List args) { // Check rank to use command int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/parkour/commands/SetWarpCommand.java b/src/main/java/world/bentobox/parkour/commands/SetWarpCommand.java index e2ce851..c3bb71b 100644 --- a/src/main/java/world/bentobox/parkour/commands/SetWarpCommand.java +++ b/src/main/java/world/bentobox/parkour/commands/SetWarpCommand.java @@ -10,6 +10,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.parkour.Parkour; import world.bentobox.parkour.ParkourManager; @@ -46,7 +47,8 @@ public boolean canExecute(User user, String label, List args) { Island island = getIslands().getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } Optional start = ((Parkour) getAddon()).getParkourManager().getStart(island); diff --git a/src/main/java/world/bentobox/parkour/commands/WarpCommand.java b/src/main/java/world/bentobox/parkour/commands/WarpCommand.java index f318815..ff03b9c 100644 --- a/src/main/java/world/bentobox/parkour/commands/WarpCommand.java +++ b/src/main/java/world/bentobox/parkour/commands/WarpCommand.java @@ -19,8 +19,8 @@ /** * Warps to a - * @author tastybento * + * @author tastybento */ public class WarpCommand extends CompositeCommand { @@ -48,7 +48,7 @@ public boolean canExecute(User user, String label, List args) { } if (args.isEmpty()) { Optional island = getIslands().getIslandAt(user.getLocation()); - if (island.isEmpty() || !((Parkour)getAddon()).inWorld(user.getWorld())) { + if (island.isEmpty() || !((Parkour) getAddon()).inWorld(user.getWorld())) { user.sendMessage("parkour.errors.not-on-island"); this.showHelp(this, user); return false; @@ -81,18 +81,18 @@ public boolean execute(User user, String label, List args) { // Teleport user user.getPlayer().playSound(user.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); user.getPlayer().playSound(warpSpot, Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); - Util.teleportAsync(user.getPlayer(), warpSpot.clone().add(new Vector(0.5, 0.5, 0.5)), TeleportCause.COMMAND); + Util.teleportAsync(user.getPlayer(), warpSpot, TeleportCause.COMMAND); return true; } @Override public Optional> tabComplete(User user, String alias, List args) { - ArrayList options = new ArrayList<>(((Parkour)getAddon()).getParkourManager().getWarps().keySet()); + ArrayList options = new ArrayList<>(((Parkour) getAddon()).getParkourManager().getWarps().keySet()); if (options.size() < 10) { return Optional.of(options); } // List is too long; require at least the first letter - String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; + String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : ""; if (args.isEmpty()) { return Optional.empty(); } diff --git a/src/main/java/world/bentobox/parkour/gui/CoursesTab.java b/src/main/java/world/bentobox/parkour/gui/CoursesTab.java index 63b5d2e..b711460 100644 --- a/src/main/java/world/bentobox/parkour/gui/CoursesTab.java +++ b/src/main/java/world/bentobox/parkour/gui/CoursesTab.java @@ -10,7 +10,6 @@ import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -25,9 +24,9 @@ /** * Implements a {@link Tab} that shows course rankings + * * @author tastybento * @since 1.0.0 - * */ public class CoursesTab implements Tab { @@ -36,8 +35,9 @@ public class CoursesTab implements Tab { /** * Show a tab of settings + * * @param addon - addon - * @param user - user who is viewing the tab + * @param user - user who is viewing the tab */ public CoursesTab(Parkour addon, User user) { super(); @@ -47,6 +47,7 @@ public CoursesTab(Parkour addon, User user) { /** * Get the icon for this tab + * * @return panel item */ @Override @@ -69,6 +70,7 @@ public String getName() { /** * Get all the flags as panel items + * * @return list of all the panel items for this flag type */ @Override @@ -78,32 +80,34 @@ public String getName() { List heads = new ArrayList<>(); // Sort the courses by runs addon.getParkourManager().getParkourData().stream() - .sorted() - .filter(hs -> Objects.nonNull(hs.getWarpSpot())) - .forEach(hs -> { - UUID owner = addon.getIslands().getIslandById(hs.getUniqueId()).map(Island::getOwner).orElse(null); - if (owner != null) { - heads.add(getHead(hs, owner)); - } - }); + .sorted() + .filter(hs -> Objects.nonNull(hs.getWarpSpot())) + .forEach(hs -> { + addon.getIslands().getIslandById(hs.getUniqueId()).ifPresent(is -> { + if (is.getOwner() != null) { + heads.add(getHead(hs, is)); + } + }); + }); return heads; } /** * Get the head panel item - * @param pd - parkour data - * @param playerUUID - the UUID of the owner + * + * @param pd - parkour data + * @param is.getOwner() - the UUID of the owner * @return PanelItem */ - private PanelItem getHead(ParkourData pd, UUID playerUUID) { - final String name = addon.getPlayers().getName(playerUUID); + private PanelItem getHead(ParkourData pd, Island is) { + final String name = addon.getPlayers().getName(is.getOwner()); List description = new ArrayList<>(); if (pd.getRunCount() > 0) { description.add(user.getTranslation("parkour.courses.head-description", "[name]", name, "[runs]", String.valueOf(pd.getRunCount()))); } - if (addon.getIslands().inTeam(addon.getOverWorld(), playerUUID)) { + if (addon.getIslands().inTeam(addon.getOverWorld(), is.getOwner())) { List memberList = new ArrayList<>(); - for (UUID members : addon.getIslands().getMembers(addon.getOverWorld(), playerUUID)) { + for (UUID members : is.getMemberSet()) { memberList.add(ChatColor.AQUA + addon.getPlayers().getName(members)); } description.addAll(memberList); @@ -115,7 +119,7 @@ private PanelItem getHead(ParkourData pd, UUID playerUUID) { .clickHandler((panel, user, clickType, slot) -> { user.sendMessage("parkour.warp.warping"); // Teleport user - Util.teleportAsync(user.getPlayer(), pd.getWarpSpot().clone().add(new Vector(0.5, 1, 0.5)), TeleportCause.COMMAND); + Util.teleportAsync(user.getPlayer(), pd.getWarpSpot(), TeleportCause.COMMAND); return true; }) .description(description); diff --git a/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java b/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java index 645162d..1503d3c 100644 --- a/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java +++ b/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java @@ -3,12 +3,15 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.UUID; +import org.bukkit.Bukkit; import org.bukkit.EntityEffect; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -16,8 +19,10 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.util.Vector; @@ -28,6 +33,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.util.Util; import world.bentobox.parkour.Parkour; import world.bentobox.parkour.ParkourRunRecord; @@ -71,13 +77,64 @@ public void onVisitorArrive(IslandEnterEvent e) { } else if (!parkourRunManager.timers().containsKey(e.getPlayerUUID())) { user.notify("parkour.to-start"); } - if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { - user.setGameMode(GameMode.CREATIVE); - } else { - user.setGameMode(GameMode.SURVIVAL); + + // the location that the player teleports from + Location fromLocation = user.getLocation(); + + if (addon.inWorld(fromLocation)) { + // if the player is staying in a parkour managed world they can have their gamemode changed + // this occurs when their island changes, so wont risk affecting players that are currently running + // since exit would trigger first + // cross (unmanaged) world teleportation is handled in onPlayerChangeWorld + + updateGamemode(island, user); } } + @EventHandler + public void onPlayerChangeWorld(PlayerChangedWorldEvent event) { + User user = User.getInstance(event.getPlayer()); + boolean fromParkour = addon.inWorld(event.getFrom()); + World newWorld = user.getWorld(); + boolean toParkour = addon.inWorld(newWorld); + + if (toParkour && !fromParkour) { + // switching from non-parkour world to parkour world + Bukkit.getServer().getScheduler().runTaskLater(addon.getPlugin(), () -> { + Location currentLocation = user.getLocation(); + + // world has changed in the 2 ticks delay, dont set gamemode + if (currentLocation.getWorld() != newWorld) { + return; + } + + addon.getIslandsManager().getIslandAt(currentLocation).ifPresent(island -> updateGamemode(island, user)); + }, 2); // 2 ticks since multiverse overrides gamemode after 1 tick + } + } + + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + User user = User.getInstance(event.getPlayer()); + World world = user.getWorld(); + if (!addon.inWorld(world)) { + return; + } + + Bukkit.getServer().getScheduler().runTaskLater(addon.getPlugin(), () -> { + Location currentLocation = user.getLocation(); + + // world has changed in the 2 ticks delay, dont set gamemode + if (currentLocation.getWorld() != world) { + return; + } + + addon.getIslandsManager().getIslandAt(currentLocation).ifPresent(island -> updateGamemode(island, user)); + }, 2); + } + + @EventHandler(priority = EventPriority.NORMAL) public void onVisitorLeave(IslandExitEvent e) { // If the user leaves any island, end and clear the session. @@ -91,6 +148,10 @@ public void onVisitorLeave(IslandExitEvent e) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerDeath(PlayerDeathEvent e) { // Game over + User user = User.getInstance(e.getEntity().getUniqueId()); + if (parkourRunManager.checkpoints().containsKey(e.getEntity().getUniqueId()) && user.isOnline()) { + user.notify("parkour.session-ended"); + } parkourRunManager.clear(e.getEntity().getUniqueId()); } @@ -113,44 +174,58 @@ public void onVisitorFall(EntityDamageEvent e) { player.playEffect(EntityEffect.ENTITY_POOF); player.setVelocity(new Vector(0, 0, 0)); player.setFallDistance(0); - player.teleport(parkourRunManager.checkpoints().get(player.getUniqueId())); - + Location checkpointLocation = parkourRunManager.checkpoints().get(player.getUniqueId()); + checkpointLocation = checkpointLocation.clone().add(0.5, 0, 0.5); + parkourRunManager.currentlyTeleporting().add(player.getUniqueId()); + Util.teleportAsync(player, checkpointLocation, PlayerTeleportEvent.TeleportCause.PLUGIN) + .thenAccept(b -> parkourRunManager.currentlyTeleporting().remove(player.getUniqueId())); } @EventHandler public void onTeleport(PlayerTeleportEvent e) { boolean shouldStopRun = switch (e.getCause()) { - case ENDER_PEARL, CHORUS_FRUIT, DISMOUNT, EXIT_BED -> false; - case COMMAND, PLUGIN, NETHER_PORTAL, END_PORTAL, SPECTATE, END_GATEWAY, UNKNOWN -> true; + case ENDER_PEARL, CHORUS_FRUIT, DISMOUNT, EXIT_BED, NETHER_PORTAL, END_PORTAL -> false; + case COMMAND, PLUGIN, SPECTATE, END_GATEWAY, UNKNOWN -> true; }; - if (shouldStopRun && parkourRunManager.timers().containsKey(e.getPlayer().getUniqueId())) { - User user = User.getInstance(e.getPlayer().getUniqueId()); - if (parkourRunManager.checkpoints().containsKey(e.getPlayer().getUniqueId()) && user.isOnline()) { + UUID playerUUID = e.getPlayer().getUniqueId(); + if (!parkourRunManager.currentlyTeleporting().contains(playerUUID) && shouldStopRun && parkourRunManager.timers().containsKey(playerUUID)) { + User user = User.getInstance(playerUUID); + if (parkourRunManager.checkpoints().containsKey(playerUUID) && user.isOnline()) { user.notify("parkour.session-ended"); } - parkourRunManager.clear(e.getPlayer().getUniqueId()); + parkourRunManager.clear(playerUUID); } // Check world - only apply flag actions to Parkour world and only if player is not actively running the course if (e.getTo() == null // To can sometimes be null... || !addon.inWorld(e.getTo()) - || parkourRunManager.timers().containsKey(e.getPlayer().getUniqueId())) { + || parkourRunManager.timers().containsKey(playerUUID)) { return; } // Handle flag action for players who are not running Optional fromIsland = addon.getIslands().getIslandAt(e.getFrom()); Optional toIsland = addon.getIslands().getIslandAt(e.getTo()); - if (fromIsland.isPresent() && toIsland.isPresent() && fromIsland.get().equals(toIsland.get())) { + boolean shouldAlterGamemode = switch (e.getCause()) { + case COMMAND, PLUGIN, UNKNOWN -> true; + default -> false; + }; + if (shouldAlterGamemode && fromIsland.isPresent() && toIsland.isPresent() && fromIsland.get().equals(toIsland.get())) { // same island teleport - Island island = fromIsland.get(); User user = User.getInstance(e.getPlayer()); - if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { - user.setGameMode(GameMode.CREATIVE); - } else { - user.setGameMode(GameMode.SURVIVAL); - } + updateGamemode(fromIsland.get(), user); } + } + private void updateGamemode(Island island, User user) { + if (user.hasPermission("parkour.mod.bypassgamemodechange")) { + return; + } + + if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { + user.setGameMode(GameMode.CREATIVE); + } else { + user.setGameMode(GameMode.SURVIVAL); + } } @@ -205,14 +280,14 @@ public void onStartEndSet(PlayerInteractEvent e) { return; } - Location l = e.getClickedBlock().getLocation(); + Location blockLocation = e.getClickedBlock().getLocation(); User user = User.getInstance(e.getPlayer()); - addon.getIslands().getProtectedIslandAt(l).ifPresent(island -> { + addon.getIslands().getProtectedIslandAt(blockLocation).ifPresent(island -> { Optional start = addon.getParkourManager().getStart(island); Optional end = addon.getParkourManager().getEnd(island); // Check if start and end is set - if (start.filter(startLoc -> isLocEquals(l, startLoc)).isPresent()) { + if (start.filter(startLoc -> isLocEquals(blockLocation, startLoc)).isPresent()) { // End is not set if (end.isEmpty()) { user.sendMessage("parkour.set-the-end"); @@ -220,29 +295,29 @@ public void onStartEndSet(PlayerInteractEvent e) { } // Start the race! if (!parkourRunManager.timers().containsKey(e.getPlayer().getUniqueId())) { - parkourStart(user, l); + parkourStart(user, blockLocation); } - } else if (end.filter(endLoc -> isLocEquals(l, endLoc)).isPresent() + } else if (end.filter(endLoc -> isLocEquals(blockLocation, endLoc)).isPresent() && parkourRunManager.timers().containsKey(e.getPlayer().getUniqueId())) { // End the race! - parkourEnd(user, island, l); + parkourEnd(user, island, blockLocation); } }); } - void parkourStart(User user, Location l) { + void parkourStart(User user, Location blockLocation) { user.sendMessage("parkour.start"); - user.getPlayer().playSound(l, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); + user.getPlayer().playSound(blockLocation, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); parkourRunManager.timers().put(user.getUniqueId(), System.currentTimeMillis()); - parkourRunManager.checkpoints().put(user.getUniqueId(), user.getLocation()); + parkourRunManager.checkpoints().put(user.getUniqueId(), blockLocation); user.setGameMode(GameMode.SURVIVAL); } - void parkourEnd(User user, Island island, Location l) { + void parkourEnd(User user, Island island, Location blockLocation) { long duration = (System.currentTimeMillis() - Objects.requireNonNull(parkourRunManager.timers().get(user.getUniqueId()))); user.notify("parkour.end"); - user.getPlayer().playSound(l, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); + user.getPlayer().playSound(blockLocation, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); user.notify("parkour.you-took", TextVariables.NUMBER, getDuration(user, duration)); parkourRunManager.clear(user.getUniqueId()); @@ -279,14 +354,18 @@ public void onCheckpoint(PlayerInteractEvent e) { || !parkourRunManager.timers().containsKey(e.getPlayer().getUniqueId())) { return; } - Location l = e.getClickedBlock().getLocation(); - User user = User.getInstance(e.getPlayer()); - Vector checkPoint = parkourRunManager.checkpoints().get(e.getPlayer().getUniqueId()).toVector(); - - if (addon.getIslands().getProtectedIslandAt(l).isPresent() && !l.toVector().equals(checkPoint)) { - user.notify("parkour.checkpoint"); - e.getPlayer().playSound(l, Sound.BLOCK_BELL_USE, 1F, 1F); - parkourRunManager.checkpoints().put(user.getUniqueId(), e.getPlayer().getLocation()); + Location newCheckpointBlockLocation = e.getClickedBlock().getLocation(); + if (addon.getIslands().getProtectedIslandAt(newCheckpointBlockLocation).isPresent()) { + // pressure plate should be a checkpoint + Location currentCheckpointBlockLocation = parkourRunManager.checkpoints().get(e.getPlayer().getUniqueId()); + if (!isLocEquals(newCheckpointBlockLocation, currentCheckpointBlockLocation)) { + // new location is different + User user = User.getInstance(e.getPlayer()); + user.sendMessage("parkour.checkpoint"); + e.getPlayer().playSound(newCheckpointBlockLocation, Sound.BLOCK_BELL_USE, 1F, 1F); + parkourRunManager.checkpoints().put(user.getUniqueId(), newCheckpointBlockLocation); + } } } + } diff --git a/src/main/java/world/bentobox/parkour/listeners/MakeCourseListener.java b/src/main/java/world/bentobox/parkour/listeners/MakeCourseListener.java index fbe2c99..c86cba9 100644 --- a/src/main/java/world/bentobox/parkour/listeners/MakeCourseListener.java +++ b/src/main/java/world/bentobox/parkour/listeners/MakeCourseListener.java @@ -50,10 +50,11 @@ public void onWarpSet(BlockPlaceEvent e) { Optional warpSpot = addon.getParkourManager().getWarpSpot(island); if (warpSpot.isEmpty()) { user.notify("parkour.warp.set"); - addon.getParkourManager().setWarpSpot(island, l); } else { user.notify("parkour.warp.replaced"); } + // shift from block to player location + addon.getParkourManager().setWarpSpot(island, l.add(0.5,0,0.5)); } } diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index e287f7c..b2ecd55 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -1,7 +1,7 @@ name: Parkour main: world.bentobox.parkour.Parkour version: ${version}${build.number} -api-version: 1.24 +api-version: 2.7.1 metrics: true icon: "POLISHED_BLACKSTONE_PRESSURE_PLATE" repository: "BentoBoxWorld/Parkour" @@ -40,6 +40,9 @@ permissions: parkour.mod.bypasslock: description: Bypasses an course lock default: op + parkour.mod.bypassgamemodechange: + description: Bypasses the changing of your gamemode when entering your island. + default: false parkour.mod.bypassban: description: Bypasses course ban default: op @@ -89,18 +92,6 @@ permissions: parkour.mod.team.setowner: description: Allow use of '/pkadmin team setowner' command - transfers course ownership to the player default: op - parkour.mod.team.add: - description: Allow use of '/pkadmin add' command - add player to owner's team - default: op - parkour.mod.team.kick: - description: Allow use of '/pkadmin kick' command - kick a player from a team - default: op - parkour.mod.team.disband: - description: Allow use of '/pkadmin disband' command - disband owner's team - default: op - parkour.mod.team.setowner: - description: Allow use of '/pkadmin setowner' command - transfers course ownership to the player - default: op parkour.admin.blueprint: description: Allow use of '/pkadmin blueprint' command - manipulate blueprints default: op @@ -170,9 +161,6 @@ permissions: parkour.admin.resets.add: description: Allow use of '/pkadmin resets add' command - adds this player's course reset count default: op - parkour.admin.resets.remove: - description: Allow use of '/pkadmin resets remove' command - reduces the player's course reset count - default: op parkour.admin.delete: description: Allow use of '/pkadmin delete' command - deletes a player and regenerates their course default: op @@ -296,9 +284,6 @@ permissions: parkour.island.team.coop: description: Allow use of '/parkour team coop' command - make a player coop rank on your course default: true - parkour.island.team.coop: - description: Allow use of '/parkour team uncoop' command - remove a coop rank from player - default: true parkour.island.team.trust: description: Allow use of '/parkour team trust', '/parkour team untrust' command - remove trusted player rank from player default: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 76abb7e..75f1ee7 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: BentoBox-Parkour main: world.bentobox.parkour.ParkourPladdon version: ${project.version}${build.number} -api-version: "1.20" +api-version: "1.21" authors: [tastybento] contributors: ["The BentoBoxWorld Community"] diff --git a/src/test/java/world/bentobox/parkour/AbstractParkourTest.java b/src/test/java/world/bentobox/parkour/AbstractParkourTest.java new file mode 100644 index 0000000..9e0d134 --- /dev/null +++ b/src/test/java/world/bentobox/parkour/AbstractParkourTest.java @@ -0,0 +1,178 @@ +package world.bentobox.parkour; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.beans.IntrospectionException; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Comparator; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginManager; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; +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 world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.Settings; +import world.bentobox.bentobox.api.configuration.Config; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.AbstractDatabaseHandler; +import world.bentobox.bentobox.database.DatabaseSetup; +import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.AddonsManager; +import world.bentobox.bentobox.managers.CommandsManager; +import world.bentobox.bentobox.managers.FlagsManager; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.bentobox.managers.PlaceholdersManager; +import world.bentobox.bentobox.managers.RanksManager; +import world.bentobox.bentobox.util.Util; +import world.bentobox.parkour.mocks.ServerMocks; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, Config.class, DatabaseSetup.class, Util.class }) +public abstract class AbstractParkourTest { + + @Mock + protected User user; + @Mock + protected IslandsManager im; + @Mock + protected Island island; + @Mock + protected BentoBox plugin; + @Mock + protected FlagsManager fm; + @Mock + protected Settings settings; + @Mock + protected PlaceholdersManager phm; + @Mock + protected IslandWorldManager iwm; + @Mock + protected Parkour addon; + @Mock + private RanksManager rm; + protected static AbstractDatabaseHandler h; + + @SuppressWarnings("unchecked") + @BeforeClass + public static void beforeClass() throws IllegalAccessException, InvocationTargetException, IntrospectionException { + // This has to be done beforeClass otherwise the tests will interfere with each + // other + h = mock(AbstractDatabaseHandler.class); + // Database + PowerMockito.mockStatic(DatabaseSetup.class); + DatabaseSetup dbSetup = mock(DatabaseSetup.class); + when(DatabaseSetup.getDatabase()).thenReturn(dbSetup); + when(dbSetup.getHandler(any())).thenReturn(h); + when(h.saveObject(any())).thenReturn(CompletableFuture.completedFuture(true)); + } + + @After + public void tearDown() throws IOException { + ServerMocks.unsetBukkitServer(); + User.clearUsers(); + Mockito.framework().clearInlineMocks(); + deleteAll(new File("database")); + deleteAll(new File("database_backup")); + deleteAll(new File("addon.jar")); + deleteAll(new File("config.yml")); + deleteAll(new File("addons")); + } + + protected void deleteAll(File file) throws IOException { + if (file.exists()) { + Files.walk(file.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } + + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + Server server = ServerMocks.newServer(); + // Set up plugin + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + when(plugin.getLogger()).thenReturn(Logger.getAnonymousLogger()); + + // The database type has to be created one line before the thenReturn() to work! + DatabaseType value = DatabaseType.JSON; + when(plugin.getSettings()).thenReturn(settings); + when(settings.getDatabaseType()).thenReturn(value); + when(plugin.getPlaceholdersManager()).thenReturn(phm); + // Placeholders + when(phm.replacePlaceholders(any(), anyString())).thenAnswer(a -> (String) a.getArgument(1, String.class)); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + when(user.isOp()).thenReturn(false); + UUID uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + User.setPlugin(plugin); + + // Island World Manager + when(plugin.getIWM()).thenReturn(iwm); + + // Player has island to begin with + island = mock(Island.class); + when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island); + when(plugin.getIslands()).thenReturn(im); + + // Locales + // Return the reference (USE THIS IN THE FUTURE) + when(user.getTranslation(Mockito.anyString())) + .thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + + // Server + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + when(Bukkit.getServer()).thenReturn(server); + when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); + when(Bukkit.getPluginManager()).thenReturn(mock(PluginManager.class)); + + // Addons manager + AddonsManager am = mock(AddonsManager.class); + when(plugin.getAddonsManager()).thenReturn(am); + + // Flags manager + when(plugin.getFlagsManager()).thenReturn(fm); + when(fm.getFlags()).thenReturn(Collections.emptyList()); + + } + +} diff --git a/src/test/java/world/bentobox/parkour/ParkourManagerTest.java b/src/test/java/world/bentobox/parkour/ParkourManagerTest.java index 171b5c6..56b3c8e 100644 --- a/src/test/java/world/bentobox/parkour/ParkourManagerTest.java +++ b/src/test/java/world/bentobox/parkour/ParkourManagerTest.java @@ -47,6 +47,7 @@ import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.util.Util; +import world.bentobox.parkour.mocks.ServerMocks; import world.bentobox.parkour.objects.ParkourData; /** @@ -99,6 +100,8 @@ public static void beforeClass() throws IllegalAccessException, InvocationTarget @Before public void setUp() { + ServerMocks.newServer(); + when(addon.getPlugin()).thenReturn(plugin); // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); @@ -150,6 +153,7 @@ public void setUp() { */ @After public void tearDown() throws Exception { + ServerMocks.unsetBukkitServer(); deleteAll(new File("database")); User.clearUsers(); Mockito.framework().clearInlineMocks(); diff --git a/src/test/java/world/bentobox/parkour/ParkourTest.java b/src/test/java/world/bentobox/parkour/ParkourTest.java index d9b11d4..4feb606 100644 --- a/src/test/java/world/bentobox/parkour/ParkourTest.java +++ b/src/test/java/world/bentobox/parkour/ParkourTest.java @@ -4,12 +4,9 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import java.io.File; import java.io.FileInputStream; @@ -19,254 +16,137 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collections; -import java.util.Comparator; -import java.util.UUID; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; -import java.util.logging.Logger; -import org.bukkit.Bukkit; -import org.bukkit.Server; -import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginManager; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; -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 world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.addons.Addon.State; import world.bentobox.bentobox.api.addons.AddonDescription; -import world.bentobox.bentobox.api.configuration.Config; -import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType; -import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.managers.AddonsManager; -import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.FlagsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; -import world.bentobox.bentobox.managers.PlaceholdersManager; /** * @author tastybento * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class, Config.class }) -public class ParkourTest { - - @Mock - private User user; - @Mock - private IslandsManager im; - @Mock - private Island island; - - private Parkour addon; - @Mock - private BentoBox plugin; - @Mock - private FlagsManager fm; - @Mock - private Settings settings; - @Mock - private PlaceholdersManager phm; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - when(plugin.getLogger()).thenReturn(Logger.getAnonymousLogger()); - - // The database type has to be created one line before the thenReturn() to work! - DatabaseType value = DatabaseType.JSON; - when(plugin.getSettings()).thenReturn(settings); - when(settings.getDatabaseType()).thenReturn(value); - when(plugin.getPlaceholdersManager()).thenReturn(phm); - // Placeholders - when(phm.replacePlaceholders(any(), anyString())).thenAnswer(a -> (String)a.getArgument(1, String.class)); - - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // Player - Player p = mock(Player.class); - // Sometimes use Mockito.withSettings().verboseLogging() - when(user.isOp()).thenReturn(false); - UUID uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - User.setPlugin(plugin); - - // Island World Manager - IslandWorldManager iwm = mock(IslandWorldManager.class); - when(plugin.getIWM()).thenReturn(iwm); - - - // Player has island to begin with - island = mock(Island.class); - when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island); - when(plugin.getIslands()).thenReturn(im); - - // Locales - // Return the reference (USE THIS IN THE FUTURE) - when(user.getTranslation(Mockito.anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); - - // Server - PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); - Server server = mock(Server.class); - when(Bukkit.getServer()).thenReturn(server); - when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); - when(Bukkit.getPluginManager()).thenReturn(mock(PluginManager.class)); - - // Create an Addon - addon = new Parkour(); - File jFile = new File("addon.jar"); - try (JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(jFile))) { - - // Copy over config file from src folder - Path fromPath = Paths.get("src/main/resources/config.yml"); - Path path = Paths.get("config.yml"); - Files.copy(fromPath, path); - - //Add the new files to the jar. - add(path, tempJarOutputStream); - - } - - File dataFolder = new File("addons/Parkour"); - addon.setDataFolder(dataFolder); - addon.setFile(jFile); - AddonDescription desc = new AddonDescription.Builder("bentobox", "parkour", "1.3").description("test").authors("tasty").build(); - addon.setDescription(desc); - // Addons manager - AddonsManager am = mock(AddonsManager.class); - when(plugin.getAddonsManager()).thenReturn(am); - - // Flags manager - when(plugin.getFlagsManager()).thenReturn(fm); - when(fm.getFlags()).thenReturn(Collections.emptyList()); - - } - - private void add(Path path, JarOutputStream tempJarOutputStream) throws FileNotFoundException, IOException { - try (FileInputStream fis = new FileInputStream(path.toFile())) { - byte[] buffer = new byte[1024]; - int bytesRead = 0; - JarEntry entry = new JarEntry(path.toString()); - tempJarOutputStream.putNextEntry(entry); - while((bytesRead = fis.read(buffer)) != -1) { - tempJarOutputStream.write(buffer, 0, bytesRead); - } - } - - } - - /** - * @throws java.lang.Exception - */ - @After - public void tearDown() throws Exception { - new File("addon.jar").delete(); - new File("config.yml").delete(); - deleteAll(new File("addons")); - deleteAll(new File("database")); - } - - private void deleteAll(File file) throws IOException { - if (file.exists()) { - Files.walk(file.toPath()) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } - - } - - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#onEnable()}. - */ - @Test - public void testOnEnable() { - testOnLoad(); - addon.setState(State.ENABLED); - addon.onEnable(); - verify(plugin, never()).logError(anyString()); - assertNotEquals(State.DISABLED, addon.getState()); - } - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#onLoad()}. - */ - @Test - public void testOnLoad() { - addon.onLoad(); - // Check that config.yml file has been saved - File check = new File("addons/Parkour","config.yml"); - assertTrue(check.exists()); - assertTrue(addon.getPlayerCommand().isPresent()); - assertTrue(addon.getAdminCommand().isPresent()); - - } - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#onReload()}. - */ - @Test - public void testOnReload() { - addon.onEnable(); - addon.onReload(); - // Check that config.yml file has been saved - File check = new File("addons/Parkour","config.yml"); - assertTrue(check.exists()); - } - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#createWorlds()}. - */ - @Test - public void testCreateWorlds() { - addon.onLoad(); - addon.createWorlds(); - verify(plugin).log("[parkour] Creating Parkour world ..."); - verify(plugin).log("[parkour] Creating Parkour's Nether..."); - verify(plugin).log("[parkour] Creating Parkour's End World..."); - - } - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#getSettings()}. - */ - @Test - public void testGetSettings() { - addon.onLoad(); - assertNotNull(addon.getSettings()); - - } - - /** - * Test method for {@link world.bentobox.aoneblock.AOneBlock#getWorldSettings()}. - */ - @Test - public void testGetWorldSettings() { - addon.onLoad(); - assertEquals(addon.getSettings(), addon.getWorldSettings()); - } +public class ParkourTest extends AbstractParkourTest { + + protected Parkour addonJar; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + // Create an Addon + addonJar = new Parkour(); + File jFile = new File("addon.jar"); + try (JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(jFile))) { + + // Copy over config file from src folder + Path fromPath = Paths.get("src/main/resources/config.yml"); + Path path = Paths.get("config.yml"); + Files.copy(fromPath, path); + + // Add the new files to the jar. + add(path, tempJarOutputStream); + + } + + File dataFolder = new File("addons/Parkour"); + addonJar.setDataFolder(dataFolder); + addonJar.setFile(jFile); + AddonDescription desc = new AddonDescription.Builder("bentobox", "parkour", "1.3").description("test") + .authors("tasty").build(); + addonJar.setDescription(desc); + + } + + private void add(Path path, JarOutputStream tempJarOutputStream) throws FileNotFoundException, IOException { + try (FileInputStream fis = new FileInputStream(path.toFile())) { + byte[] buffer = new byte[1024]; + int bytesRead = 0; + JarEntry entry = new JarEntry(path.toString()); + tempJarOutputStream.putNextEntry(entry); + while ((bytesRead = fis.read(buffer)) != -1) { + tempJarOutputStream.write(buffer, 0, bytesRead); + } + } + + } + + /** + * Test method for {@link world.bentobox.aoneblock.AOneBlock#onEnable()}. + */ + @Test + public void testOnEnable() { + testOnLoad(); + addonJar.setState(State.ENABLED); + addonJar.onEnable(); + verify(plugin, never()).logError(anyString()); + assertNotEquals(State.DISABLED, addonJar.getState()); + } + + /** + * Test method for {@link world.bentobox.aoneblock.AOneBlock#onLoad()}. + */ + @Test + public void testOnLoad() { + addonJar.onLoad(); + // Check that config.yml file has been saved + File check = new File("addons/Parkour", "config.yml"); + assertTrue(check.exists()); + assertTrue(addonJar.getPlayerCommand().isPresent()); + assertTrue(addonJar.getAdminCommand().isPresent()); + + } + + /** + * Test method for {@link world.bentobox.aoneblock.AOneBlock#onReload()}. + */ + @Test + public void testOnReload() { + addonJar.onEnable(); + addonJar.onReload(); + // Check that config.yml file has been saved + File check = new File("addons/Parkour", "config.yml"); + assertTrue(check.exists()); + } + + /** + * Test method for {@link world.bentobox.aoneblock.AOneBlock#createWorlds()}. + */ + @Test + public void testCreateWorlds() { + addonJar.onLoad(); + addonJar.createWorlds(); + verify(plugin).log("[parkour] Creating Parkour world ..."); + verify(plugin).log("[parkour] Creating Parkour's Nether..."); + verify(plugin).log("[parkour] Creating Parkour's End World..."); + + } + + /** + * Test method for {@link world.bentobox.aoneblock.AOneBlock#getSettings()}. + */ + @Test + public void testGetSettings() { + addonJar.onLoad(); + assertNotNull(addonJar.getSettings()); + + } + + /** + * Test method for + * {@link world.bentobox.aoneblock.AOneBlock#getWorldSettings()}. + */ + @Test + public void testGetWorldSettings() { + addonJar.onLoad(); + assertEquals(addonJar.getSettings(), addonJar.getWorldSettings()); + } } diff --git a/src/test/java/world/bentobox/parkour/SettingsTest.java b/src/test/java/world/bentobox/parkour/SettingsTest.java index 402dc03..5b95165 100644 --- a/src/test/java/world/bentobox/parkour/SettingsTest.java +++ b/src/test/java/world/bentobox/parkour/SettingsTest.java @@ -3,26 +3,36 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; import java.util.Collections; import java.util.List; import java.util.Map; +import org.bukkit.Bukkit; import org.bukkit.Difficulty; import org.bukkit.GameMode; +import org.bukkit.Server; import org.bukkit.block.Biome; import org.bukkit.entity.EntityType; import org.junit.After; 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.api.user.User; +import world.bentobox.parkour.mocks.ServerMocks; + /** * @author tastybento * */ @RunWith(PowerMockRunner.class) +@PrepareForTest(Bukkit.class) public class SettingsTest { private Settings s; @@ -32,14 +42,17 @@ public class SettingsTest { */ @Before public void setUp() throws Exception { + Server server = ServerMocks.newServer(); + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + when(Bukkit.getServer()).thenReturn(server); s = new Settings(); } - /** - * @throws java.lang.Exception - */ @After - public void tearDown() throws Exception { + public void tearDown() { + ServerMocks.unsetBukkitServer(); + User.clearUsers(); + Mockito.framework().clearInlineMocks(); } /** diff --git a/src/test/java/world/bentobox/parkour/commands/ClearTopCommandTest.java b/src/test/java/world/bentobox/parkour/commands/ClearTopCommandTest.java index ee94bd7..0a23d2e 100644 --- a/src/test/java/world/bentobox/parkour/commands/ClearTopCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/ClearTopCommandTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -24,6 +25,7 @@ import org.bukkit.entity.Player; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,13 +52,14 @@ import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.Settings; import world.bentobox.parkour.gui.RankingsUI; +import world.bentobox.parkour.mocks.ServerMocks; /** * @author tastybento * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class, Util.class}) +@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, Util.class, RanksManager.class }) public class ClearTopCommandTest { @Mock @@ -88,12 +91,15 @@ public class ClearTopCommandTest { private RankingsUI rankings; @Mock private PlayersManager pm; + @Mock + private RanksManager rm; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { + ServerMocks.newServer(); // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); world.bentobox.bentobox.Settings s = new world.bentobox.bentobox.Settings(); @@ -155,8 +161,7 @@ public void setUp() throws Exception { when(addon.getSettings()).thenReturn(settings); // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); + Whitebox.setInternalState(RanksManager.class, "instance", rm); // Players Manager when(addon.getPlayers()).thenReturn(pm); @@ -165,18 +170,22 @@ public void setUp() throws Exception { // DUT cmd = new ClearTopCommand(ac); } + + @After + public void tearDown() { + ServerMocks.unsetBukkitServer(); + User.clearUsers(); + Mockito.framework().clearInlineMocks(); + } + /** * Test method for {@link world.bentobox.parkour.commands.ClearTopCommand#ClearTopCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. */ @Test public void testClearTopCommand() { - assertNonNull(cmd); + assertNotNull(cmd); } - private void assertNonNull(ClearTopCommand cmd2) { - // TODO Auto-generated method stub - - } /** * Test method for {@link world.bentobox.parkour.commands.ClearTopCommand#setup()}. */ @@ -217,7 +226,7 @@ public void testCanExecuteNoIsland() { public void testCanExecuteInsufficientRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.ADMIN_RANK); assertFalse(cmd.canExecute(user, "", List.of())); - verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, null); } diff --git a/src/test/java/world/bentobox/parkour/commands/QuitCommandTest.java b/src/test/java/world/bentobox/parkour/commands/QuitCommandTest.java index 2c953dc..d2c8bf7 100644 --- a/src/test/java/world/bentobox/parkour/commands/QuitCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/QuitCommandTest.java @@ -11,35 +11,28 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -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.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.parkour.Parkour; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.ParkourRunRecord; import world.bentobox.parkour.Settings; @@ -49,122 +42,108 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) -public class QuitCommandTest { - @Mock - private BentoBox plugin; - @Mock - private CompositeCommand ac; - @Mock - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - @Mock - private ParkourManager parkourManager; - - private QuitCommand cmd; - @Mock - private @NonNull Location location; - // No mock - private ParkourRunRecord prm; - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // Player - Player p = mock(Player.class); - // Sometimes use Mockito.withSettings().verboseLogging() - when(user.isOp()).thenReturn(false); - when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); - when(user.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - when(user.getLocation()).thenReturn(location); - when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); - User.setPlugin(plugin); - - // Parent command has no aliases - when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); - when(ac.getWorld()).thenReturn(world); - when(ac.getAddon()).thenReturn(addon); - - prm = new ParkourRunRecord(new HashMap<>(), new HashMap<>()); - prm.timers().put(uuid, 20L); - when(addon.getParkourRunRecord()).thenReturn(prm); - - // Islands - when(addon.getIslands()).thenReturn(im); - when(plugin.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.getIslandAt(location)).thenReturn(Optional.of(island)); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // No warp spot - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); - when(iwm.inWorld(world)).thenReturn(true); - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // DUT - cmd = new QuitCommand(ac); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.QuitCommand#QuitCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. - */ - @Test - public void testQuitCommand() { - assertNotNull(cmd); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.QuitCommand#setup()}. - */ - @Test - public void testSetup() { - assertEquals("quit", cmd.getPermission()); - assertEquals("parkour.commands.parkour.quit.description", cmd.getDescription()); - assertTrue(cmd.isOnlyPlayer()); - } - - /** +public class QuitCommandTest extends AbstractParkourTest { + @Mock + private CompositeCommand ac; + @Mock + private User user; + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + @Mock + private ParkourManager parkourManager; + + private QuitCommand cmd; + @Mock + private @NonNull Location location; + // No mock + private ParkourRunRecord prm; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + when(user.isOp()).thenReturn(false); + when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); + when(user.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + when(user.getLocation()).thenReturn(location); + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + User.setPlugin(plugin); + + // Parent command has no aliases + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ac.getWorld()).thenReturn(world); + when(ac.getAddon()).thenReturn(addon); + + prm = new ParkourRunRecord(new HashMap<>(), new HashMap<>(), new ArrayList<>()); + prm.timers().put(uuid, 20L); + when(addon.getParkourRunRecord()).thenReturn(prm); + + // Islands + when(addon.getIslands()).thenReturn(im); + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.getIslandAt(location)).thenReturn(Optional.of(island)); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // No warp spot + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); + when(iwm.inWorld(world)).thenReturn(true); + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // DUT + cmd = new QuitCommand(ac); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.QuitCommand#QuitCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. + */ + @Test + public void testQuitCommand() { + assertNotNull(cmd); + } + + /** + * Test method for {@link world.bentobox.parkour.commands.QuitCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("quit", cmd.getPermission()); + assertEquals("parkour.commands.parkour.quit.description", cmd.getDescription()); + assertTrue(cmd.isOnlyPlayer()); + } + + /** * Test method for {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -174,7 +153,7 @@ public void testCanExecuteWrongWorld() { verify(user).sendMessage("general.errors.wrong-world"); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -185,33 +164,36 @@ public void testCanExecuteNotOnIsland() { verify(user).sendMessage("parkour.errors.not-on-island"); } - /** - * Test method for {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteNotInRun() { - prm.timers().clear(); - assertFalse(cmd.canExecute(user, "", List.of())); - verify(user).sendMessage("parkour.errors.not-in-run"); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteSuccess() { - assertTrue(cmd.canExecute(user, "", List.of())); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.QuitCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfString() { - assertTrue(cmd.execute(user, "", List.of())); - verify(user).sendMessage("parkour.quit.success"); - assertTrue(prm.timers().isEmpty()); - assertTrue(prm.checkpoints().isEmpty()); - } + /** + * Test method for + * {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteNotInRun() { + prm.timers().clear(); + assertFalse(cmd.canExecute(user, "", List.of())); + verify(user).sendMessage("parkour.errors.not-in-run"); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.QuitCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteSuccess() { + assertTrue(cmd.canExecute(user, "", List.of())); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.QuitCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + assertTrue(cmd.execute(user, "", List.of())); + verify(user).sendMessage("parkour.quit.success"); + assertTrue(prm.timers().isEmpty()); + assertTrue(prm.checkpoints().isEmpty()); + } } diff --git a/src/test/java/world/bentobox/parkour/commands/RemoveWarpCommandTest.java b/src/test/java/world/bentobox/parkour/commands/RemoveWarpCommandTest.java index 2eab589..d7e7a4d 100644 --- a/src/test/java/world/bentobox/parkour/commands/RemoveWarpCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/RemoveWarpCommandTest.java @@ -1,6 +1,9 @@ package world.bentobox.parkour.commands; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -14,30 +17,22 @@ import java.util.Optional; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -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.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.parkour.Parkour; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.Settings; @@ -46,133 +41,118 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) -public class RemoveWarpCommandTest { - @Mock - private BentoBox plugin; - @Mock - private CompositeCommand ac; - @Mock - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - private RemoveWarpCommand cmd; - @Mock - private ParkourManager parkourManager; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - BentoBox plugin = mock(BentoBox.class); - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // Player - Player p = mock(Player.class); - // Sometimes use Mockito.withSettings().verboseLogging() - when(user.isOp()).thenReturn(false); - when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); - when(user.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); - User.setPlugin(plugin); - - // Parent command has no aliases - when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); - when(ac.getWorld()).thenReturn(world); - when(ac.getAddon()).thenReturn(addon); - - // Islands - when(plugin.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // Warp spot available by default - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.of(mock(Location.class))); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock."); - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // DUT - cmd = new RemoveWarpCommand(ac); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#RemoveWarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. - */ - @Test - public void testRemoveWarpCommand() { - assertNotNull(cmd); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#setup()}. - */ - @Test - public void testSetup() { - assertEquals("removewarp", cmd.getPermission()); - assertEquals("parkour.commands.parkour.removewarp.description", cmd.getDescription()); - assertTrue(cmd.isConfigurableRankCommand()); - assertTrue(cmd.isOnlyPlayer()); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteFailHelp() { - // Help - assertFalse(cmd.canExecute(user, "", List.of("something"))); - verify(user).sendMessage("commands.help.header","[label]",null); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteFailNoRank() { - // Insufficient rank - assertFalse(cmd.canExecute(user, "", List.of())); - verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); - - } - - /** +public class RemoveWarpCommandTest extends AbstractParkourTest { + @Mock + private CompositeCommand ac; + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + private RemoveWarpCommand cmd; + @Mock + private ParkourManager parkourManager; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + when(user.isOp()).thenReturn(false); + when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); + when(user.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + User.setPlugin(plugin); + + // Parent command has no aliases + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ac.getWorld()).thenReturn(world); + when(ac.getAddon()).thenReturn(addon); + + // Islands + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // Warp spot available by default + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.of(mock(Location.class))); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock."); + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // DUT + cmd = new RemoveWarpCommand(ac); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.RemoveWarpCommand#RemoveWarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. + */ + @Test + public void testRemoveWarpCommand() { + assertNotNull(cmd); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.RemoveWarpCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("removewarp", cmd.getPermission()); + assertEquals("parkour.commands.parkour.removewarp.description", cmd.getDescription()); + assertTrue(cmd.isConfigurableRankCommand()); + assertTrue(cmd.isOnlyPlayer()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteFailHelp() { + // Help + assertFalse(cmd.canExecute(user, "", List.of("something"))); + verify(user).sendMessage("commands.help.header", "[label]", null); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteFailNoRank() { + // Insufficient rank + assertFalse(cmd.canExecute(user, "", List.of())); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); + + } + + /** * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -185,7 +165,7 @@ public void testCanExecuteFailNoWarpSpot() { } - /** + /** * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -196,18 +176,19 @@ public void testCanExecutePass() { verify(user, never()).sendMessage(any()); } - /** - * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfString() { - assertTrue(cmd.execute(user, "", List.of())); - verify(user).sendMessage("parkour.warp.removed"); - verify(parkourManager).setWarpSpot(island, null); + /** + * Test method for + * {@link world.bentobox.parkour.commands.RemoveWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + assertTrue(cmd.execute(user, "", List.of())); + verify(user).sendMessage("parkour.warp.removed"); + verify(parkourManager).setWarpSpot(island, null); - } + } - /** + /** * Test method for {@link world.bentobox.parkour.commands.RemoveWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test diff --git a/src/test/java/world/bentobox/parkour/commands/SetWarpCommandTest.java b/src/test/java/world/bentobox/parkour/commands/SetWarpCommandTest.java index 74e3f69..8dc45f4 100644 --- a/src/test/java/world/bentobox/parkour/commands/SetWarpCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/SetWarpCommandTest.java @@ -17,159 +17,141 @@ import java.util.Optional; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; 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.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.parkour.Parkour; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.Settings; /** * Set warp command testd + * * @author tastybento * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) -public class SetWarpCommandTest { +@PrepareForTest(RanksManager.class) +public class SetWarpCommandTest extends AbstractParkourTest { + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + private SetWarpCommand cmd; + @Mock + private ParkourManager parkourManager; + @Mock + private Location location; + @Mock + private CompositeCommand ac; @Mock - private BentoBox plugin; - @Mock - private CompositeCommand ac; - @Mock - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - private SetWarpCommand cmd; - @Mock - private ParkourManager parkourManager; - @Mock - private Location location; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // Player - Player p = mock(Player.class); - // Sometimes use Mockito.withSettings().verboseLogging() - when(user.isOp()).thenReturn(false); - when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); - when(user.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); - User.setPlugin(plugin); - - // Parent command has no aliases - when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); - when(ac.getWorld()).thenReturn(world); - when(ac.getAddon()).thenReturn(addon); - - // Islands - when(plugin.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // No warp spot - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); - // Start and end plates are set - when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); - when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // DUT - cmd = new SetWarpCommand(ac); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#SetWarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. - */ - @Test - public void testSetWarpCommand() { - assertNotNull(cmd); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#setup()}. - */ - @Test - public void testSetup() { - assertEquals("setwarp", cmd.getPermission()); - assertEquals("parkour.commands.parkour.setwarp.description", cmd.getDescription()); - assertTrue(cmd.isConfigurableRankCommand()); - assertTrue(cmd.isOnlyPlayer()); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteFailHelp() { - // Help - assertFalse(cmd.canExecute(user, "", List.of("something"))); - verify(user).sendMessage("commands.help.header","[label]",null); - } - - /** + private RanksManager rm; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + when(user.isOp()).thenReturn(false); + when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); + when(user.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + User.setPlugin(plugin); + + // Parent command has no aliases + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ac.getWorld()).thenReturn(world); + when(ac.getAddon()).thenReturn(addon); + + // Islands + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // No warp spot + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); + // Start and end plates are set + when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); + when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // DUT + cmd = new SetWarpCommand(ac); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.SetWarpCommand#SetWarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. + */ + @Test + public void testSetWarpCommand() { + assertNotNull(cmd); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.SetWarpCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("setwarp", cmd.getPermission()); + assertEquals("parkour.commands.parkour.setwarp.description", cmd.getDescription()); + assertTrue(cmd.isConfigurableRankCommand()); + assertTrue(cmd.isOnlyPlayer()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteFailHelp() { + // Help + assertFalse(cmd.canExecute(user, "", List.of("something"))); + verify(user).sendMessage("commands.help.header", "[label]", null); + } + + /** * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -180,18 +162,19 @@ public void testCanExecuteFailNoIsland() { verify(user).sendMessage("parkour.errors.not-on-island"); } - /** - * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteFailNoRank() { - // Insufficient rank - assertFalse(cmd.canExecute(user, "", List.of())); - verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); + /** + * Test method for + * {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteFailNoRank() { + // Insufficient rank + assertFalse(cmd.canExecute(user, "", List.of())); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); - } + } - /** + /** * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -209,7 +192,7 @@ public void testCanExecuteNoStartEndPlates() { verify(user).notify("parkour.no-end-yet"); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -220,18 +203,19 @@ public void testCanExecutePass() { verify(user, never()).sendMessage(any()); } - /** - * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfString() { - assertTrue(cmd.execute(user, "", List.of())); - verify(user).sendMessage("parkour.warp.set"); - verify(parkourManager).setWarpSpot(island, null); + /** + * Test method for + * {@link world.bentobox.parkour.commands.SetWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + assertTrue(cmd.execute(user, "", List.of())); + verify(user).sendMessage("parkour.warp.set"); + verify(parkourManager).setWarpSpot(island, null); - } + } - /** + /** * Test method for {@link world.bentobox.parkour.commands.SetWarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test diff --git a/src/test/java/world/bentobox/parkour/commands/TopCommandTest.java b/src/test/java/world/bentobox/parkour/commands/TopCommandTest.java index 3c97e7a..bf7a032 100644 --- a/src/test/java/world/bentobox/parkour/commands/TopCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/TopCommandTest.java @@ -16,30 +16,22 @@ import java.util.Optional; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -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.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.parkour.Parkour; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.Settings; import world.bentobox.parkour.gui.RankingsUI; @@ -49,119 +41,102 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) -public class TopCommandTest { - @Mock - private BentoBox plugin; - @Mock - private CompositeCommand ac; - @Mock - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - @Mock - private ParkourManager parkourManager; - - private TopCommand cmd; - @Mock - private @NonNull Location location; - @Mock - private RankingsUI rankings; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // Player - Player p = mock(Player.class); - // Sometimes use Mockito.withSettings().verboseLogging() - when(user.isOp()).thenReturn(false); - when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); - when(user.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - when(user.getLocation()).thenReturn(location); - when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); - User.setPlugin(plugin); - - // Parent command has no aliases - when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); - when(ac.getWorld()).thenReturn(world); - when(ac.getAddon()).thenReturn(addon); - when(addon.getRankings()).thenReturn(rankings); - - // Islands - when(plugin.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.getIslandAt(location)).thenReturn(Optional.of(island)); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // No warp spot - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); - when(iwm.inWorld(world)).thenReturn(true); - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // DUT - cmd = new TopCommand(ac); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.TopCommand#TopCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. - */ - @Test - public void testTopCommand() { - assertNotNull(cmd); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.TopCommand#setup()}. - */ - @Test - public void testSetup() { - assertEquals("top", cmd.getPermission()); - assertEquals("parkour.commands.parkour.top.description", cmd.getDescription()); - assertTrue(cmd.isOnlyPlayer()); - } - - /** +public class TopCommandTest extends AbstractParkourTest { + @Mock + private CompositeCommand ac; + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + @Mock + private ParkourManager parkourManager; + + private TopCommand cmd; + @Mock + private @NonNull Location location; + @Mock + private RankingsUI rankings; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + when(user.isOp()).thenReturn(false); + when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); + when(user.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + when(user.getLocation()).thenReturn(location); + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + User.setPlugin(plugin); + + // Parent command has no aliases + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ac.getWorld()).thenReturn(world); + when(ac.getAddon()).thenReturn(addon); + when(addon.getRankings()).thenReturn(rankings); + + // Islands + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.getIslandAt(location)).thenReturn(Optional.of(island)); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // No warp spot + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); + when(iwm.inWorld(world)).thenReturn(true); + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // DUT + cmd = new TopCommand(ac); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.TopCommand#TopCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. + */ + @Test + public void testTopCommand() { + assertNotNull(cmd); + } + + /** + * Test method for {@link world.bentobox.parkour.commands.TopCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("top", cmd.getPermission()); + assertEquals("parkour.commands.parkour.top.description", cmd.getDescription()); + assertTrue(cmd.isOnlyPlayer()); + } + + /** * Test method for {@link world.bentobox.parkour.commands.TopCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -172,8 +147,7 @@ public void testCanExecuteFailNotOnIsland() { verify(user).sendMessage("parkour.errors.not-on-island"); } - - /** + /** * Test method for {@link world.bentobox.parkour.commands.TopCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -183,22 +157,24 @@ public void testCanExecuteFailWrongWorld() { verify(user).sendMessage("general.errors.wrong-world"); } - /** - * Test method for {@link world.bentobox.parkour.commands.TopCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecutePass() { - assertTrue(cmd.canExecute(user, "", List.of())); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.TopCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfString() { - testCanExecutePass(); - assertTrue(cmd.execute(user, "", List.of())); - verify(rankings).getGUI(island, user); - } + /** + * Test method for + * {@link world.bentobox.parkour.commands.TopCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecutePass() { + assertTrue(cmd.canExecute(user, "", List.of())); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.TopCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + testCanExecutePass(); + assertTrue(cmd.execute(user, "", List.of())); + verify(rankings).getGUI(island, user); + } } diff --git a/src/test/java/world/bentobox/parkour/commands/WarpCommandTest.java b/src/test/java/world/bentobox/parkour/commands/WarpCommandTest.java index a70afc4..45a5ed5 100644 --- a/src/test/java/world/bentobox/parkour/commands/WarpCommandTest.java +++ b/src/test/java/world/bentobox/parkour/commands/WarpCommandTest.java @@ -25,30 +25,22 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; 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 world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; -import world.bentobox.parkour.Parkour; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.Settings; @@ -57,152 +49,140 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class, Util.class}) -public class WarpCommandTest { - - @Mock - private BentoBox plugin; - @Mock - private CompositeCommand ac; - @Mock - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - private WarpCommand cmd; - @Mock - private ParkourManager parkourManager; - @Mock - private Location location; - @Mock - private @NonNull Player p; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Command manager - CommandsManager cm = mock(CommandsManager.class); - when(plugin.getCommandsManager()).thenReturn(cm); - - // User - when(user.isOp()).thenReturn(false); - when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); - when(user.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(user.getUniqueId()).thenReturn(uuid); - when(user.getPlayer()).thenReturn(p); - when(user.getName()).thenReturn("tastybento"); - when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); - when(user.getLocation()).thenReturn(location); - User.setPlugin(plugin); - - // Parent command has no aliases - when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); - when(ac.getWorld()).thenReturn(world); - when(ac.getAddon()).thenReturn(addon); - - // Islands - when(plugin.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // No warp spot - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); - // Start and end plates are set - when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); - when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); - - // World - when(addon.inWorld(world)).thenReturn(true); - - // Location - when(location.clone()).thenReturn(location); - when(location.add(any(Vector.class))).thenReturn(location); - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // Static classes : Bukkit, Util - PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); - PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS); - when(Util.tabLimit(any(), any())).thenCallRealMethod(); - // DUT - cmd = new WarpCommand(ac); - } - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#WarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. - */ - @Test - public void testWarpCommand() { - assertNotNull(cmd); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#setup()}. - */ - @Test - public void testSetup() { - assertEquals("warp", cmd.getPermission()); - assertEquals("parkour.commands.parkour.warp.description", cmd.getDescription()); - assertEquals("parkour.commands.parkour.warp.parameters", cmd.getParameters()); - assertTrue(cmd.isOnlyPlayer()); - - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteHelp() { - assertFalse(cmd.canExecute(user, "", List.of("more","than","one"))); - verify(user).sendMessage("commands.help.header","[label]",null); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteNoArgNotOnParkourIsland() { - assertFalse(cmd.canExecute(user, "", List.of())); - // On island, but not in world - when(im.getIslandAt(location)).thenReturn(Optional.of(island)); - when(addon.inWorld(world)).thenReturn(false); - assertFalse(cmd.canExecute(user, "", List.of())); - verify(user, times(2)).sendMessage("parkour.errors.not-on-island"); - verify(user, times(2)).sendMessage("commands.help.header","[label]",null); - } - - /** +public class WarpCommandTest extends AbstractParkourTest { + + @Mock + private CompositeCommand ac; + @Mock + private User user; + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + @Mock + private WarpCommand cmd; + @Mock + private ParkourManager parkourManager; + @Mock + private Location location; + @Mock + private @NonNull Player p; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // User + when(user.isOp()).thenReturn(false); + when(user.getPermissionValue(anyString(), anyInt())).thenReturn(4); + when(user.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + when(user.getLocation()).thenReturn(location); + User.setPlugin(plugin); + + // Parent command has no aliases + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ac.getWorld()).thenReturn(world); + when(ac.getAddon()).thenReturn(addon); + + // Islands + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // No warp spot + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); + // Start and end plates are set + when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); + when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); + + // World + when(addon.inWorld(world)).thenReturn(true); + + // Location + when(location.clone()).thenReturn(location); + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // Static classes : Bukkit, Util + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS); + when(Util.tabLimit(any(), any())).thenCallRealMethod(); + // DUT + cmd = new WarpCommand(ac); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#WarpCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}. + */ + @Test + public void testWarpCommand() { + assertNotNull(cmd); + } + + /** + * Test method for {@link world.bentobox.parkour.commands.WarpCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("warp", cmd.getPermission()); + assertEquals("parkour.commands.parkour.warp.description", cmd.getDescription()); + assertEquals("parkour.commands.parkour.warp.parameters", cmd.getParameters()); + assertTrue(cmd.isOnlyPlayer()); + + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteHelp() { + assertFalse(cmd.canExecute(user, "", List.of("more", "than", "one"))); + verify(user).sendMessage("commands.help.header", "[label]", null); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteNoArgNotOnParkourIsland() { + assertFalse(cmd.canExecute(user, "", List.of())); + // On island, but not in world + when(im.getIslandAt(location)).thenReturn(Optional.of(island)); + when(addon.inWorld(world)).thenReturn(false); + assertFalse(cmd.canExecute(user, "", List.of())); + verify(user, times(2)).sendMessage("parkour.errors.not-on-island"); + verify(user, times(2)).sendMessage("commands.help.header", "[label]", null); + } + + /** * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -214,7 +194,7 @@ public void testCanExecuteNoArgOnIslandNoWarp() { verify(user, never()).sendMessage("commands.help.header","[label]",null); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -225,7 +205,7 @@ public void testCanExecuteNoArgSuccess() { verify(user, never()).sendMessage(any()); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -235,7 +215,7 @@ public void testCanExecuteArgNoWarps() { verify(user).sendMessage("parkour.warp.unknown-course"); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -245,7 +225,7 @@ public void testCanExecuteArgDifferentPlayer() { verify(user).sendMessage("parkour.warp.unknown-course"); } - /** + /** * Test method for {@link world.bentobox.parkour.commands.WarpCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test @@ -255,73 +235,76 @@ public void testCanExecuteArgMixedCase() { verify(user, never()).sendMessage(any()); } - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfString() { - // Set warpspot - testCanExecuteArgMixedCase(); - // Run test - assertTrue(cmd.execute(user, "", List.of())); - verify(user).sendMessage("parkour.warp.warping"); - // Teleport user - verify(p, times(2)).playSound(location, Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); - verify(location).add(any(Vector.class)); - PowerMockito.verifyStatic(Util.class); - Util.teleportAsync(p, location, TeleportCause.COMMAND); - - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testTabCompleteUserStringListOfString() { - assertTrue(cmd.tabComplete(user, "", List.of("ta")).get().isEmpty()); - when(parkourManager.getWarps()).thenReturn(Map.of("tAsTyBeNtO", location)); - List list = cmd.tabComplete(user, "", List.of("ta")).get(); - assertEquals("tAsTyBeNtO", list.get(0)); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testTabCompleteUserStringListOfStringEmpty() { - assertTrue(cmd.tabComplete(user, "", List.of()).get().isEmpty()); - when(parkourManager.getWarps()).thenReturn(Map.of("tAsTyBeNtO", location)); - List list = cmd.tabComplete(user, "", List.of("ta")).get(); - assertEquals("tAsTyBeNtO", list.get(0)); - } - - /** - * Test method for {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testTabCompleteUserStringListOfString10OptionsEmpty() { - assertTrue(cmd.tabComplete(user, "", List.of("ta")).get().isEmpty()); - Map map = new HashMap<>(); - map.put("tAsTyBeNtO1", location); - map.put("tAsTyBeNtO2", location); - map.put("tAsTyBeNtO3", location); - map.put("tAsTyBeNtO4", location); - map.put("tAsTyBeNtO5", location); - map.put("tAsTyBeNtO6", location); - map.put("tAsTyBeNtO7", location); - map.put("tAsTyBeNtO8", location); - map.put("tAsTyBeNtO9", location); - map.put("tAsTyBeNtO10", location); - when(parkourManager.getWarps()).thenReturn(map); - Optional> list = cmd.tabComplete(user, "", List.of()); - assertTrue(list.isEmpty()); - // Try again - list = cmd.tabComplete(user, "", List.of("tA")); - assertEquals(10, list.get().size()); - // Try again - list = cmd.tabComplete(user, "", List.of("p")); - assertTrue(list.get().isEmpty()); // Zero length list - - } + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + // Set warpspot + testCanExecuteArgMixedCase(); + // Run test + assertTrue(cmd.execute(user, "", List.of())); + verify(user).sendMessage("parkour.warp.warping"); + // Teleport user + verify(p, times(2)).playSound(location, Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); + PowerMockito.verifyStatic(Util.class); + Util.teleportAsync(p, location, TeleportCause.COMMAND); + + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfString() { + assertTrue(cmd.tabComplete(user, "", List.of("ta")).get().isEmpty()); + when(parkourManager.getWarps()).thenReturn(Map.of("tAsTyBeNtO", location)); + List list = cmd.tabComplete(user, "", List.of("ta")).get(); + assertEquals("tAsTyBeNtO", list.get(0)); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfStringEmpty() { + assertTrue(cmd.tabComplete(user, "", List.of()).get().isEmpty()); + when(parkourManager.getWarps()).thenReturn(Map.of("tAsTyBeNtO", location)); + List list = cmd.tabComplete(user, "", List.of("ta")).get(); + assertEquals("tAsTyBeNtO", list.get(0)); + } + + /** + * Test method for + * {@link world.bentobox.parkour.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfString10OptionsEmpty() { + assertTrue(cmd.tabComplete(user, "", List.of("ta")).get().isEmpty()); + Map map = new HashMap<>(); + map.put("tAsTyBeNtO1", location); + map.put("tAsTyBeNtO2", location); + map.put("tAsTyBeNtO3", location); + map.put("tAsTyBeNtO4", location); + map.put("tAsTyBeNtO5", location); + map.put("tAsTyBeNtO6", location); + map.put("tAsTyBeNtO7", location); + map.put("tAsTyBeNtO8", location); + map.put("tAsTyBeNtO9", location); + map.put("tAsTyBeNtO10", location); + when(parkourManager.getWarps()).thenReturn(map); + Optional> list = cmd.tabComplete(user, "", List.of()); + assertTrue(list.isEmpty()); + // Try again + list = cmd.tabComplete(user, "", List.of("tA")); + assertEquals(10, list.get().size()); + // Try again + list = cmd.tabComplete(user, "", List.of("p")); + assertTrue(list.get().isEmpty()); // Zero length list + + } } diff --git a/src/test/java/world/bentobox/parkour/listeners/CourseRunnerListenerTest.java b/src/test/java/world/bentobox/parkour/listeners/CourseRunnerListenerTest.java index c486435..8c05df3 100644 --- a/src/test/java/world/bentobox/parkour/listeners/CourseRunnerListenerTest.java +++ b/src/test/java/world/bentobox/parkour/listeners/CourseRunnerListenerTest.java @@ -1,5 +1,6 @@ package world.bentobox.parkour.listeners; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -8,6 +9,8 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.RETURNS_MOCKS; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -20,7 +23,6 @@ import java.util.Optional; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.EntityEffect; import org.bukkit.GameMode; import org.bukkit.Location; @@ -32,6 +34,7 @@ import org.bukkit.block.BlockFace; import org.bukkit.entity.Creeper; import org.bukkit.entity.Player; +import org.bukkit.entity.Player.Spigot; import org.bukkit.event.block.Action; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; @@ -43,18 +46,16 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.stubbing.Answer; -import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.api.mockito.PowerMockito; import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import world.bentobox.bentobox.BentoBox; +import net.md_5.bungee.api.chat.TextComponent; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.island.IslandEnterEvent; import world.bentobox.bentobox.api.events.island.IslandExitEvent; @@ -62,181 +63,167 @@ import world.bentobox.bentobox.api.user.Notifier; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.PlaceholdersManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.parkour.Parkour; +import world.bentobox.bentobox.util.Util; +import world.bentobox.parkour.AbstractParkourTest; import world.bentobox.parkour.ParkourManager; import world.bentobox.parkour.ParkourRunRecord; import world.bentobox.parkour.Settings; /** * @author tastybento - * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) -public class CourseRunnerListenerTest { - - @Mock - private BentoBox plugin; - private User user; - @Mock - private LocalesManager lm; - @Mock - private Parkour addon; - private UUID uuid; - @Mock - private World world; - @Mock - private IslandsManager im; - @Mock - private @Nullable Island island; - @Mock - private IslandWorldManager iwm; - @Mock - private ParkourManager parkourManager; - - private CourseRunnerListener crl; - @Mock - private @NonNull Location location; - // Not mock - private ParkourRunRecord prm; - @Mock - private Player player; - @Mock - private PlaceholdersManager phm; - @Mock - private Notifier notifier; - @Mock - private Server server; +public class CourseRunnerListenerTest extends AbstractParkourTest { + private User user; + @Mock + private LocalesManager lm; + private UUID uuid; + @Mock + private World world; + @Mock + private ParkourManager parkourManager; + + private CourseRunnerListener crl; + @Mock + private @NonNull Location location; + // Not mock + private ParkourRunRecord prm; + @Mock + private Player player; + @Mock + private PlaceholdersManager phm; + @Mock + private Notifier notifier; + @Mock + private Server server; + @Mock + private CompositeCommand cc; + @Mock + private Block block; + @Mock + private User u; @Mock - private CompositeCommand cc; - @Mock - private Block block; - @Mock - private User u; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // Player - when(player.getWorld()).thenReturn(world); - uuid = UUID.randomUUID(); - when(player.getUniqueId()).thenReturn(uuid); - when(player.getName()).thenReturn("tastybento"); - when(player.getLocation()).thenReturn(location); - when(player.isOnline()).thenReturn(true); - when(player.hasPermission(anyString())).thenReturn(false); - when(player.getGameMode()).thenReturn(GameMode.SURVIVAL); - when(player.getServer()).thenReturn(server); - User.setPlugin(plugin); - user = User.getInstance(player); - - // Mock user u - when(u.getUniqueId()).thenReturn(uuid); - when(u.getPlayer()).thenReturn(player); - when(u.getTranslationOrNothing(anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); - - // Islands - when(plugin.getIslands()).thenReturn(im); - when(addon.getIslands()).thenReturn(im); - when(im.getIsland(world, user)).thenReturn(island); - when(im.getIslandAt(location)).thenReturn(Optional.of(island)); - when(im.getProtectedIslandAt(location)).thenReturn(Optional.of(island)); - when(im.hasIsland(world, user)).thenReturn(true); - when(im.inTeam(world, uuid)).thenReturn(true); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); - when(island.getWorld()).thenReturn(world); - when(im.userIsOnIsland(any(), any())).thenReturn(true); - - // Parkour Manager - // No warp spot - when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); - when(addon.getParkourManager()).thenReturn(parkourManager); - - // Notifier - when(plugin.getNotifier()).thenReturn(notifier); - - // Locales Manager - when(plugin.getLocalesManager()).thenReturn(lm); - when(lm.get(anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); - when(phm.replacePlaceholders(any(), any())).thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class)); - when(plugin.getPlaceholdersManager()).thenReturn(phm); - - // Command - List al = new ArrayList<>(); - al.add("parkour"); - al.add("pk"); - when(cc.getAliases()).thenReturn(al); - when(addon.getPlayerCommand()).thenReturn(Optional.of(cc)); - - // IWM - when(plugin.getIWM()).thenReturn(iwm); - when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); - when(iwm.inWorld(world)).thenReturn(true); // Always in world - - // Settings - Settings settings = new Settings(); - when(addon.getSettings()).thenReturn(settings); - - // Location - when(location.getWorld()).thenReturn(world); - when(location.toVector()).thenReturn(new Vector(0,0,0)); - - // Run Manager and ParkourManager - prm = new ParkourRunRecord(new HashMap<>(), new HashMap<>()); - when(addon.getParkourRunRecord()).thenReturn(prm); - when(addon.inWorld(location)).thenReturn(true); - when(addon.inWorld(world)).thenReturn(true); - when(addon.getParkourManager()).thenReturn(parkourManager); - when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); - when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); - - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // Block - when(block.getType()).thenReturn(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); - when(block.getLocation()).thenReturn(location); - // DUT - crl = new CourseRunnerListener(addon); - } - - @After - public void tearDown() { - User.clearUsers(); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#CourseRunnerListener(world.bentobox.parkour.Parkour)}. - */ - @Test - public void testCourseRunnerListener() { - assertNotNull(crl); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorArrive(world.bentobox.bentobox.api.events.island.IslandEnterEvent)}. - */ - @Test - public void testOnVisitorArrive() { - IslandEnterEvent e = new IslandEnterEvent(island, uuid, false, location, island, null); - crl.onVisitorArrive(e); - verify(notifier).notify(any(), eq("parkour.to-start")); - verify(player).setGameMode(GameMode.CREATIVE); - } - - /** + private Spigot spigot; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + // Player + when(player.getWorld()).thenReturn(world); + uuid = UUID.randomUUID(); + when(player.getUniqueId()).thenReturn(uuid); + when(player.getName()).thenReturn("tastybento"); + when(player.getLocation()).thenReturn(location); + when(player.isOnline()).thenReturn(true); + when(player.hasPermission(anyString())).thenReturn(false); + when(player.getGameMode()).thenReturn(GameMode.SURVIVAL); + when(player.getServer()).thenReturn(server); + when(player.spigot()).thenReturn(spigot); + User.setPlugin(plugin); + user = User.getInstance(player); + + // Mock user u + when(u.getUniqueId()).thenReturn(uuid); + when(u.getPlayer()).thenReturn(player); + when(u.getTranslationOrNothing(anyString())) + .thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + + // Islands + when(plugin.getIslands()).thenReturn(im); + when(addon.getIslands()).thenReturn(im); + when(im.getIsland(world, user)).thenReturn(island); + when(im.getIslandAt(location)).thenReturn(Optional.of(island)); + when(im.getProtectedIslandAt(location)).thenReturn(Optional.of(island)); + when(im.hasIsland(world, user)).thenReturn(true); + when(im.inTeam(world, uuid)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + when(island.getWorld()).thenReturn(world); + when(im.userIsOnIsland(any(), any())).thenReturn(true); + + // Parkour Manager + // No warp spot + when(parkourManager.getWarpSpot(island)).thenReturn(Optional.empty()); + when(addon.getParkourManager()).thenReturn(parkourManager); + + // Notifier + when(plugin.getNotifier()).thenReturn(notifier); + + // Locales Manager + when(plugin.getLocalesManager()).thenReturn(lm); + when(lm.get(anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + when(phm.replacePlaceholders(any(), any())) + .thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class)); + when(plugin.getPlaceholdersManager()).thenReturn(phm); + + // Command + List al = new ArrayList<>(); + al.add("parkour"); + al.add("pk"); + when(cc.getAliases()).thenReturn(al); + when(addon.getPlayerCommand()).thenReturn(Optional.of(cc)); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("parkour."); + when(iwm.inWorld(world)).thenReturn(true); // Always in world + + // Settings + Settings settings = new Settings(); + when(addon.getSettings()).thenReturn(settings); + + // Location + when(location.getWorld()).thenReturn(world); + when(location.toVector()).thenReturn(new Vector(0, 0, 0)); + when(location.clone()).thenReturn(location); + when(location.add(0.5, 0, 0.5)).thenReturn(location); + + // Run Manager and ParkourManager + prm = new ParkourRunRecord(new HashMap<>(), new HashMap<>(), new ArrayList<>()); + when(addon.getParkourRunRecord()).thenReturn(prm); + when(addon.inWorld(location)).thenReturn(true); + when(addon.inWorld(world)).thenReturn(true); + when(addon.getParkourManager()).thenReturn(parkourManager); + when(parkourManager.getStart(island)).thenReturn(Optional.of(location)); + when(parkourManager.getEnd(island)).thenReturn(Optional.of(location)); + + // Block + when(block.getType()).thenReturn(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); + when(block.getLocation()).thenReturn(location); + + // DUT + crl = new CourseRunnerListener(addon); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#CourseRunnerListener(world.bentobox.parkour.Parkour)}. + */ + @Test + public void testCourseRunnerListener() { + assertNotNull(crl); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorArrive(world.bentobox.bentobox.api.events.island.IslandEnterEvent)}. + */ + @Test + public void testOnVisitorArrive() { + IslandEnterEvent e = new IslandEnterEvent(island, uuid, false, location, island, null); + crl.onVisitorArrive(e); + verify(notifier).notify(any(), eq("parkour.to-start")); + verify(player).setGameMode(GameMode.CREATIVE); + } + + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorArrive(world.bentobox.bentobox.api.events.island.IslandEnterEvent)}. */ @Test @@ -248,30 +235,32 @@ public void testOnVisitorArriveOtherGame() { verify(player, never()).setGameMode(GameMode.CREATIVE); } - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorArrive(world.bentobox.bentobox.api.events.island.IslandEnterEvent)}. - */ - @Test - public void testOnVisitorArriveInRace() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - prm.checkpoints().put(uuid, location); - IslandEnterEvent e = new IslandEnterEvent(island, uuid, false, location, island, null); - crl.onVisitorArrive(e); - verify(notifier, never()).notify(any(), eq("parkour.to-start")); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorLeave(world.bentobox.bentobox.api.events.island.IslandExitEvent)}. - */ - @Test - public void testOnVisitorLeave() { - prm.checkpoints().put(uuid, location); - IslandExitEvent e = new IslandExitEvent(island, uuid, false, location, island, null); - crl.onVisitorLeave(e); - verify(notifier).notify(any(), eq("parkour.session-ended")); - } - - /** + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorArrive(world.bentobox.bentobox.api.events.island.IslandEnterEvent)}. + */ + @Test + public void testOnVisitorArriveInRace() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + prm.checkpoints().put(uuid, location); + IslandEnterEvent e = new IslandEnterEvent(island, uuid, false, location, island, null); + crl.onVisitorArrive(e); + verify(notifier, never()).notify(any(), eq("parkour.to-start")); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorLeave(world.bentobox.bentobox.api.events.island.IslandExitEvent)}. + */ + @Test + public void testOnVisitorLeave() { + prm.checkpoints().put(uuid, location); + IslandExitEvent e = new IslandExitEvent(island, uuid, false, location, island, null); + crl.onVisitorLeave(e); + verify(notifier).notify(any(), eq("parkour.session-ended")); + } + + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorLeave(world.bentobox.bentobox.api.events.island.IslandExitEvent)}. */ @Test @@ -283,146 +272,160 @@ public void testOnVisitorLeaveOffline() { verify(notifier, never()).notify(any(), eq("parkour.session-ended")); } - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorLeave(world.bentobox.bentobox.api.events.island.IslandExitEvent)}. - */ - @Test - public void testOnVisitorLeaveNotRuning() { - IslandExitEvent e = new IslandExitEvent(island, uuid, false, location, island, null); - crl.onVisitorLeave(e); - verify(notifier, never()).notify(any(), eq("parkour.session-ended")); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onPlayerDeath(org.bukkit.event.entity.PlayerDeathEvent)}. - */ - @Test - public void testOnPlayerDeath() { - PlayerDeathEvent e = new PlayerDeathEvent(player, new ArrayList<>(), 0, 0, 0, 0, ""); - crl.onPlayerDeath(e); - assertFalse(prm.timers().containsKey(uuid)); - assertFalse(prm.checkpoints().containsKey(uuid)); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onPlayerQuit(org.bukkit.event.player.PlayerQuitEvent)}. - */ - @Test - public void testOnPlayerQuit() { - PlayerQuitEvent e = new PlayerQuitEvent(player, ""); - crl.onPlayerQuit(e); - assertFalse(prm.timers().containsKey(uuid)); - assertFalse(prm.checkpoints().containsKey(uuid)); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. - */ - @Test - public void testOnVisitorFall() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - prm.checkpoints().put(uuid, location); - EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.VOID, 1D); - crl.onVisitorFall(e); - verify(player).playEffect(EntityEffect.ENTITY_POOF); - verify(player).setVelocity(new Vector(0, 0, 0)); - verify(player).setFallDistance(0); - verify(player).teleport(location); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. - */ - @Test - public void testOnVisitorFallNotVoid() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - prm.checkpoints().put(uuid, location); - EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.BLOCK_EXPLOSION, 1D); - crl.onVisitorFall(e); - verify(player, never()).playEffect(EntityEffect.ENTITY_POOF); - verify(player, never()).setVelocity(new Vector(0, 0, 0)); - verify(player, never()).setFallDistance(0); - verify(player, never()).teleport(location); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. - */ - @Test - public void testOnVisitorFallNotRunning() { - EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.VOID, 1D); - crl.onVisitorFall(e); - verify(player, never()).playEffect(EntityEffect.ENTITY_POOF); - verify(player, never()).setVelocity(new Vector(0, 0, 0)); - verify(player, never()).setFallDistance(0); - verify(player, never()).teleport(location); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. - */ - @Test - public void testOnVisitorFallNotPlayer() { - Creeper creeper = mock(Creeper.class); - EntityDamageEvent e = new EntityDamageEvent(creeper, DamageCause.VOID, 1D); - crl.onVisitorFall(e); - verify(creeper, never()).playEffect(EntityEffect.ENTITY_POOF); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. - */ - @Test - public void testOnVisitorCommand() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/island"); - crl.onVisitorCommand(e); - assertTrue(e.isCancelled()); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. - */ - @Test - public void testOnVisitorCommandNotRunning() { - PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/island"); - crl.onVisitorCommand(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. - */ - @Test - public void testOnVisitorCommandQuitting() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/pk quit"); - crl.onVisitorCommand(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. - */ - @Test - public void testOnVisitorCommandQuittingParkour() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/parkour quit"); - crl.onVisitorCommand(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onStartEndSet(org.bukkit.event.player.PlayerInteractEvent)}. - */ - @Test - public void testOnStartEndSet() { - PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); - crl.onStartEndSet(e); - verify(player).sendMessage("parkour.start"); - } - - /** + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorLeave(world.bentobox.bentobox.api.events.island.IslandExitEvent)}. + */ + @Test + public void testOnVisitorLeaveNotRuning() { + IslandExitEvent e = new IslandExitEvent(island, uuid, false, location, island, null); + crl.onVisitorLeave(e); + verify(notifier, never()).notify(any(), eq("parkour.session-ended")); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onPlayerDeath(org.bukkit.event.entity.PlayerDeathEvent)}. + */ + @Test + public void testOnPlayerDeath() { + PlayerDeathEvent e = new PlayerDeathEvent(player, null, null, 0, 0, 0, 0, null); + crl.onPlayerDeath(e); + assertFalse(prm.timers().containsKey(uuid)); + assertFalse(prm.checkpoints().containsKey(uuid)); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onPlayerQuit(org.bukkit.event.player.PlayerQuitEvent)}. + */ + @Test + public void testOnPlayerQuit() { + PlayerQuitEvent e = new PlayerQuitEvent(player, ""); + crl.onPlayerQuit(e); + assertFalse(prm.timers().containsKey(uuid)); + assertFalse(prm.checkpoints().containsKey(uuid)); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. + */ + @Test + public void testOnVisitorFall() { + PowerMockito.mockStatic(Util.class, RETURNS_MOCKS); + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + prm.checkpoints().put(uuid, location); + EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.VOID, null, 0); + crl.onVisitorFall(e); + verify(player).playEffect(EntityEffect.ENTITY_POOF); + verify(player).setVelocity(new Vector(0, 0, 0)); + verify(player).setFallDistance(0); + PowerMockito.verifyStatic(Util.class); + Util.teleportAsync(player, location, PlayerTeleportEvent.TeleportCause.PLUGIN); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. + */ + @Test + public void testOnVisitorFallNotVoid() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + prm.checkpoints().put(uuid, location); + EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.BLOCK_EXPLOSION, null, 0); + crl.onVisitorFall(e); + verify(player, never()).playEffect(EntityEffect.ENTITY_POOF); + verify(player, never()).setVelocity(new Vector(0, 0, 0)); + verify(player, never()).setFallDistance(0); + verify(player, never()).teleport(location); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. + */ + @Test + public void testOnVisitorFallNotRunning() { + EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.VOID, null, 1D); + crl.onVisitorFall(e); + verify(player, never()).playEffect(EntityEffect.ENTITY_POOF); + verify(player, never()).setVelocity(new Vector(0, 0, 0)); + verify(player, never()).setFallDistance(0); + verify(player, never()).teleport(location); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorFall(org.bukkit.event.entity.EntityDamageEvent)}. + */ + @Test + public void testOnVisitorFallNotPlayer() { + Creeper creeper = mock(Creeper.class); + EntityDamageEvent e = new EntityDamageEvent(creeper, DamageCause.VOID, null, 1D); + crl.onVisitorFall(e); + verify(creeper, never()).playEffect(EntityEffect.ENTITY_POOF); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. + */ + @Test + public void testOnVisitorCommand() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/island"); + crl.onVisitorCommand(e); + assertTrue(e.isCancelled()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. + */ + @Test + public void testOnVisitorCommandNotRunning() { + PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/island"); + crl.onVisitorCommand(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. + */ + @Test + public void testOnVisitorCommandQuitting() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/pk quit"); + crl.onVisitorCommand(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onVisitorCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent)}. + */ + @Test + public void testOnVisitorCommandQuittingParkour() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/parkour quit"); + crl.onVisitorCommand(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onStartEndSet(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnStartEndSet() { + PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); + crl.onStartEndSet(e); + checkSpigotMessage("parkour.start"); + } + + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onStartEndSet(org.bukkit.event.player.PlayerInteractEvent)}. */ @Test @@ -430,58 +433,60 @@ public void testOnStartEndSetNoEnd() { when(this.parkourManager.getEnd(island)).thenReturn(Optional.empty()); PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); crl.onStartEndSet(e); - verify(player).sendMessage("parkour.set-the-end"); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onStartEndSet(org.bukkit.event.player.PlayerInteractEvent)}. - */ - @Test - public void testOnStartEndSetRaceOver() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - Location l = mock(Location.class); - when(l.getWorld()).thenReturn(world); - when(l.getBlockX()).thenReturn(20); - when(this.parkourManager.getStart(island)).thenReturn(Optional.of(l)); - PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); - crl.onStartEndSet(e); - verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourStart(User, Location)}. - */ - @Test - public void testParkourStart() { - crl.parkourStart(u, location); - verify(u).sendMessage("parkour.start"); - verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); - verify(u).setGameMode(GameMode.SURVIVAL); - - assertTrue(prm.checkpoints().containsKey(uuid)); - assertTrue(prm.timers().containsKey(uuid)); - - } - - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourEnd(User, Island, Location)}. - */ - @Test - public void testParkourEnd() { - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - - crl.parkourEnd(u, island, location); - verify(u).notify("parkour.end"); - verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); - verify(u).notify(eq("parkour.you-took"), eq(TextVariables.NUMBER), contains("parkour.seconds")); - verify(u).sendMessage("parkour.top.beat-previous-time"); - verify(parkourManager).addScore(eq(island), eq(u), anyLong()); - verify(u).sendMessage("parkour.top.your-rank", TextVariables.NUMBER, "0"); - verify(u).setGameMode(GameMode.CREATIVE); - } - - /** + checkSpigotMessage("parkour.set-the-end"); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onStartEndSet(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnStartEndSetRaceOver() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + Location l = mock(Location.class); + when(l.getWorld()).thenReturn(world); + when(l.getBlockX()).thenReturn(20); + when(this.parkourManager.getStart(island)).thenReturn(Optional.of(l)); + PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); + crl.onStartEndSet(e); + verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourStart(User, Location)}. + */ + @Test + public void testParkourStart() { + crl.parkourStart(u, location); + verify(u).sendMessage("parkour.start"); + verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); + verify(u).setGameMode(GameMode.SURVIVAL); + + assertTrue(prm.checkpoints().containsKey(uuid)); + assertTrue(prm.timers().containsKey(uuid)); + + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourEnd(User, Island, Location)}. + */ + @Test + public void testParkourEnd() { + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + + crl.parkourEnd(u, island, location); + verify(u).notify("parkour.end"); + verify(player).playSound(location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1F, 1F); + verify(u).notify(eq("parkour.you-took"), eq(TextVariables.NUMBER), contains("parkour.seconds")); + verify(u).sendMessage("parkour.top.beat-previous-time"); + verify(parkourManager).addScore(eq(island), eq(u), anyLong()); + verify(u).sendMessage("parkour.top.your-rank", TextVariables.NUMBER, "0"); + verify(u).setGameMode(GameMode.CREATIVE); + } + + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourEnd(User, Island, Location)}. */ @Test @@ -494,7 +499,7 @@ public void testParkourEndLongerTime() { verify(u).sendMessage("parkour.top.did-not-beat-previous-time"); } - /** + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#parkourEnd(User, Island, Location)}. */ @Test @@ -507,134 +512,185 @@ public void testParkourEndNoCreative() { verify(u, never()).setGameMode(GameMode.CREATIVE); } - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onCheckpoint(org.bukkit.event.player.PlayerInteractEvent)}. - */ - @Test - public void testOnCheckpointNotPhysical() { - PlayerInteractEvent e = new PlayerInteractEvent(player, Action.LEFT_CLICK_AIR, null, block, BlockFace.DOWN); - crl.onCheckpoint(e); - verify(block, never()).getLocation(); - } - - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onCheckpoint(org.bukkit.event.player.PlayerInteractEvent)}. - */ - @Test - public void testOnCheckpointInitialChecks() { - Location l = mock(Location.class); - when(l.toVector()).thenReturn(new Vector(100,0,20)); // Different to location - prm.checkpoints().put(uuid, l); - - when(block.getType()).thenReturn(Material.STONE); - - when(iwm.inWorld(location)).thenReturn(false); - - - PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); - crl.onCheckpoint(e); - verify(block, never()).getLocation(); - - when(iwm.inWorld(location)).thenReturn(true); - crl.onCheckpoint(e); - verify(block, never()).getLocation(); - - when(block.getType()).thenReturn(Material.POLISHED_BLACKSTONE_PRESSURE_PLATE); - crl.onCheckpoint(e); - verify(block, never()).getLocation(); - - prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago - crl.onCheckpoint(e); - verify(block).getLocation(); - - // Checkpoint reached! - verify(player).playSound(location, Sound.BLOCK_BELL_USE, 1F, 1F); - - } - - /** + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onCheckpoint(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCheckpointNotPhysical() { + PlayerInteractEvent e = new PlayerInteractEvent(player, Action.LEFT_CLICK_AIR, null, block, BlockFace.DOWN); + crl.onCheckpoint(e); + verify(block, never()).getLocation(); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onCheckpoint(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCheckpointInitialChecks() { + Location l = mock(Location.class); + when(l.toVector()).thenReturn(new Vector(100, 0, 20)); // Different to location + prm.checkpoints().put(uuid, l); + + when(block.getType()).thenReturn(Material.STONE); + + when(iwm.inWorld(location)).thenReturn(false); + + PlayerInteractEvent e = new PlayerInteractEvent(player, Action.PHYSICAL, null, block, BlockFace.DOWN); + crl.onCheckpoint(e); + verify(block, never()).getLocation(); + + when(iwm.inWorld(location)).thenReturn(true); + crl.onCheckpoint(e); + verify(block, never()).getLocation(); + + when(block.getType()).thenReturn(Material.POLISHED_BLACKSTONE_PRESSURE_PLATE); + crl.onCheckpoint(e); + verify(block, never()).getLocation(); + + prm.timers().put(uuid, System.currentTimeMillis() - 20000); // ~ 20 seconds ago + crl.onCheckpoint(e); + verify(block).getLocation(); + + // Checkpoint reached! + verify(player).playSound(location, Sound.BLOCK_BELL_USE, 1F, 1F); + + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. + */ + @Test + public void testOnTeleport() { + // Player is running + for (TeleportCause cause : TeleportCause.values()) { + // Reset the maps + prm.checkpoints().clear(); + prm.timers().clear(); + prm.checkpoints().put(uuid, location); + prm.timers().put(uuid, 20L); + // Make the event + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, location, cause); + // Fire event + crl.onTeleport(e); + } + // Should fire 5 times: COMMAND, PLUGIN, SPECTATE, END_GATEWAY, UNKNOWN + verify(notifier, times(5)).notify(any(), eq("parkour.session-ended")); + // Should happen just 3 times: COMMAND, PLUGIN, UNKNOWN + verify(player, times(3)).setGameMode(GameMode.CREATIVE); + verify(player, never()).setGameMode(GameMode.SURVIVAL); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. + */ + @Test + public void testOnTeleportNoFlagActionNullTo() { + // Make the event + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, null, TeleportCause.ENDER_PEARL); + // Fire event + crl.onTeleport(e); + verify(player, never()).setGameMode(GameMode.CREATIVE); + verify(player, never()).setGameMode(GameMode.SURVIVAL); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. + */ + @Test + public void testOnTeleportToNoFlagActionNotInParkourWorld() { + // Make the event + Location l = mock(Location.class); + when(l.getWorld()).thenReturn(mock(World.class)); + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, l, TeleportCause.PLUGIN); + // Fire event + crl.onTeleport(e); + verify(player, never()).setGameMode(GameMode.CREATIVE); + verify(player, never()).setGameMode(GameMode.SURVIVAL); + } + + /** + * Test method for + * {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. + */ + @Test + public void testOnTeleportToNoFlagActionDifferentIsland() { + // Make the event + Location l = mock(Location.class); + when(l.getWorld()).thenReturn(world); + Island i = mock(Island.class); + when(im.getIslandAt(l)).thenReturn(Optional.of(i)); + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, l, TeleportCause.PLUGIN); + // Fire event + crl.onTeleport(e); + verify(player, never()).setGameMode(GameMode.CREATIVE); + verify(player, never()).setGameMode(GameMode.SURVIVAL); + } + + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. */ @Test - public void testOnTeleport() { - // Player is running - for (TeleportCause cause : TeleportCause.values()) { - // Reset the maps - prm.checkpoints().clear(); - prm.timers().clear(); - prm.checkpoints().put(uuid, location); - prm.timers().put(uuid, 20L); - // Make the event - PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, location, cause); - // Fire event - crl.onTeleport(e); - } - // Should fire 7 times: COMMAND, PLUGIN, NETHER_PORTAL, END_PORTAL, SPECTATE, END_GATEWAY, UNKNOWN - verify(notifier, times(7)).notify(any(), eq("parkour.session-ended")); - verify(player, times(7)).setGameMode(GameMode.CREATIVE); - verify(player, never()).setGameMode(GameMode.SURVIVAL); - } + public void testOnTeleportToFlagActionVisitors() { + when(island.getFlag(any())).thenReturn(RanksManager.MEMBER_RANK); + when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. - */ - @Test - public void testOnTeleportNoFlagActionNullTo() { // Make the event - PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, null, TeleportCause.ENDER_PEARL); + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, location, TeleportCause.PLUGIN); // Fire event crl.onTeleport(e); verify(player, never()).setGameMode(GameMode.CREATIVE); - verify(player, never()).setGameMode(GameMode.SURVIVAL); + // Visitors should be set to survival when they teleport to the island. + verify(player).setGameMode(GameMode.SURVIVAL); } - /** + /** * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. */ @Test - public void testOnTeleportToNoFlagActionNotInParkourWorld() { - // Make the event - Location l = mock(Location.class); - when(l.getWorld()).thenReturn(mock(World.class)); - PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, l, TeleportCause.CHORUS_FRUIT); - // Fire event - crl.onTeleport(e); - verify(player, never()).setGameMode(GameMode.CREATIVE); - verify(player, never()).setGameMode(GameMode.SURVIVAL); - } + public void testOnTeleportToFlagActionVisitorsChorusFruit() { + when(island.getFlag(any())).thenReturn(RanksManager.MEMBER_RANK); + when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); - /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. - */ - @Test - public void testOnTeleportToNoFlagActionDifferentIsland() { // Make the event - Location l = mock(Location.class); - when(l.getWorld()).thenReturn(world); - Island i = mock(Island.class); - when(im.getIslandAt(l)).thenReturn(Optional.of(i)); - PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, l, TeleportCause.CHORUS_FRUIT); + PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, location, TeleportCause.CHORUS_FRUIT); // Fire event crl.onTeleport(e); + // Never alter the game mode verify(player, never()).setGameMode(GameMode.CREATIVE); verify(player, never()).setGameMode(GameMode.SURVIVAL); } /** - * Test method for {@link world.bentobox.parkour.listeners.CourseRunnerListener#onTeleport(org.bukkit.event.player.PlayerTeleportEvent)}. + * Check that spigot sent the message + * @param message - message to check */ - @Test - public void testOnTeleportToFlagActionVisitors() { - when(island.getFlag(any())).thenReturn(RanksManager.MEMBER_RANK); - when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); - // Make the event - PlayerTeleportEvent e = new PlayerTeleportEvent(player, location, location, TeleportCause.CHORUS_FRUIT); - // Fire event - crl.onTeleport(e); - verify(player, never()).setGameMode(GameMode.CREATIVE); - // Visitors should be set to survival when they teleport to the island. - verify(player).setGameMode(GameMode.SURVIVAL); + public void checkSpigotMessage(String expectedMessage) { + checkSpigotMessage(expectedMessage, 1); } + public void checkSpigotMessage(String expectedMessage, int expectedOccurrences) { + // Capture the argument passed to spigot().sendMessage(...) if messages are sent + ArgumentCaptor captor = ArgumentCaptor.forClass(TextComponent.class); + + // Verify that sendMessage() was called at least 0 times (capture any sent messages) + verify(spigot, atLeast(0)).sendMessage(captor.capture()); + + // Get all captured TextComponents + List capturedMessages = captor.getAllValues(); + + // Count the number of occurrences of the expectedMessage in the captured messages + long actualOccurrences = capturedMessages.stream().map(component -> component.toLegacyText()) // Convert each TextComponent to plain text + .filter(messageText -> messageText.contains(expectedMessage)) // Check if the message contains the expected text + .count(); // Count how many times the expected message appears + + // Assert that the number of occurrences matches the expectedOccurrences + assertEquals("Expected message occurrence mismatch: " + expectedMessage, expectedOccurrences, + actualOccurrences); + } } diff --git a/src/test/java/world/bentobox/parkour/mocks/ServerMocks.java b/src/test/java/world/bentobox/parkour/mocks/ServerMocks.java new file mode 100644 index 0000000..7f8b4b8 --- /dev/null +++ b/src/test/java/world/bentobox/parkour/mocks/ServerMocks.java @@ -0,0 +1,118 @@ +package world.bentobox.parkour.mocks; + +import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.Server; +import org.bukkit.Tag; +import org.bukkit.UnsafeValues; +import org.eclipse.jdt.annotation.NonNull; + +public final class ServerMocks { + + public static @NonNull Server newServer() { + Server mock = mock(Server.class); + + Logger noOp = mock(Logger.class); + when(mock.getLogger()).thenReturn(noOp); + when(mock.isPrimaryThread()).thenReturn(true); + + // Unsafe + UnsafeValues unsafe = mock(UnsafeValues.class); + when(mock.getUnsafe()).thenReturn(unsafe); + + // Server must be available before tags can be mocked. + Bukkit.setServer(mock); + + // Bukkit has a lot of static constants referencing registry values. To initialize those, the + // registries must be able to be fetched before the classes are touched. + Map, Object> registers = new HashMap<>(); + + doAnswer(invocationGetRegistry -> registers.computeIfAbsent(invocationGetRegistry.getArgument(0), clazz -> { + Registry registry = mock(Registry.class); + Map cache = new HashMap<>(); + doAnswer(invocationGetEntry -> { + NamespacedKey key = invocationGetEntry.getArgument(0); + // Some classes (like BlockType and ItemType) have extra generics that will be + // erased during runtime calls. To ensure accurate typing, grab the constant's field. + // This approach also allows us to return null for unsupported keys. + Class constantClazz; + try { + //noinspection unchecked + constantClazz = (Class) clazz + .getField(key.getKey().toUpperCase(Locale.ROOT).replace('.', '_')).getType(); + } catch (ClassCastException e) { + throw new RuntimeException(e); + } catch (NoSuchFieldException e) { + return null; + } + + return cache.computeIfAbsent(key, key1 -> { + Keyed keyed = mock(constantClazz); + doReturn(key).when(keyed).getKey(); + return keyed; + }); + }).when(registry).get(notNull()); + return registry; + })).when(mock).getRegistry(notNull()); + + // Tags are dependent on registries, but use a different method. + // This will set up blank tags for each constant; all that needs to be done to render them + // functional is to re-mock Tag#getValues. + doAnswer(invocationGetTag -> { + Tag tag = mock(Tag.class); + doReturn(invocationGetTag.getArgument(1)).when(tag).getKey(); + doReturn(Set.of()).when(tag).getValues(); + doAnswer(invocationIsTagged -> { + Keyed keyed = invocationIsTagged.getArgument(0); + Class type = invocationGetTag.getArgument(2); + if (!type.isAssignableFrom(keyed.getClass())) { + return null; + } + // Since these are mocks, the exact instance might not be equal. Consider equal keys equal. + return tag.getValues().contains(keyed) + || tag.getValues().stream().anyMatch(value -> value.getKey().equals(keyed.getKey())); + }).when(tag).isTagged(notNull()); + return tag; + }).when(mock).getTag(notNull(), notNull(), notNull()); + + // Once the server is all set up, touch BlockType and ItemType to initialize. + // This prevents issues when trying to access dependent methods from a Material constant. + try { + Class.forName("org.bukkit.inventory.ItemType"); + Class.forName("org.bukkit.block.BlockType"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + return mock; + } + + public static void unsetBukkitServer() { + try { + Field server = Bukkit.class.getDeclaredField("server"); + server.setAccessible(true); + server.set(null, null); + } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ServerMocks() { + } + +} \ No newline at end of file