diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b76061a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: java +sudo: false +addons: + sonarcloud: + organization: "bentobox-world" + token: + secure: $SONAR_TOKEN +jdk: + - openjdk8 + - openjdk11 + +matrix: + allow_failures: + - jdk: openjdk11 + +script: + mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=BentoBoxWorld_Warps + +cache: + directories: + - '$HOME/.m2/repository' + - '$HOME/.sonar/cache' diff --git a/pom.xml b/pom.xml index 9a5fb3b..f9d2ba1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,20 +1,20 @@ - 4.0.0 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - world.bentobox - warps + world.bentobox + warps ${revision} - WelcomeWarpSigns - WelcomeWarpSigns is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland. - https://github.com/BentoBoxWorld/addon-welcomewarpsigns - 2018 + WelcomeWarpSigns + WelcomeWarpSigns is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland. + https://github.com/BentoBoxWorld/addon-welcomewarpsigns + 2018 - + tastybento tastybento@bentobox.world -8 @@ -24,34 +24,34 @@ - - scm:git:https://github.com/BentoBoxWorld/addon-welcomewarpsigns.git - scm:git:git@github.com:BentoBoxWorld/addon-welcomewarpsigns.git - https://github.com/BentoBoxWorld/addon-welcomewarpsigns - + + scm:git:https://github.com/BentoBoxWorld/addon-welcomewarpsigns.git + scm:git:git@github.com:BentoBoxWorld/addon-welcomewarpsigns.git + https://github.com/BentoBoxWorld/addon-welcomewarpsigns + - - jenkins - http://ci.codemc.org/job/BentoBoxWorld/job/addon-welcomewarpsigns - + + jenkins + http://ci.codemc.org/job/BentoBoxWorld/job/addon-welcomewarpsigns + - - GitHub - https://github.com/BentoBoxWorld/addon-welcomewarpsigns/issues - + + GitHub + https://github.com/BentoBoxWorld/addon-welcomewarpsigns/issues + - - - codemc-snapshots - https://repo.codemc.org/repository/maven-snapshots - - - codemc-releases - https://repo.codemc.org/repository/maven-releases - - + + + codemc-snapshots + https://repo.codemc.org/repository/maven-snapshots + + + codemc-releases + https://repo.codemc.org/repository/maven-releases + + - + UTF-8 UTF-8 1.8 @@ -66,8 +66,8 @@ -LOCAL - 1.7.0 - + 1.8.1 + @@ -113,14 +113,14 @@ sonar https://sonarcloud.io - tastybento-github + bentobox-world org.sonarsource.scanner.maven sonar-maven-plugin - 3.4.1.1168 + 3.6.0.1398 verify @@ -135,22 +135,22 @@ - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots - - - codemc - https://repo.codemc.org/repository/maven-snapshots/ - - - codemc-public - https://repo.codemc.org/repository/maven-public/ - - + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots + + + codemc + https://repo.codemc.org/repository/maven-snapshots/ + + + codemc-public + https://repo.codemc.org/repository/maven-public/ + + - + org.spigotmc @@ -183,15 +183,24 @@ ${bentobox.version} provided - - world.bentobox - level - ${level.version} - provided - - + + world.bentobox + level + ${level.version} + provided + + + + + org.eclipse.jdt + org.eclipse.jdt.annotation + 2.2.200 + + - + @@ -202,18 +211,18 @@ be the empty string. --> ${project.name}-${revision}${build.number} - clean package - - - src/main/resources - true - - - src/main/resources/locales - ./locales - false - - + clean package + + + src/main/resources + true + + + src/main/resources/locales + ./locales + false + + org.apache.maven.plugins @@ -300,8 +309,8 @@ true - + **/*Names* @@ -321,5 +330,5 @@ - + \ No newline at end of file diff --git a/src/main/java/world/bentobox/warps/Warp.java b/src/main/java/world/bentobox/warps/Warp.java index 7919dc1..482fe79 100644 --- a/src/main/java/world/bentobox/warps/Warp.java +++ b/src/main/java/world/bentobox/warps/Warp.java @@ -18,7 +18,7 @@ import world.bentobox.warps.commands.WarpsCommand; import world.bentobox.warps.config.Settings; /** - * Addin to BSkyBlock that enables welcome warp signs + * Addin to BentoBox that enables welcome warp signs * @author tastybento * */ @@ -32,6 +32,11 @@ public class Warp extends Addon { */ private static final String LEVEL_ADDON_NAME = "Level"; + /** + * Permission prefix for non-game world operation + */ + public static final String WELCOME_WARP_SIGNS = "welcomewarpsigns"; + /** * Warp panel Manager */ @@ -78,7 +83,11 @@ public class Warp extends Addon { // Save default config.yml this.saveDefaultConfig(); // Load the plugin's config - this.loadSettings(); + if (this.loadSettings()) { + // Load the master warp and warps command + new WarpCommand(this); + new WarpsCommand(this); + } } @@ -111,16 +120,14 @@ public class Warp extends Addon { // Register commands this.getPlugin().getAddonsManager().getGameModeAddons().forEach(gameModeAddon -> { - if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName())) + if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName()) + && gameModeAddon.getPlayerCommand().isPresent()) { - if (gameModeAddon.getPlayerCommand().isPresent()) - { - this.registeredWorlds.add(gameModeAddon.getOverWorld()); + this.registeredWorlds.add(gameModeAddon.getOverWorld()); - new WarpCommand(this, gameModeAddon.getPlayerCommand().get()); - new WarpsCommand(this, gameModeAddon.getPlayerCommand().get()); - this.hooked = true; - } + new WarpCommand(this, gameModeAddon.getPlayerCommand().get()); + new WarpsCommand(this, gameModeAddon.getPlayerCommand().get()); + this.hooked = true; } }); @@ -130,7 +137,7 @@ public class Warp extends Addon { warpSignsManager = new WarpSignsManager(this, this.getPlugin()); warpPanelManager = new WarpPanelManager(this); // Load the listener - getServer().getPluginManager().registerEvents(new WarpSignsListener(this), this.getPlugin()); + this.registerListener(new WarpSignsListener(this)); } } @@ -146,7 +153,7 @@ public class Warp extends Addon { /** * This method loads addon configuration settings in memory. */ - private void loadSettings() { + private boolean loadSettings() { if (settingsConfig == null) { settingsConfig = new Config<>(this, Settings.class); } @@ -155,7 +162,10 @@ public class Warp extends Addon { // Disable this.logError("WelcomeWarp settings could not load! Addon disabled."); this.setState(State.DISABLED); + return false; } + settingsConfig.saveConfigObject(settings); + return true; } @@ -215,8 +225,8 @@ public class Warp extends Addon { // Parse keys if (metaData.containsKey("world")) { world = Bukkit.getWorld((String)metaData.get("world")); - if (world == null) return null; } + if (world == null) return null; if (metaData.containsKey("uuid")) { try { uuid = UUID.fromString((String)metaData.get("uuid")); @@ -229,11 +239,11 @@ public class Warp extends Addon { case "getSortedWarps": return getWarpSignsManager().getSortedWarps(world); case "getWarp": - return getWarpSignsManager().getWarp(world, uuid); + return uuid == null ? null : getWarpSignsManager().getWarp(world, uuid); case "getWarpMap": return getWarpSignsManager().getWarpMap(world); case "hasWarp": - return getWarpSignsManager().hasWarp(world, uuid); + return uuid == null ? null : getWarpSignsManager().hasWarp(world, uuid); case "listWarps": return getWarpSignsManager().listWarps(world); default: diff --git a/src/main/java/world/bentobox/warps/WarpPanelManager.java b/src/main/java/world/bentobox/warps/WarpPanelManager.java index d25ceef..236551a 100644 --- a/src/main/java/world/bentobox/warps/WarpPanelManager.java +++ b/src/main/java/world/bentobox/warps/WarpPanelManager.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.UUID; import org.bukkit.Material; @@ -30,14 +31,9 @@ public class WarpPanelManager { private PanelItem getPanelItem(World world, UUID warpOwner) { PanelItemBuilder pib = new PanelItemBuilder() - .name(addon.getPlugin().getPlayers().getName(warpOwner)) + .name(addon.getSettings().getNameFormat() + addon.getPlugin().getPlayers().getName(warpOwner)) .description(getSign(world, warpOwner)) - .clickHandler((panel, clicker, click, slot) -> { { - clicker.closeInventory(); - addon.getWarpSignsManager().warpPlayer(world, clicker, warpOwner); - return true; - } - }); + .clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner)); Material icon = getSignIcon(world, warpOwner); if (icon.equals(Material.PLAYER_HEAD)) { return pib.icon(addon.getPlayers().getName(warpOwner)).build(); @@ -46,6 +42,20 @@ public class WarpPanelManager { } } + private boolean hander(World world, User clicker, UUID warpOwner) { + clicker.closeInventory(); + addon.getWarpSignsManager().warpPlayer(world, clicker, warpOwner); + return true; + } + + private PanelItem getRandomButton(World world, User user, UUID warpOwner) { + ///give @p minecraft:player_head{display:{Name:"{\"text\":\"Question Mark\"}"},SkullOwner:"MHF_Question"} 1 + return new PanelItemBuilder() + .name(addon.getSettings().getNameFormat() + user.getTranslation("warps.random")) + .clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner)) + .icon(Material.END_CRYSTAL).build(); + } + private Material getSignIcon(World world, UUID warpOwner) { // Add the worlds if we haven't seen this before cachedSigns.putIfAbsent(world, new HashMap<>()); @@ -83,6 +93,12 @@ public class WarpPanelManager { */ public void showWarpPanel(World world, User user, int index) { List warps = new ArrayList<>(addon.getWarpSignsManager().getSortedWarps(world)); + UUID randomWarp = null; + // Add random UUID + if (!warps.isEmpty() && addon.getSettings().isRandomAllowed()) { + randomWarp = warps.get(new Random().nextInt(warps.size())); + warps.add(0, randomWarp); + } if (index < 0) { index = 0; } else if (index > (warps.size() / PANEL_MAX_SIZE)) { @@ -90,18 +106,22 @@ public class WarpPanelManager { } PanelBuilder panelBuilder = new PanelBuilder() .user(user) - .name(user.getTranslation("warps.title") + " " + String.valueOf(index + 1)); + .name(user.getTranslation("warps.title") + " " + (index + 1)); int i = index * PANEL_MAX_SIZE; for (; i < (index * PANEL_MAX_SIZE + PANEL_MAX_SIZE) && i < warps.size(); i++) { - panelBuilder.item(getPanelItem(world, warps.get(i))); + if (i == 0 && randomWarp != null) { + panelBuilder.item(getRandomButton(world, user, randomWarp)); + } else { + panelBuilder.item(getPanelItem(world, warps.get(i))); + } } final int panelNum = index; // Add signs if (i < warps.size()) { // Next panelBuilder.item(new PanelItemBuilder() - .name("Next") + .name(user.getTranslation("warps.next")) .icon(new ItemStack(Material.STONE)) .clickHandler((panel, clicker, click, slot) -> { user.closeInventory(); @@ -112,7 +132,7 @@ public class WarpPanelManager { if (i > PANEL_MAX_SIZE) { // Previous panelBuilder.item(new PanelItemBuilder() - .name("Previous") + .name(user.getTranslation("warps.previous")) .icon(new ItemStack(Material.COBBLESTONE)) .clickHandler((panel, clicker, click, slot) -> { user.closeInventory(); diff --git a/src/main/java/world/bentobox/warps/WarpSignsListener.java b/src/main/java/world/bentobox/warps/WarpSignsListener.java index 9e2bcd2..2ed72a3 100644 --- a/src/main/java/world/bentobox/warps/WarpSignsListener.java +++ b/src/main/java/world/bentobox/warps/WarpSignsListener.java @@ -6,8 +6,10 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.Sign; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -46,39 +48,41 @@ public class WarpSignsListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onSignBreak(BlockBreakEvent e) { Block b = e.getBlock(); + boolean inWorld = addon.getPlugin().getIWM().inWorld(b.getWorld()); // Signs only // FIXME: When we drop support for 1.13, switch to Tag.SIGNS - if (!e.getBlock().getType().name().contains("SIGN")) { - return; - } - if (!addon.inRegisteredWorld(b.getWorld())) { + if (!e.getBlock().getType().name().contains("SIGN") + || (inWorld && !addon.inRegisteredWorld(b.getWorld())) + || (!inWorld && !addon.getSettings().isAllowInOtherWorlds()) ) { return; } User user = User.getInstance(e.getPlayer()); - Sign s = (Sign) b.getState(); - if (s == null) { - return; - } - if (s.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { - // Do a quick check to see if this sign location is in - // the list of warp signs - Map list = addon.getWarpSignsManager().getWarpMap(b.getWorld()); - if (list.containsValue(s.getLocation())) { - // Welcome sign detected - check to see if it is - // this player's sign - if ((list.containsKey(user.getUniqueId()) && list.get(user.getUniqueId()).equals(s.getLocation())) - || user.isOp() || user.hasPermission(addon.getPermPrefix(e.getBlock().getWorld()) + "mod.removesign")) { - addon.getWarpSignsManager().removeWarp(s.getLocation()); - Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, s.getLocation(), user.getUniqueId())); - } else { - // Someone else's sign - not allowed - user.sendMessage("warps.error.no-remove"); - e.setCancelled(true); - } + if (isWarpSign(b)) { + if (isPlayersSign(e.getPlayer(), b, inWorld)) { + addon.getWarpSignsManager().removeWarp(b.getLocation()); + Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, b.getLocation(), user.getUniqueId())); + } else { + // Someone else's sign - not allowed + user.sendMessage("warps.error.no-remove"); + e.setCancelled(true); } } } + private boolean isPlayersSign(Player player, Block b, boolean inWorld) { + // Welcome sign detected - check to see if it is this player's sign + Map list = addon.getWarpSignsManager().getWarpMap(b.getWorld()); + String reqPerm = inWorld ? addon.getPermPrefix(b.getWorld()) + "mod.removesign" : Warp.WELCOME_WARP_SIGNS + ".mod.removesign"; + return ((list.containsKey(player.getUniqueId()) && list.get(player.getUniqueId()).equals(b.getLocation())) + || player.isOp() || player.hasPermission(reqPerm)); + } + + private boolean isWarpSign(Block b) { + Sign s = (Sign) b.getState(); + return s.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine()) + && addon.getWarpSignsManager().getWarpMap(b.getWorld()).containsValue(s.getLocation()); + } + /** * Event handler for Sign Changes * @@ -87,7 +91,8 @@ public class WarpSignsListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onSignWarpCreate(SignChangeEvent e) { Block b = e.getBlock(); - if (!addon.inRegisteredWorld(b.getWorld())) { + boolean inWorld = addon.getPlugin().getIWM().inWorld(b.getWorld()); + if ((inWorld && !addon.inRegisteredWorld(b.getWorld())) || (!inWorld && !addon.getSettings().isAllowInOtherWorlds()) ) { return; } String title = e.getLine(0); @@ -95,24 +100,10 @@ public class WarpSignsListener implements Listener { // Check if someone is changing their own sign if (title.equalsIgnoreCase(addon.getSettings().getWelcomeLine())) { // Welcome sign detected - check permissions - if (!(user.hasPermission(addon.getPermPrefix(b.getWorld()) + "island.addwarp"))) { - user.sendMessage("warps.error.no-permission"); - user.sendMessage("general.errors.no-permission", "[permission]", addon.getPermPrefix(b.getWorld()) + "island.addwarp"); + if (noPerms(user, b.getWorld(), inWorld)) { return; } - // Get level if level addon is available - Long level = addon.getLevel(Util.getWorld(b.getWorld()), user.getUniqueId()); - if (level != null && level < addon.getSettings().getWarpLevelRestriction()) { - user.sendMessage("warps.error.not-enough-level"); - user.sendMessage("warps.error.your-level-is", - "[level]", String.valueOf(level), - "[required]", String.valueOf(addon.getSettings().getWarpLevelRestriction())); - return; - } - - // Check that the player is on their island - if (!(plugin.getIslands().userIsOnIsland(b.getWorld(), user))) { - user.sendMessage("warps.error.not-on-island"); + if (inWorld && noLevelOrIsland(user, b.getWorld())) { e.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); return; } @@ -131,14 +122,12 @@ public class WarpSignsListener implements Listener { if (oldSignBlock.getType().name().contains("SIGN")) { // The block is still a sign Sign oldSign = (Sign) oldSignBlock.getState(); - if (oldSign != null) { - if (oldSign.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { - oldSign.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); - oldSign.update(true, false); - user.sendMessage("warps.deactivate"); - addon.getWarpSignsManager().removeWarp(oldSignBlock.getWorld(), user.getUniqueId()); - Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, oldSign.getLocation(), user.getUniqueId())); - } + if (oldSign.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { + oldSign.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); + oldSign.update(true, false); + user.sendMessage("warps.deactivate"); + addon.getWarpSignsManager().removeWarp(oldSignBlock.getWorld(), user.getUniqueId()); + Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, oldSign.getLocation(), user.getUniqueId())); } } // Set up the new warp sign @@ -148,6 +137,42 @@ public class WarpSignsListener implements Listener { } + private boolean noLevelOrIsland(User user, World world) { + // Get level if level addon is available + Long level = addon.getLevel(Util.getWorld(world), user.getUniqueId()); + if (level != null && level < addon.getSettings().getWarpLevelRestriction()) { + user.sendMessage("warps.error.not-enough-level"); + user.sendMessage("warps.error.your-level-is", + "[level]", String.valueOf(level), + "[required]", String.valueOf(addon.getSettings().getWarpLevelRestriction())); + return true; + } + + // Check that the player is on their island + if (!(plugin.getIslands().userIsOnIsland(world, user))) { + user.sendMessage("warps.error.not-on-island"); + return true; + } + return false; + } + + /** + * Check if player has permission to execute command + * @param user - user + * @param world - world that the warp is in + * @param inWorld - true if warp is in a game world + * @return true if player does not have the required perms, false otherwise + */ + private boolean noPerms(User user, World world, boolean inWorld) { + String permReq = inWorld ? addon.getPermPrefix(world) + "island.addwarp" : Warp.WELCOME_WARP_SIGNS + ".addwarp"; + if (!(user.hasPermission(permReq))) { + user.sendMessage("warps.error.no-permission"); + user.sendMessage("general.errors.no-permission", "[permission]", permReq); + return true; + } + return false; + } + private void addSign(SignChangeEvent e, User user, Block b) { if (addon.getWarpSignsManager().addWarp(user.getUniqueId(), b.getLocation())) { user.sendMessage("warps.success"); diff --git a/src/main/java/world/bentobox/warps/WarpSignsManager.java b/src/main/java/world/bentobox/warps/WarpSignsManager.java index a4e695c..da6040c 100644 --- a/src/main/java/world/bentobox/warps/WarpSignsManager.java +++ b/src/main/java/world/bentobox/warps/WarpSignsManager.java @@ -25,6 +25,8 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; import org.bukkit.permissions.PermissionAttachmentInfo; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.addons.Addon; @@ -59,7 +61,8 @@ public class WarpSignsManager { * @param world - world * @return map of warps */ - public Map getWarpMap(World world) { + @NonNull + public Map getWarpMap(@Nullable World world) { return worldsWarpList.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>()); } @@ -70,7 +73,7 @@ public class WarpSignsManager { public WarpSignsManager(Warp addon, BentoBox plugin) { this.addon = addon; this.plugin = plugin; - // Set up the database handler to store and retrieve Island classes + // Set up the database handler // Note that these are saved by the BSkyBlock database handler = new Database<>(addon, WarpsData.class); // Load the warps @@ -86,7 +89,7 @@ public class WarpSignsManager { */ public boolean addWarp(final UUID playerUUID, final Location loc) { // Do not allow null players to set warps - if (playerUUID == null) { + if (playerUUID == null || loc == null) { return false; } // Check for warps placed in a location where there was a warp before @@ -108,6 +111,7 @@ public class WarpSignsManager { * - the warp requested * @return Location of warp or null */ + @Nullable public Location getWarp(World world, UUID playerUUID) { return getWarpMap(world).get(playerUUID); } @@ -117,6 +121,7 @@ public class WarpSignsManager { * @param location to search * @return Name of warp owner or empty string if there is none */ + @NonNull public String getWarpOwner(Location location) { return getWarpMap(location.getWorld()).entrySet().stream().filter(en -> en.getValue().equals(location)) .findFirst().map(en -> plugin.getPlayers().getName(en.getKey())).orElse(""); @@ -126,11 +131,12 @@ public class WarpSignsManager { * Get sorted list of warps with most recent players listed first * @return UUID list */ - public List getSortedWarps(World world) { + @NonNull + public List getSortedWarps(@NonNull World world) { // Remove any null locations - this can happen if an admin changes the name of the world and signs point to old locations getWarpMap(world).values().removeIf(Objects::isNull); // Bigger value of time means a more recent login - TreeMap map = new TreeMap(); + TreeMap map = new TreeMap<>(); getWarpMap(world).entrySet().forEach(en -> { UUID uuid = en.getKey(); // If never played, will be zero @@ -148,7 +154,7 @@ public class WarpSignsManager { } // Fire event WarpListEvent event = new WarpListEvent(addon, list); - addon.getServer().getPluginManager().callEvent(event); + Bukkit.getPluginManager().callEvent(event); // Get the result of any changes by listeners list = event.getWarps(); return list; @@ -160,7 +166,8 @@ public class WarpSignsManager { * * @return UUID set of warps */ - public Set listWarps(World world) { + @NonNull + public Set listWarps(@NonNull World world) { // Remove any null locations getWarpMap(world).values().removeIf(Objects::isNull); return getWarpMap(world).entrySet().stream().filter(e -> Util.sameWorld(world, e.getValue().getWorld())).map(Map.Entry::getKey).collect(Collectors.toSet()); @@ -194,11 +201,9 @@ public class WarpSignsManager { Block b = loc.getBlock(); if (b.getType().name().contains("SIGN")) { Sign s = (Sign) b.getState(); - if (s != null) { - if (s.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { - s.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); - s.update(true, false); - } + if (s.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { + s.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); + s.update(true, false); } } } @@ -257,7 +262,8 @@ public class WarpSignsManager { * @param uuid - player's uuid * @return Sign's content and type */ - public SignCache getSignInfo(World world, UUID uuid) { + @NonNull + public SignCache getSignInfo(@NonNull World world, @NonNull UUID uuid) { List result = new ArrayList<>(); //get the sign info Location signLocation = getWarp(world, uuid); @@ -268,10 +274,13 @@ public class WarpSignsManager { result.remove(0); // Remove any trailing blank lines result.removeIf(String::isEmpty); + // Set the initial color per lore setting + for (int i = 0; i< result.size(); i++) { + result.set(i, ChatColor.translateAlternateColorCodes('&', addon.getSettings().getLoreFormat()) + result.get(i)); + } // Get the sign type - String prefix = this.plugin.getIWM().getAddon(world).map( - Addon::getPermissionPrefix).orElse(""); + String prefix = plugin.getIWM().getAddon(world).map(Addon::getPermissionPrefix).orElse(""); Material icon; @@ -306,7 +315,7 @@ public class WarpSignsManager { * @param directionFacing - direction that sign is facing * @param pvp - true if this location allowed PVP */ - private void warpPlayer(User user, Location inFront, UUID signOwner, BlockFace directionFacing, boolean pvp) { + private void warpPlayer(@NonNull User user, @NonNull Location inFront, @NonNull UUID signOwner, @NonNull BlockFace directionFacing, boolean pvp) { // convert blockface to angle float yaw = blockFaceToFloat(directionFacing); final Location actualWarp = new Location(inFront.getWorld(), inFront.getBlockX() + 0.5D, inFront.getBlockY(), @@ -331,7 +340,7 @@ public class WarpSignsManager { * @param face * @return degrees */ - private float blockFaceToFloat(BlockFace face) { + private float blockFaceToFloat(@NonNull BlockFace face) { switch (face) { case EAST: return 90F; @@ -377,7 +386,7 @@ public class WarpSignsManager { * @param user - user who is warping * @param owner - owner of the warp */ - public void warpPlayer(World world, User user, UUID owner) { + public void warpPlayer(@NonNull World world, @NonNull User user, @NonNull UUID owner) { final Location warpSpot = getWarp(world, owner); // Check if the warp spot is safe if (warpSpot == null) { @@ -394,7 +403,7 @@ public class WarpSignsManager { return; } - Island island = addon.getPlugin().getIslands().getIsland(world, owner); + Island island = addon.getIslands().getIsland(world, owner); boolean pvp = false; if (island != null) { // Check for PVP @@ -421,30 +430,29 @@ public class WarpSignsManager { Location inFront = b.getRelative(directionFacing).getLocation(); Location oneDown = b.getRelative(directionFacing).getRelative(BlockFace.DOWN).getLocation(); if ((plugin.getIslands().isSafeLocation(inFront))) { - addon.getWarpSignsManager().warpPlayer(user, inFront, owner, directionFacing, pvp); + warpPlayer(user, inFront, owner, directionFacing, pvp); return; } else if (plugin.getIslands().isSafeLocation(oneDown)) { // Try one block down if this is a wall sign - addon.getWarpSignsManager().warpPlayer(user, oneDown, owner, directionFacing, pvp); + warpPlayer(user, oneDown, owner, directionFacing, pvp); return; } } else if (b.getType().name().contains("SIGN")) { org.bukkit.block.data.type.Sign s = (org.bukkit.block.data.type.Sign) b.getBlockData(); BlockFace directionFacing = s.getRotation(); Location inFront = b.getRelative(directionFacing).getLocation(); - if ((plugin.getIslands().isSafeLocation(inFront))) { - addon.getWarpSignsManager().warpPlayer(user, inFront, owner, directionFacing, pvp); + if ((addon.getIslands().isSafeLocation(inFront))) { + warpPlayer(user, inFront, owner, directionFacing, pvp); return; } } else { // Warp has been removed user.sendMessage("warps.error.does-not-exist"); - addon.getWarpSignsManager().removeWarp(warpSpot); + removeWarp(warpSpot); return; } if (!(plugin.getIslands().isSafeLocation(warpSpot))) { user.sendMessage("warps.error.not-safe"); - return; } else { final Location actualWarp = new Location(warpSpot.getWorld(), warpSpot.getBlockX() + 0.5D, warpSpot.getBlockY(), warpSpot.getBlockZ() + 0.5D); @@ -455,7 +463,6 @@ public class WarpSignsManager { user.getWorld().playSound(user.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); } user.teleport(actualWarp); - return; } } @@ -464,7 +471,7 @@ public class WarpSignsManager { * @param playerUUID - player's UUID * @return true if they have warp */ - public boolean hasWarp(World world, UUID playerUUID) { + public boolean hasWarp(@NonNull World world, @NonNull UUID playerUUID) { return getWarpMap(world).containsKey(playerUUID); } @@ -482,7 +489,7 @@ public class WarpSignsManager { * @param defaultValue Default value that will be returned if permission not found. * @return String value that follows permissionPrefix. */ - private String getPermissionValue(User user, String permissionPrefix, String defaultValue) + private String getPermissionValue(@NonNull User user, @NonNull String permissionPrefix, @NonNull String defaultValue) { if (user.isPlayer()) { diff --git a/src/main/java/world/bentobox/warps/commands/WarpCommand.java b/src/main/java/world/bentobox/warps/commands/WarpCommand.java index 1a51b4c..d52358c 100644 --- a/src/main/java/world/bentobox/warps/commands/WarpCommand.java +++ b/src/main/java/world/bentobox/warps/commands/WarpCommand.java @@ -1,10 +1,12 @@ package world.bentobox.warps.commands; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; + +import org.bukkit.World; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; @@ -21,13 +23,18 @@ public class WarpCommand extends CompositeCommand { private Warp addon; public WarpCommand(Warp addon, CompositeCommand bsbIslandCmd) { - super(bsbIslandCmd, "warp"); + super(bsbIslandCmd, addon.getSettings().getWarpCommand()); + this.addon = addon; + } + + public WarpCommand(Warp addon) { + super(addon.getSettings().getWarpCommand()); this.addon = addon; } @Override public void setup() { - this.setPermission("island.warp"); + this.setPermission(this.getParent() == null ? Warp.WELCOME_WARP_SIGNS + ".warp" : "island.warp"); this.setOnlyPlayer(true); this.setParametersHelp("warp.help.parameters"); this.setDescription("warp.help.description"); @@ -36,22 +43,23 @@ public class WarpCommand extends CompositeCommand { @Override public boolean execute(User user, String label, List args) { if (args.size() == 1) { + World world = getWorld() == null ? user.getWorld() : getWorld(); // Warp somewhere command - Set warpList = addon.getWarpSignsManager().listWarps(getWorld()); + Set warpList = addon.getWarpSignsManager().listWarps(world); if (warpList.isEmpty()) { user.sendMessage("warps.error.no-warps-yet"); user.sendMessage("warps.warpTip", "[text]", addon.getSettings().getWelcomeLine()); - return true; + return false; } else { // Check if this is part of a name - UUID foundWarp = warpList.stream().filter(u -> getPlayers().getName(u).toLowerCase().equals(args.get(0).toLowerCase()) + UUID foundWarp = warpList.stream().filter(u -> getPlayers().getName(u).equalsIgnoreCase(args.get(0)) || getPlayers().getName(u).toLowerCase().startsWith(args.get(0).toLowerCase())).findFirst().orElse(null); if (foundWarp == null) { user.sendMessage("warps.error.does-not-exist"); return false; } else { // Warp exists! - addon.getWarpSignsManager().warpPlayer(getWorld(), user, foundWarp); + addon.getWarpSignsManager().warpPlayer(world, user, foundWarp); return true; } } @@ -62,14 +70,8 @@ public class WarpCommand extends CompositeCommand { @Override public Optional> tabComplete(User user, String alias, List args) { - List options = new ArrayList<>(); - final Set warpList = addon.getWarpSignsManager().listWarps(getWorld()); - - for (UUID warp : warpList) { - options.add(addon.getPlugin().getPlayers().getName(warp)); - } - - return Optional.of(options); + World world = getWorld() == null ? user.getWorld() : getWorld(); + return Optional.of(addon.getWarpSignsManager().listWarps(world).stream().map(getPlayers()::getName).collect(Collectors.toList())); } diff --git a/src/main/java/world/bentobox/warps/commands/WarpsCommand.java b/src/main/java/world/bentobox/warps/commands/WarpsCommand.java index c547e3b..efbbd72 100644 --- a/src/main/java/world/bentobox/warps/commands/WarpsCommand.java +++ b/src/main/java/world/bentobox/warps/commands/WarpsCommand.java @@ -1,16 +1,16 @@ -/** - * - */ package world.bentobox.warps.commands; import java.util.List; +import org.bukkit.World; + import world.bentobox.warps.Warp; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; /** - * @author ben + * Handles the warps command + * @author tastybento * */ public class WarpsCommand extends CompositeCommand { @@ -18,7 +18,12 @@ public class WarpsCommand extends CompositeCommand { private Warp addon; public WarpsCommand(Warp addon, CompositeCommand bsbIslandCmd) { - super(bsbIslandCmd, "warps"); + super(bsbIslandCmd, addon.getSettings().getWarpsCommand()); + this.addon = addon; + } + + public WarpsCommand(Warp addon) { + super(addon.getSettings().getWarpsCommand()); this.addon = addon; } @@ -27,7 +32,7 @@ public class WarpsCommand extends CompositeCommand { */ @Override public void setup() { - this.setPermission("island.warp"); + this.setPermission(this.getParent() == null ? Warp.WELCOME_WARP_SIGNS + ".warp" : "island.warp"); this.setOnlyPlayer(true); this.setDescription("warps.help.description"); } @@ -37,12 +42,13 @@ public class WarpsCommand extends CompositeCommand { */ @Override public boolean execute(User user, String label, List args) { - if (addon.getWarpSignsManager().listWarps(getWorld()).isEmpty()) { + World world = getWorld() == null ? user.getWorld() : getWorld(); + if (addon.getWarpSignsManager().listWarps(world).isEmpty()) { user.sendMessage("warps.error.no-warps-yet"); user.sendMessage("warps.warpTip", "[text]", addon.getSettings().getWelcomeLine()); - } else { - addon.getWarpPanelManager().showWarpPanel(getWorld(), user,0); + return false; } + addon.getWarpPanelManager().showWarpPanel(world, user, 0); return true; } diff --git a/src/main/java/world/bentobox/warps/config/Settings.java b/src/main/java/world/bentobox/warps/config/Settings.java index 0b1e7ac..7b51024 100644 --- a/src/main/java/world/bentobox/warps/config/Settings.java +++ b/src/main/java/world/bentobox/warps/config/Settings.java @@ -45,6 +45,36 @@ public class Settings implements ConfigObject @ConfigEntry(path = "disabled-gamemodes") private Set disabledGameModes = new HashSet<>(); + @ConfigComment("") + @ConfigComment("Warp panel name formatting.") + @ConfigComment("Example: &c will make names red. &f is white") + @ConfigEntry(path = "name-format") + private String nameFormat = "&f"; + + @ConfigComment("") + @ConfigComment("Warp panel default lore formatting.") + @ConfigComment("Example: &c will make lore red. &f is white") + @ConfigEntry(path = "lore-format") + private String loreFormat = "&f"; + + @ConfigComment("") + @ConfigComment("Allow random teleport - adds a button to the warp panel that goes to a random warp sign") + @ConfigEntry(path = "random-allowed") + private boolean randomAllowed = true; + + @ConfigComment("") + @ConfigComment("Allow use in other worlds. Players must have the welcomewarpsigns.warp permission.") + @ConfigEntry(path = "allow-in-other-worlds") + private boolean allowInOtherWorlds = false; + + @ConfigComment("") + @ConfigComment("Warp and warps commands. You can change them if they clash with other addons or plugins.") + @ConfigEntry(path = "warp-command") + String warpCommand = "warp"; + @ConfigEntry(path = "warps-command") + String warpsCommand = "warps"; + + // --------------------------------------------------------------------- // Section: Constructor // --------------------------------------------------------------------- @@ -143,4 +173,102 @@ public class Settings implements ConfigObject { this.icon = icon; } + + + /** + * @return the nameFormat + */ + public String getNameFormat() { + return nameFormat; + } + + + /** + * @param nameFormat the nameFormat to set + */ + public void setNameFormat(String nameFormat) { + this.nameFormat = nameFormat; + } + + + /** + * @return the loreFormat + */ + public String getLoreFormat() { + return loreFormat; + } + + + /** + * @param loreFormat the loreFormat to set + */ + public void setLoreFormat(String loreFormat) { + this.loreFormat = loreFormat; + } + + + /** + * @return the randomAllowed + */ + public boolean isRandomAllowed() { + return randomAllowed; + } + + + /** + * @param randomAllowed the randomAllowed to set + */ + public void setRandomAllowed(boolean randomAllowed) { + this.randomAllowed = randomAllowed; + } + + + /** + * @return the allowInOtherWorlds + */ + public boolean isAllowInOtherWorlds() { + return allowInOtherWorlds; + } + + + /** + * @param allowInOtherWorlds the allowInOtherWorlds to set + */ + public void setAllowInOtherWorlds(boolean allowInOtherWorlds) { + this.allowInOtherWorlds = allowInOtherWorlds; + } + + + /** + * @return the warpCommand + */ + public String getWarpCommand() { + return warpCommand; + } + + + /** + * @param warpCommand the warpCommand to set + */ + public void setWarpCommand(String warpCommand) { + this.warpCommand = warpCommand; + } + + + /** + * @return the warpsCommand + */ + public String getWarpsCommand() { + return warpsCommand; + } + + + /** + * @param warpsCommand the warpsCommand to set + */ + public void setWarpsCommand(String warpsCommand) { + this.warpsCommand = warpsCommand; + } + + } diff --git a/src/main/java/world/bentobox/warps/event/WarpCreateEvent.java b/src/main/java/world/bentobox/warps/event/WarpCreateEvent.java index 0c87f21..cdf7b81 100644 --- a/src/main/java/world/bentobox/warps/event/WarpCreateEvent.java +++ b/src/main/java/world/bentobox/warps/event/WarpCreateEvent.java @@ -11,39 +11,39 @@ import world.bentobox.warps.Warp; /** * This event is fired when a Warp is created * A Listener to this event can use it only to get informations. e.g: broadcast something - * + * * @author Poslovitch * */ public class WarpCreateEvent extends Event{ - private static final HandlerList handlers = new HandlerList(); - - private Location warpLoc; - private UUID creator; - - /** - * @param plugin - BSkyBlock plugin objects - * @param warpLoc - * @param creator - */ - public WarpCreateEvent(Warp plugin, Location warpLoc, UUID creator){ - this.warpLoc = warpLoc; - this.creator = creator; - } - - /** - * Get the location of the created Warp - * @return created warp's location - */ - public Location getWarpLocation(){return this.warpLoc;} - - /** - * Get who has created the warp - * @return the warp's creator - */ - public UUID getCreator(){return this.creator;} - - @Override + private static final HandlerList handlers = new HandlerList(); + + private Location warpLoc; + private UUID creator; + + /** + * @param plugin - BSkyBlock plugin objects + * @param warpLoc + * @param creator + */ + public WarpCreateEvent(Warp plugin, Location warpLoc, UUID creator){ + this.warpLoc = warpLoc; + this.creator = creator; + } + + /** + * Get the location of the created Warp + * @return created warp's location + */ + public Location getWarpLocation(){return this.warpLoc;} + + /** + * Get who has created the warp + * @return the warp's creator + */ + public UUID getCreator(){return this.creator;} + + @Override public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/world/bentobox/warps/event/WarpInitiateEvent.java b/src/main/java/world/bentobox/warps/event/WarpInitiateEvent.java index 0d4725d..1e50a3b 100644 --- a/src/main/java/world/bentobox/warps/event/WarpInitiateEvent.java +++ b/src/main/java/world/bentobox/warps/event/WarpInitiateEvent.java @@ -10,34 +10,34 @@ import org.bukkit.event.HandlerList; import world.bentobox.warps.Warp; /** - * This event is fired when a player tries to do a warp + * This event is fired when a player tries to do a warp * A Listener to this event can use it to get informations. e.g: broadcast something - * + * * @author tastybento * */ public class WarpInitiateEvent extends Event implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private Location warpLoc; - private final UUID player; - - /** - * @param plugin - BSkyBlock plugin objects - * @param warpLoc - where the player is warping to - * @param player - the UUID of the player - */ - public WarpInitiateEvent(Warp plugin, Location warpLoc, UUID player){ - this.warpLoc = warpLoc; - this.player = player; - } - - /** - * Get the location of the Warp - * @return created warp's location - */ - public Location getWarpLoc(){return this.warpLoc;} - + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private Location warpLoc; + private final UUID player; + + /** + * @param plugin - BSkyBlock plugin objects + * @param warpLoc - where the player is warping to + * @param player - the UUID of the player + */ + public WarpInitiateEvent(Warp plugin, Location warpLoc, UUID player){ + this.warpLoc = warpLoc; + this.player = player; + } + + /** + * Get the location of the Warp + * @return created warp's location + */ + public Location getWarpLoc(){return this.warpLoc;} + /** * Set a different location to where the player will go * @param warpLoc @@ -47,12 +47,12 @@ public class WarpInitiateEvent extends Event implements Cancellable { } /** - * Get who is warping - * @return the warping player's uuid - */ - public UUID getPlayer(){return this.player;} - - @Override + * Get who is warping + * @return the warping player's uuid + */ + public UUID getPlayer(){return this.player;} + + @Override public HandlerList getHandlers() { return handlers; } @@ -63,13 +63,12 @@ public class WarpInitiateEvent extends Event implements Cancellable { @Override public boolean isCancelled() { - // TODO Auto-generated method stub return cancelled; } @Override public void setCancelled(boolean cancelled) { this.cancelled = cancelled; - + } } diff --git a/src/main/java/world/bentobox/warps/objects/WarpsData.java b/src/main/java/world/bentobox/warps/objects/WarpsData.java index 9fc6757..ad4a1f3 100644 --- a/src/main/java/world/bentobox/warps/objects/WarpsData.java +++ b/src/main/java/world/bentobox/warps/objects/WarpsData.java @@ -12,13 +12,15 @@ import com.google.gson.annotations.Expose; import world.bentobox.bentobox.database.objects.DataObject; public class WarpsData implements DataObject { - + @Expose private String uniqueId = "warps"; @Expose private Map warpSigns = new HashMap<>(); - - public WarpsData() {} + + public WarpsData() { + // Required by YAML database + } @Override public String getUniqueId() { @@ -31,8 +33,8 @@ public class WarpsData implements DataObject { } public Map getWarpSigns() { - if (warpSigns == null) - return new HashMap<>(); + if (warpSigns == null) + return new HashMap<>(); return warpSigns; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 93a29dc..a723f46 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -23,3 +23,21 @@ icon: 'SIGN' # disabled-gamemodes: # - BSkyBlock disabled-gamemodes: [] +# +# Warp panel name formatting. +# Example: &c will make names red, &f is white +name-format: &f +# +# Warp panel default lore formatting. +# Example: &c will make lore red. &f is white +lore-format: &f +# +# Allow random teleport - adds a button to the warp panel that goes to a random warp sign +random-allowed: true +# +# Allow use in other worlds. Players must have the welcomewarpsigns.warp permission. +allow-in-other-worlds: false +# +# Warp and warps commands. You can change them if they clash with other addons or plugins. +warp-command: warp +warps-command: warps diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 4810a30..1593c51 100755 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -23,6 +23,7 @@ warps: next: "&6Next page" player-warped: "&2[name] warped to your warp sign!" previous: "&6Previous page" + random: "&4Random Warp" sign-removed: "&CWarp sign removed!" success: "&ASuccess!" title: "Warp Signs" diff --git a/src/main/resources/locales/fr.yml b/src/main/resources/locales/fr.yml index eb2a4d2..0fcee35 100644 --- a/src/main/resources/locales/fr.yml +++ b/src/main/resources/locales/fr.yml @@ -1,30 +1,28 @@ -########################################################################################### -# This is a YML file. Be careful when editing. Check your edits in a YAML checker like # -# the one at http://yaml-online-parser.appspot.com # -########################################################################################### - -warp: - help: - description: "te téléporte au Warp d'un autre joueur" - parameters: -warps: +--- +warp: + help: + description: te téléporte au Warp d'un autre joueur + parameters: "" +warps: deactivate: "&cAncien panneau de Warp désactivé !" - error: + error: does-not-exist: "&cCe Warp n'existe plus !" no-permission: "&cVous n'avez pas la permission pour faire cela !" no-remove: "&cVous ne pouvez pas supprimer ce panneau !" - no-warps-yet: "&cIl n'y a encore aucun Warp sur ce serveur." - not-enough-level: "&cVotre niveau d'île n'est pas assez élevé pour faire cela !" + not-enough-level: "&cVotre niveau d'île n'est pas assez élevé pour faire cela + !" not-on-island: "&cVous devez être sur votre île pour faire cela !" not-safe: "&cCe Warp n'est pas sûr!" + no-warps-yet: "&cIl n'y a encore aucun Warp sur ce serveur." your-level-is: "&cVotre île est seulement niveau [level] et doit être niveau [required]." - help: - description: "Ouvre le menu des Warps" + help: + description: Ouvre le menu des Warps next: "&6Page suivante" player-warped: "&2[name] s'est téléporté sur votre île !" previous: "&6Page précédente" sign-removed: "&cPanneau de Warp supprimé !" success: "&aSuccès !" - title: "Panneau Warp" + title: Panneau Warp warpTip: "&6Placez un panneau et écrivez [text] sur la première ligne." warpToPlayersSign: "&6Téléportation sur l'île de [player]..." + random: "&4Warp aléatoire" diff --git a/src/main/resources/locales/lv.yml b/src/main/resources/locales/lv.yml index edae7c4..57070e5 100644 --- a/src/main/resources/locales/lv.yml +++ b/src/main/resources/locales/lv.yml @@ -9,10 +9,10 @@ warps: does-not-exist: "&cAk vai! Uzaicinājuma zīme vairāk neeksistē!" no-permission: "&CTev nav nepieciešamās atļaujas, lai veiktu darbību!" no-remove: "&CTu nevari noņemt šo zīmi!" - no-warps-yet: "&CNav neviena aktīva uzaicinājuma zīme." not-enough-level: "&CTavas salas līmenis ir pārāk zems!" not-on-island: "&CTev ir jāatrodas uz savas salas, lai veiktu šo darbību!" not-safe: "&cŠī uzaicinājuma zīme nav droša!" + no-warps-yet: "&CNav neviena aktīva uzaicinājuma zīme." your-level-is: "&cTavas salas līmenis ir tikai [level], bet ir nepieciešams vismaz [required]. Vari mēģināt pārrēķināt savas salas līmeni." help: @@ -25,3 +25,4 @@ warps: title: Uzaicinājuma Zīmes warpTip: "&6Novieto zīmi ar tekstu [text] pirmajā rindā" warpToPlayersSign: "&6Pārvietojās uz [player] uzaicinājuma zīmes" + random: "&4Nejauša Zīmes Izvēle" diff --git a/src/main/resources/locales/zh-CN.yml b/src/main/resources/locales/zh-CN.yml index 111b1c1..88601b2 100644 --- a/src/main/resources/locales/zh-CN.yml +++ b/src/main/resources/locales/zh-CN.yml @@ -1,32 +1,27 @@ -########################################################################################### -# 本文件是 YML 格式的文件. 编辑时请务必小心. # -# 请在 http://yaml-online-parser.appspot.com 等 YAML 检查器中检查您的编辑. # -########################################################################################### - -warp: - help: +--- +warp: + help: description: 传送到该玩家的传送木牌处 - parameters: <玩家名称> + parameters: "" warps: - deactivate: "&c禁用的旧转移标志!" - error: - does-not-exist: "&c转移不再存在!" + error: no-permission: "&C权限不足!" no-remove: "&C无权移除传送木牌!" - no-warps-yet: "&C暂无可用传送木牌" not-enough-level: "&C岛屿等级不够高!" - not-on-island: "&C操作必须在空岛上进行!" - not-safe: "&c转移不安全!" + no-warps-yet: "&C暂无可用传送木牌" your-level-is: "&c岛屿当前等级 [level], 需要等级 [required]" - help: + does-not-exist: "&c那个传送已经不存在了!" + not-on-island: "&C操作必须在你的岛屿上进行!" + not-safe: "&c那个传送不安全!" + help: description: 打开传送面板 next: "&6下一页" - player-warped: "&2[name]转移到你的标志!" previous: "&6上一页" sign-removed: "&C传送木牌已移除!" success: "&A成功!" title: 传送木牌 warpTip: "&6放置一个第一行是 [text] 的木牌以创建传送木牌" warpToPlayersSign: "&6正传送到 [player] 的传送木牌" - - + deactivate: "&c旧传送牌已不再使用!" + player-warped: "&2[name] 刚刚传送到了你的传送牌!" + random: "&4随机传送" diff --git a/src/test/java/world/bentobox/warps/WarpPanelManagerTest.java b/src/test/java/world/bentobox/warps/WarpPanelManagerTest.java index b555f2e..3e3e584 100644 --- a/src/test/java/world/bentobox/warps/WarpPanelManagerTest.java +++ b/src/test/java/world/bentobox/warps/WarpPanelManagerTest.java @@ -1,9 +1,12 @@ package world.bentobox.warps; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; @@ -23,6 +26,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; @@ -57,6 +61,8 @@ public class WarpPanelManagerTest { @Mock private Inventory top; private UUID uuid; + @Mock + private Settings settings; /** * @throws java.lang.Exception @@ -104,7 +110,6 @@ public class WarpPanelManagerTest { when(Bukkit.createInventory(any(), Mockito.anyInt(), any())).thenReturn(top); - Settings settings = mock(Settings.class); when(settings.getIcon()).thenReturn("SIGN"); when(addon.getSettings()).thenReturn(settings); @@ -133,11 +138,43 @@ public class WarpPanelManagerTest { */ @Test public void testShowWarpPanelFirst() { + ArgumentCaptor argument = ArgumentCaptor.forClass(ItemStack.class); WarpPanelManager wpm = new WarpPanelManager(addon); wpm.showWarpPanel(world, user, 0); verify(player).openInventory(Mockito.eq(top)); // Just next sign - verify(top, Mockito.times(53)).setItem(Mockito.anyInt(), Mockito.any(ItemStack.class)); + verify(top, Mockito.times(53)).setItem(Mockito.anyInt(),argument.capture()); + assertEquals(Material.STONE, argument.getAllValues().get(52).getType()); + } + + /** + * Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}. + */ + @Test + public void testShowWarpPanelFirstRandom() { + when(settings.isRandomAllowed()).thenReturn(true); + ArgumentCaptor argument = ArgumentCaptor.forClass(ItemStack.class); + WarpPanelManager wpm = new WarpPanelManager(addon); + wpm.showWarpPanel(world, user, 0); + verify(player).openInventory(Mockito.eq(top)); + // Check crystal + verify(top, Mockito.atLeastOnce()).setItem(anyInt(), argument.capture()); + assertEquals(Material.END_CRYSTAL, argument.getAllValues().get(0).getType()); + } + + /** + * Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}. + */ + @Test + public void testShowWarpPanelNoRandom() { + when(settings.isRandomAllowed()).thenReturn(false); + ArgumentCaptor argument = ArgumentCaptor.forClass(ItemStack.class); + WarpPanelManager wpm = new WarpPanelManager(addon); + wpm.showWarpPanel(world, user, 0); + verify(player).openInventory(Mockito.eq(top)); + // Check crystal + verify(top, Mockito.atLeastOnce()).setItem(anyInt(), argument.capture()); + assertFalse(argument.getAllValues().get(0).getType().equals(Material.END_CRYSTAL)); } /** @@ -145,11 +182,14 @@ public class WarpPanelManagerTest { */ @Test public void testShowWarpPanelMiddle() { + ArgumentCaptor argument = ArgumentCaptor.forClass(ItemStack.class); WarpPanelManager wpm = new WarpPanelManager(addon); wpm.showWarpPanel(world, user, 1); verify(player).openInventory(Mockito.eq(top)); // includes previous and next signs - verify(top, Mockito.times(54)).setItem(Mockito.anyInt(), Mockito.any(ItemStack.class)); + verify(top, Mockito.times(54)).setItem(Mockito.anyInt(), argument.capture()); + assertEquals(Material.STONE, argument.getAllValues().get(52).getType()); + assertEquals(Material.COBBLESTONE, argument.getAllValues().get(53).getType()); } /** @@ -157,11 +197,13 @@ public class WarpPanelManagerTest { */ @Test public void testShowWarpPanelLast() { + ArgumentCaptor argument = ArgumentCaptor.forClass(ItemStack.class); WarpPanelManager wpm = new WarpPanelManager(addon); wpm.showWarpPanel(world, user, 3); verify(player).openInventory(Mockito.eq(top)); // Final amount, just previous sign - verify(top, Mockito.times(46)).setItem(Mockito.anyInt(), Mockito.any(ItemStack.class)); + verify(top, Mockito.times(46)).setItem(Mockito.anyInt(), argument.capture()); + assertEquals(Material.COBBLESTONE, argument.getAllValues().get(45).getType()); } /** diff --git a/src/test/java/world/bentobox/warps/WarpSignsListenerTest.java b/src/test/java/world/bentobox/warps/WarpSignsListenerTest.java index 62b3f7f..930e170 100644 --- a/src/test/java/world/bentobox/warps/WarpSignsListenerTest.java +++ b/src/test/java/world/bentobox/warps/WarpSignsListenerTest.java @@ -10,6 +10,7 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.never; import java.util.HashMap; import java.util.Map; @@ -79,6 +80,8 @@ public class WarpSignsListenerTest { private Settings settings; @Mock private IslandsManager im; + @Mock + private IslandWorldManager iwm; @Before public void setUp() throws Exception { @@ -121,6 +124,7 @@ public class WarpSignsListenerTest { Location location = mock(Location.class); when(location.getBlock()).thenReturn(block); when(s.getLocation()).thenReturn(location); + when(block.getLocation()).thenReturn(location); list.put(uuid, location); // Player is in world when(wsm.getWarpMap(Mockito.eq(world))).thenReturn(list); @@ -155,9 +159,10 @@ public class WarpSignsListenerTest { // Sufficient level when(addon.getLevel(any(), any())).thenReturn(100L); - IslandWorldManager iwm = mock(IslandWorldManager.class); + // IWM when(plugin.getIWM()).thenReturn(iwm); when(iwm.getAddon(any())).thenReturn(Optional.empty()); + when(iwm.inWorld(any(World.class))).thenReturn(true); // Util PowerMockito.mockStatic(Util.class); @@ -190,7 +195,7 @@ public class WarpSignsListenerTest { } @Test - public void testOnSignBreakWrongWorld() { + public void testOnSignNotGameWorld() { WarpSignsListener wsl = new WarpSignsListener(addon); BlockBreakEvent e = new BlockBreakEvent(block, player); when(addon.inRegisteredWorld(any())).thenReturn(false); @@ -199,16 +204,6 @@ public class WarpSignsListenerTest { verify(addon).inRegisteredWorld(Mockito.eq(world)); } - @Test - public void testOnSignBreakNullState() { - WarpSignsListener wsl = new WarpSignsListener(addon); - BlockBreakEvent e = new BlockBreakEvent(block, player); - when(block.getState()).thenReturn(null); - wsl.onSignBreak(e); - assertFalse(e.isCancelled()); - verify(block).getState(); - } - @Test public void testOnSignNotWelcomeSign() { WarpSignsListener wsl = new WarpSignsListener(addon); @@ -283,7 +278,7 @@ public class WarpSignsListenerTest { * Sign create */ @Test - public void testOnCreateWrongWorld() { + public void testOnCreateWrongWorldGameWorld() { when(player.hasPermission(anyString())).thenReturn(true); WarpSignsListener wsl = new WarpSignsListener(addon); SignChangeEvent e = new SignChangeEvent(block, player, lines); @@ -292,6 +287,43 @@ public class WarpSignsListenerTest { verify(addon).inRegisteredWorld(Mockito.eq(world)); } + @Test + public void testOnCreateNotGameWorldAllowed() { + when(settings.isAllowInOtherWorlds()).thenReturn(true); + when(iwm.inWorld(any(World.class))).thenReturn(false); + when(player.hasPermission(anyString())).thenReturn(true); + WarpSignsListener wsl = new WarpSignsListener(addon); + SignChangeEvent e = new SignChangeEvent(block, player, lines); + when(addon.inRegisteredWorld(any())).thenReturn(false); + wsl.onSignWarpCreate(e); + verify(player).sendMessage("warps.success"); + assertEquals(ChatColor.GREEN + "[WELCOME]", e.getLine(0)); + } + + @Test + public void testOnCreateNotGameWorldNotAllowed() { + when(settings.isAllowInOtherWorlds()).thenReturn(false); + when(iwm.inWorld(any(World.class))).thenReturn(false); + when(player.hasPermission(anyString())).thenReturn(true); + WarpSignsListener wsl = new WarpSignsListener(addon); + SignChangeEvent e = new SignChangeEvent(block, player, lines); + when(addon.inRegisteredWorld(any())).thenReturn(false); + wsl.onSignWarpCreate(e); + verify(player, never()).sendMessage("warps.success"); + } + + @Test + public void testOnCreateNotGameWorldNoPerm() { + when(settings.isAllowInOtherWorlds()).thenReturn(true); + when(iwm.inWorld(any(World.class))).thenReturn(false); + when(player.hasPermission(anyString())).thenReturn(false); + WarpSignsListener wsl = new WarpSignsListener(addon); + SignChangeEvent e = new SignChangeEvent(block, player, lines); + when(addon.inRegisteredWorld(any())).thenReturn(false); + wsl.onSignWarpCreate(e); + verify(player).sendMessage("warps.error.no-permission"); + } + @Test public void testOnCreateWrongText() { when(player.hasPermission(anyString())).thenReturn(true); diff --git a/src/test/java/world/bentobox/warps/WarpSignsManagerTest.java b/src/test/java/world/bentobox/warps/WarpSignsManagerTest.java new file mode 100644 index 0000000..37c3456 --- /dev/null +++ b/src/test/java/world/bentobox/warps/WarpSignsManagerTest.java @@ -0,0 +1,450 @@ +package world.bentobox.warps; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.beans.IntrospectionException; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Sign; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginManager; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +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.api.user.User; +import world.bentobox.bentobox.database.AbstractDatabaseHandler; +import world.bentobox.bentobox.database.DatabaseSetup; +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.PlayersManager; +import world.bentobox.bentobox.util.Util; +import world.bentobox.warps.config.Settings; +import world.bentobox.warps.event.WarpInitiateEvent; +import world.bentobox.warps.objects.WarpsData; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, Util.class, DatabaseSetup.class}) +public class WarpSignsManagerTest { + + @Mock + private Warp addon; + @Mock + private BentoBox plugin; + @Mock + private World world; + @Mock + private static AbstractDatabaseHandler handler; + + + private WarpSignsManager wsm; + @Mock + private Logger logger; + @Mock + private WarpsData load; + private UUID uuid = UUID.randomUUID(); + @Mock + private Location location; + @Mock + private Block block; + @Mock + private PluginManager pim; + @Mock + private Server server; + @Mock + private Player player; + @Mock + private WarpPanelManager wpm; + @Mock + private PlayersManager pm; + @Mock + private OfflinePlayer offlinePlayer; + @Mock + private Settings settings; + @Mock + private IslandWorldManager iwm; + @Mock + private IslandsManager im; + @Mock + private Island island; + + + @SuppressWarnings("unchecked") + @BeforeClass + public static void beforeClass() { + // This has to be done beforeClass otherwise the tests will interfere with each other + handler = mock(AbstractDatabaseHandler.class); + // Database + PowerMockito.mockStatic(DatabaseSetup.class); + DatabaseSetup dbSetup = mock(DatabaseSetup.class); + when(DatabaseSetup.getDatabase()).thenReturn(dbSetup); + when(dbSetup.getHandler(any())).thenReturn(handler); + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + when(addon.getPlugin()).thenReturn(plugin); + when(addon.getLogger()).thenReturn(logger); + + // Player + when(player.getUniqueId()).thenReturn(uuid); + User.getInstance(player); + + // Locales + LocalesManager lm = mock(LocalesManager.class); + when(lm.get(Mockito.any(), Mockito.any())).thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class)); + when(plugin.getLocalesManager()).thenReturn(lm); + // Return the same string + PlaceholdersManager phm = mock(PlaceholdersManager.class); + when(phm.replacePlaceholders(any(), anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class)); + when(plugin.getPlaceholdersManager()).thenReturn(phm); + + + // Server + when(addon.getServer()).thenReturn(server); + when(server.getPlayer(any(UUID.class))).thenReturn(player); + + // Util + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(any())).thenAnswer((Answer) invocation -> invocation.getArgument(0, World.class)); + when(Util.sameWorld(any(), any())).thenReturn(true); + + // Location + when(location.getWorld()).thenReturn(world); + when(location.getBlock()).thenReturn(block); + when(location.getBlockX()).thenReturn(23); + when(location.getBlockY()).thenReturn(24); + when(location.getBlockZ()).thenReturn(25); + when(world.getEnvironment()).thenReturn(Environment.NORMAL); + + // Block + when(block.getType()).thenReturn(Material.ACACIA_SIGN); + when(block.getLocation()).thenReturn(location); + Sign sign = mock(Sign.class); + String[] lines = {"[Welcome]", "line2", "line3", "line4"}; + when(sign.getLines()).thenReturn(lines); + when(sign.getLine(anyInt())).thenReturn("[Welcome]"); + when(sign.getType()).thenReturn(Material.ACACIA_SIGN); + when(block.getState()).thenReturn(sign); + org.bukkit.block.data.type.Sign signBd = mock(org.bukkit.block.data.type.Sign.class); + when(signBd.getRotation()).thenReturn(BlockFace.EAST); + when(block.getBlockData()).thenReturn(signBd); + when(block.getRelative(any())).thenReturn(block); + + // Handler + when(handler.objectExists(eq("warps"))).thenReturn(true); + Map warpMap = Collections.singletonMap(location, uuid); + when(load.getWarpSigns()).thenReturn(warpMap); + when(handler.loadObject(anyString())).thenReturn(load); + + // Settings + when(addon.getSettings()).thenReturn(settings); + when(settings.getWelcomeLine()).thenReturn("[Welcome]"); + when(settings.getLoreFormat()).thenReturn("&f"); + when(settings.getIcon()).thenReturn("SIGN"); + + // Bukkit + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getPluginManager()).thenReturn(pim); + + // Players Manager + when(plugin.getPlayers()).thenReturn(pm); + when(pm.getName(eq(uuid))).thenReturn("tastybento"); + + // Offline player + when(server.getOfflinePlayer(any(UUID.class))).thenReturn(offlinePlayer); + when(offlinePlayer.getLastPlayed()).thenReturn(System.currentTimeMillis()); + + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock."); + + // Island Manager + when(addon.getIslands()).thenReturn(im); + when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + when(im.isSafeLocation(any())).thenReturn(true); + + // WarpPanelManager + when(addon.getWarpPanelManager()).thenReturn(wpm); + + // User + + + wsm = new WarpSignsManager(addon, plugin); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + User.clearUsers(); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + */ + @Test + public void testGetWarpMap() { + assertFalse("Map is empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + */ + @Test + public void testGetWarpMapNullWorld() { + when(location.getWorld()).thenReturn(null); + wsm = new WarpSignsManager(addon, plugin); + assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + */ + @Test + public void testGetWarpMapWrongBlockType() { + when(block.getType()).thenReturn(Material.COAL_ORE); + wsm = new WarpSignsManager(addon, plugin); + assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + */ + @Test + public void testGetWarpMapNullLocation() { + Map warpMap = Collections.singletonMap(null, uuid); + when(load.getWarpSigns()).thenReturn(warpMap); + wsm = new WarpSignsManager(addon, plugin); + assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + * @throws Exception + */ + @Test + public void testGetWarpMapNullDatabaseObject() throws Exception { + when(handler.loadObject(anyString())).thenReturn(null); + wsm = new WarpSignsManager(addon, plugin); + assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. + */ + @Test + public void testGetWarpMapNothingInDatabase() { + when(handler.objectExists(eq("warps"))).thenReturn(false); + wsm = new WarpSignsManager(addon, plugin); + assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#WarpSignsManager(world.bentobox.warps.Warp, world.bentobox.bentobox.BentoBox)}. + * @throws Exception + */ + @Test + public void testWarpSignsManager() throws Exception { + verify(logger).info("Loading warps..."); + verify(load).getWarpSigns(); + verify(block).getType(); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}. + */ + @Test + public void testAddWarpNullPlayer() { + assertFalse(wsm.addWarp(null, null)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}. + */ + @Test + public void testAddWarpNullLocation() { + assertFalse(wsm.addWarp(uuid, null)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}. + */ + @Test + public void testAddWarpReplaceOldSign() { + assertTrue(wsm.addWarp(uuid, location)); + verify(player).sendMessage("warps.sign-removed"); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}. + */ + @Test + public void testAddWarpReplaceOldSignDifferentPlayer() { + assertTrue(wsm.addWarp(UUID.randomUUID(), location)); + verify(player).sendMessage("warps.sign-removed"); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}. + */ + @Test + public void testAddWarp() { + Location loc = mock(Location.class); + assertTrue(wsm.addWarp(uuid, loc)); + verify(pim).callEvent(any(WarpInitiateEvent.class)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarp(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetWarpWorldWorld() { + assertNull(wsm.getWarp(mock(World.class), uuid)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarp(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetWarp() { + assertEquals(location, wsm.getWarp(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpOwner(org.bukkit.Location)}. + */ + @Test + public void testGetWarpOwner() { + assertEquals("tastybento", wsm.getWarpOwner(location)); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getSortedWarps(org.bukkit.World)}. + */ + @Test + public void testGetSortedWarps() { + assertEquals(1, wsm.getSortedWarps(world).size()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#listWarps(org.bukkit.World)}. + */ + @Test + public void testListWarps() { + assertEquals(1, wsm.listWarps(world).size()); + assertEquals(uuid, wsm.listWarps(world).toArray()[0]); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#removeWarp(org.bukkit.Location)}. + */ + @Test + public void testRemoveWarpLocation() { + wsm.removeWarp(location); + assertTrue(wsm.listWarps(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#removeWarp(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testRemoveWarpWorldUUID() { + wsm.removeWarp(world, uuid); + assertTrue(wsm.listWarps(world).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#saveWarpList()}. + * @throws IntrospectionException + * @throws InvocationTargetException + * @throws Exception + */ + @Test + public void testSaveWarpList() throws Exception { + wsm.saveWarpList(); + verify(handler, Mockito.atLeastOnce()).saveObject(any()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#getSignInfo(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetSignInfo() { + SignCache sc = wsm.getSignInfo(world, uuid); + assertEquals(Material.ACACIA_SIGN, sc.getType()); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#warpPlayer(org.bukkit.World, world.bentobox.bentobox.api.user.User, java.util.UUID)}. + */ + @Test + public void testWarpPlayer() { + Player p = mock(Player.class); + when(p.getUniqueId()).thenReturn(UUID.randomUUID()); + when(p.getWorld()).thenReturn(world); + when(p.getName()).thenReturn("tastybento"); + @Nullable + User u = User.getInstance(p); + wsm.warpPlayer(world, u, uuid); + verify(p).teleport(any(Location.class)); + verify(player).sendMessage("warps.player-warped"); + } + + /** + * Test method for {@link world.bentobox.warps.WarpSignsManager#hasWarp(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testHasWarp() { + assertTrue(wsm.hasWarp(world, uuid)); + assertFalse(wsm.hasWarp(mock(World.class), uuid)); + assertFalse(wsm.hasWarp(world, UUID.randomUUID())); + } + +} diff --git a/src/test/java/world/bentobox/warps/commands/WarpCommandTest.java b/src/test/java/world/bentobox/warps/commands/WarpCommandTest.java new file mode 100644 index 0000000..aa4958a --- /dev/null +++ b/src/test/java/world/bentobox/warps/commands/WarpCommandTest.java @@ -0,0 +1,236 @@ +package world.bentobox.warps.commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.eclipse.jdt.annotation.NonNull; +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.managers.CommandsManager; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.PlayersManager; +import world.bentobox.warps.Warp; +import world.bentobox.warps.WarpSignsManager; +import world.bentobox.warps.config.Settings; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BentoBox.class}) +public class WarpCommandTest { + + private static final String WELCOME_LINE = "[Welcome]"; + @Mock + private CompositeCommand ic; + private UUID uuid; + @Mock + private User user; + @Mock + private World world; + @Mock + private IslandWorldManager iwm; + @Mock + private Warp addon; + // Command under test + private WarpCommand wc; + @Mock + private Settings settings; + @Mock + private WarpSignsManager wsm; + @Mock + private PlayersManager pm; + + /** + * @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); + // Addon + when(ic.getAddon()).thenReturn(addon); + when(ic.getPermissionPrefix()).thenReturn("bskyblock."); + when(ic.getWorld()).thenReturn(world); + + // IWM friendly name + when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); + when(iwm.inWorld(any(World.class))).thenReturn(true); + when(plugin.getIWM()).thenReturn(iwm); + + // Player + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getWorld()).thenReturn(world); + + // settings + when(addon.getSettings()).thenReturn(settings); + when(settings.getWarpCommand()).thenReturn("warp"); + when(settings.getWelcomeLine()).thenReturn(WELCOME_LINE); + + // Warp Signs Manager + when(addon.getWarpSignsManager()).thenReturn(wsm); + @NonNull + Set set = new HashSet<>(); + set.add(UUID.randomUUID()); + set.add(UUID.randomUUID()); + set.add(UUID.randomUUID()); + when(wsm.listWarps(eq(world))).thenReturn(set); + + // Players Manager + when(plugin.getPlayers()).thenReturn(pm); + when(addon.getPlayers()).thenReturn(pm); + // Repeat twice because it is asked twice + when(pm.getName(any())).thenReturn("tastybento", "tastybento", "poslovich", "poslovich", "BONNe", "BONNe", "Joe"); + } + + public void warpCommandWarpCompositeCommand() { + // Command under test + wc = new WarpCommand(addon, ic); + } + + public void warpCommandWarp() { + // Command under test + wc = new WarpCommand(addon); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#setup()}. + */ + @Test + public void testSetupWarpCompositeCommand() { + warpCommandWarpCompositeCommand(); + assertEquals("bskyblock.island.warp", wc.getPermission()); + assertTrue(wc.isOnlyPlayer()); + assertEquals("warp.help.parameters", wc.getParameters()); + assertEquals("warp.help.description", wc.getDescription()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#setup()}. + */ + @Test + public void testSetupWarp() { + warpCommandWarp(); + assertEquals(Warp.WELCOME_WARP_SIGNS + ".warp", wc.getPermission()); + assertTrue(wc.isOnlyPlayer()); + assertEquals("warp.help.parameters", wc.getParameters()); + assertEquals("warp.help.description", wc.getDescription()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringNoArgs() { + warpCommandWarpCompositeCommand(); + wc.execute(user, "warp", Collections.emptyList()); + verify(user).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("BSkyBlock")); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringKnownPlayer() { + warpCommandWarpCompositeCommand(); + assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento"))); + verify(wsm).warpPlayer(eq(world), eq(user), any()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringKnownPlayerWarp() { + warpCommandWarp(); + assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento"))); + verify(wsm).warpPlayer(eq(world), eq(user), any()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringKnownPlayerMixedCase() { + warpCommandWarpCompositeCommand(); + assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTyBEnTo"))); + verify(wsm).warpPlayer(eq(world), eq(user), any()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringKnownPlayerStartOnly() { + warpCommandWarpCompositeCommand(); + assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTy"))); + verify(wsm).warpPlayer(eq(world), eq(user), any()); + } + + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringUnknownPlayer() { + warpCommandWarpCompositeCommand(); + assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky"))); + verify(user).sendMessage(eq("warps.error.does-not-exist")); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringNoWarpsYet() { + when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); + warpCommandWarpCompositeCommand(); + assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky"))); + verify(user).sendMessage(eq("warps.error.no-warps-yet")); + verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfString() { + warpCommandWarpCompositeCommand(); + List op = wc.tabComplete(user, "warp", Collections.singletonList("tas")).get(); + assertEquals("tastybento", op.get(0)); + assertEquals("tastybento", op.get(1)); + assertEquals("poslovich", op.get(2)); + } + +} diff --git a/src/test/java/world/bentobox/warps/commands/WarpsCommandTest.java b/src/test/java/world/bentobox/warps/commands/WarpsCommandTest.java new file mode 100644 index 0000000..1cf8d41 --- /dev/null +++ b/src/test/java/world/bentobox/warps/commands/WarpsCommandTest.java @@ -0,0 +1,186 @@ +package world.bentobox.warps.commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.eclipse.jdt.annotation.NonNull; +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.managers.CommandsManager; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.PlayersManager; +import world.bentobox.warps.Warp; +import world.bentobox.warps.WarpPanelManager; +import world.bentobox.warps.WarpSignsManager; +import world.bentobox.warps.config.Settings; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BentoBox.class}) +public class WarpsCommandTest { + + private static final String WELCOME_LINE = "[Welcome]"; + @Mock + private CompositeCommand ic; + @Mock + private User user; + @Mock + private World world; + @Mock + private IslandWorldManager iwm; + @Mock + private Warp addon; + // Command under test + private WarpsCommand wc; + @Mock + private Settings settings; + @Mock + private WarpSignsManager wsm; + @Mock + private PlayersManager pm; + @Mock + private WarpPanelManager wpm; + + /** + * @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); + // Addon + when(ic.getAddon()).thenReturn(addon); + when(ic.getPermissionPrefix()).thenReturn("bskyblock."); + + // World + when(world.toString()).thenReturn("world"); + + // Player + when(user.getWorld()).thenReturn(world); + + // settings + when(addon.getSettings()).thenReturn(settings); + when(settings.getWarpsCommand()).thenReturn("warps"); + when(settings.getWelcomeLine()).thenReturn(WELCOME_LINE); + + // Warp Signs Manager + when(addon.getWarpSignsManager()).thenReturn(wsm); + @NonNull + Set set = new HashSet<>(); + set.add(UUID.randomUUID()); + set.add(UUID.randomUUID()); + set.add(UUID.randomUUID()); + when(wsm.listWarps(eq(world))).thenReturn(set); + + // Warp Panel Manager + when(addon.getWarpPanelManager()).thenReturn(wpm); + + } + + public void warpCommandWarpsCompositeCommand() { + // Command under test + wc = new WarpsCommand(addon, ic); + } + + public void warpCommandWarps() { + // Command under test + wc = new WarpsCommand(addon); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#setup()}. + */ + @Test + public void testSetupWarpCompositeCommand() { + warpCommandWarpsCompositeCommand(); + assertEquals("bskyblock.island.warp", wc.getPermission()); + assertTrue(wc.isOnlyPlayer()); + assertEquals("warps.help.description", wc.getDescription()); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#setup()}. + */ + @Test + public void testSetupWarp() { + warpCommandWarps(); + assertEquals(Warp.WELCOME_WARP_SIGNS + ".warp", wc.getPermission()); + assertTrue(wc.isOnlyPlayer()); + assertEquals("warps.help.description", wc.getDescription()); + } + + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringNoWarpsYet() { + when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); + warpCommandWarpsCompositeCommand(); + assertFalse(wc.execute(user, "warps", Collections.emptyList())); + verify(user).sendMessage(eq("warps.error.no-warps-yet")); + verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringNoWarpsYetNoAddon() { + when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); + warpCommandWarps(); + assertFalse(wc.execute(user, "warps", Collections.emptyList())); + verify(user).sendMessage(eq("warps.error.no-warps-yet")); + verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + warpCommandWarpsCompositeCommand(); + assertTrue(wc.execute(user, "warps", Collections.emptyList())); + verify(wpm).showWarpPanel(world, user, 0); + } + + /** + * Test method for {@link world.bentobox.warps.commands.WarpsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfStringNoAddon() { + warpCommandWarps(); + assertTrue(wc.execute(user, "warps", Collections.emptyList())); + verify(wpm).showWarpPanel(world, user, 0); + } + +}