From 72d6d1c6199d85ea4d25ebbb0171c6442e726fa8 Mon Sep 17 00:00:00 2001 From: Amaury Carrade Date: Mon, 11 Jan 2016 15:43:19 +0100 Subject: [PATCH] Added a /uh tpspawn command to teleport a player to his spawn point. Closes #115. * NEW: added a command (/uh tpspawn [force]) to teleport a player to his registered spawn point. The command behaves like the /uh tpback one, with safe TP and `force` option if no safe spot is available. --- .../commands/commands/UHRootCommand.java | 2 + .../commands/commands/uh/UHTPBackCommand.java | 2 - .../commands/uh/UHTPSpawnCommand.java | 153 ++++++++++++++++++ .../amaury/UHCReloaded/game/Teleporter.java | 20 +++ src/main/resources/i18n/en_US.yml | 14 +- src/main/resources/i18n/fr_FR.yml | 10 +- .../commands/TestCommandsAnnotation.java | 14 +- 7 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java index 1003541..4c569c5 100644 --- a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java @@ -50,6 +50,7 @@ import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHStartCommand; import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPBackCommand; import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPSpawnCommand; import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTeamCommand; import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTimersCommand; import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; @@ -90,6 +91,7 @@ public UHRootCommand(UHCReloaded plugin) registerSubCommand(new UHKillCommand(p)); registerSubCommand(new UHResurrectCommand(p)); registerSubCommand(new UHTPBackCommand(p)); + registerSubCommand(new UHTPSpawnCommand(p)); // Misc registerSubCommand(new UHFinishCommand(p)); diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java index 234f951..c1d848c 100644 --- a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java @@ -43,7 +43,6 @@ import org.bukkit.entity.Player; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -105,7 +104,6 @@ else if (UHUtils.safeTP(player, deathLocation)) @Override public List tabComplete(CommandSender sender, String[] args) { - if (args.length == 1) { List suggestions = new ArrayList<>(); diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java new file mode 100644 index 0000000..56920cd --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java @@ -0,0 +1,153 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.i18n.I18n; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "tpspawn") +public class UHTPSpawnCommand extends AbstractCommand +{ + private final UHCReloaded p; + private final I18n i; + + public UHTPSpawnCommand(UHCReloaded plugin) + { + p = plugin; + i = p.getI18n(); + } + + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + // Spawns not assigned + if (p.getGameManager().getTeleporter() == null) + { + sender.sendMessage(i.t("tpspawn.notAssigned")); + return; + } + + + if (args.length < 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + Player player = p.getServer().getPlayer(args[0]); + if (player == null || !player.isOnline()) + { + sender.sendMessage(i.t("tpspawn.offline", args[0])); + return; + } + + Location spawnLocation = p.getGameManager().getTeleporter().getSpawnForPlayer(player.getUniqueId()); + + if (spawnLocation == null) + { + sender.sendMessage(i.t("tpspawn.noSpawnLocation", args[0])); + return; + } + + + if (args.length >= 2 && args[1].equalsIgnoreCase("force")) + { + p.getGameManager().getTeleporter().teleportPlayer(player.getUniqueId(), true); + sender.sendMessage(i.t("tpspawn.teleported", args[0])); + } + else if (UHUtils.safeTP(player, spawnLocation)) + { + sender.sendMessage(i.t("tpspawn.teleported", args[0])); + } + else + { + sender.sendMessage(i.t("tpspawn.notTeleportedNoSafeSpot", args[0])); + sender.sendMessage(i.t("tpspawn.notTeleportedNoSafeSpotCmd", args[0])); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + // Spawns not attributed + if (p.getGameManager().getTeleporter() == null) + return null; + + + if (args.length == 1) + { + List suggestions = new ArrayList<>(); + + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getGameManager().getTeleporter().hasSpawnForPlayer(player.getUniqueId())) + { + suggestions.add(player.getName()); + } + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + } + + else if (args.length == 2) + { + return CommandUtils.getAutocompleteSuggestions(args[1], Collections.singletonList("force")); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(i.t("cmd.helpTpspawn")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java index de5506f..af02eab 100644 --- a/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java @@ -93,6 +93,26 @@ public void setSpawnForPlayer(UUID playerUUID, Location spawn) spawnPoints.put(playerUUID, spawn); } + /** + * Checks if a spawn point is registered for the given player. + * + * @param playerUUID The player UUID. + * @return {@code true} if a spawn point is registered. + */ + public boolean hasSpawnForPlayer(UUID playerUUID) + { + return spawnPoints.containsKey(playerUUID); + } + + /** + * @param playerUUID A player's UUID. + * @return The registered spawn point for that player, or {@code null} if no-one was ever registered. + */ + public Location getSpawnForPlayer(UUID playerUUID) + { + return spawnPoints.get(playerUUID).clone(); + } + /** * Teleports the given player to the spawn point. * diff --git a/src/main/resources/i18n/en_US.yml b/src/main/resources/i18n/en_US.yml index 3ad93b1..510d971 100644 --- a/src/main/resources/i18n/en_US.yml +++ b/src/main/resources/i18n/en_US.yml @@ -51,6 +51,7 @@ keys: helpKill: "{cc}/uh kill {ci}: mark a player as dead, even if he is offline." helpResurrect: "{cc}/uh resurrect {ci}: resurrects a player." helpTpback: "{cc}/uh tpback [force] {ci}: safely teleports back a player to his death location." + helpTpspawn: "{cc}/uh tpspawn [force] {ci}: safely teleports back a player to his spawn location." titleMiscCmd: "{aqua}------ Miscellaneous commands ------" helpFreeze: "{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh freeze for details." @@ -404,14 +405,21 @@ keys: offlineOk: "{cs}Because {0} is offline, he will be resurrected when he logins. If he was, he is no longer banned." notDead: "{ce}{0} is not dead!" broadcastMessage: "{gold}{0} returned from the dead!" - + tpback: - usage: "{ce}Usage: /uh tpback [force]" offline: "{ce}The player {0} is not online." noDeathLocation: "{ce}No death location available for the player {0}." teleported: "{cs}The player {0} was teleported back." notTeleportedNoSafeSpot: "{ce}The player {0} was NOT teleported back because no safe spot was found." - notTeleportedNoSafeSpotCmd: "{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardess this point." + notTeleportedNoSafeSpotCmd: "{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this point." + + tpspawn: + notAssigned: "{ce}The spawn points are not already assigned to the player, because the game is not started." + offline: "{ce}The player {0} is not online." + noSpawnLocation: "{ce}No spawn location available for the player {0}." + teleported: "{cs}The player {0} was teleported to his spawn location." + notTeleportedNoSafeSpot: "{ce}The player {0} was NOT teleported to his spawn because no safe spot was found." + notTeleportedNoSafeSpotCmd: "{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this point." tp: NaN: "{ce}The coordinates must be three valid numbers." diff --git a/src/main/resources/i18n/fr_FR.yml b/src/main/resources/i18n/fr_FR.yml index 10177f9..84738fc 100644 --- a/src/main/resources/i18n/fr_FR.yml +++ b/src/main/resources/i18n/fr_FR.yml @@ -51,6 +51,7 @@ keys: helpKill: "{cc}/uh kill {ci}: marque un joueur comme mort, même s'il est hors-ligne." helpResurrect: "{cc}/uh resurrect {ci}: fait revivre un joueur." helpTpback: "{cc}/uh tpback [force] {ci}: téléporte un joueur au lieu de sa mort en toute sécurité." + helpTpspawn: "{cc}/uh tpspawn [force] {ci}: téléporte un joueur à son point de démarrage attribué en toute sécurité." titleMiscCmd: "{aqua}------ Commandes diverses ------" helpFreeze: "{cc}/uh freeze {ci}: (dés)immobilise l'ensemble du jeu, ou un joueur. Consultez /uh freeze pour plus de détails." @@ -408,12 +409,19 @@ keys: broadcastMessage: "{gold}{0} est revenu d'entre les morts !" tpback: - usage: "{ce}Utilisation : /uh tpback [force]" offline: "{ce}Le joueur {0} n'est pas connecté." noDeathLocation: "{ce}Pas de localisation de mort enregistrée pour le joueur {0}." teleported: "{cs}Le joueur {0} a été téléporté là où il est mort." notTeleportedNoSafeSpot: "{ce}Le joueur {0} n'a PAS été téléporté car aucun point de téléportation sûr n'a été trouvé." notTeleportedNoSafeSpotCmd: "{ci}Utilisez {cc}/uh tpback {0} force{ci} pour le téléporter malgré tout." + + tpspawn: + notAssigned: "{ce}Les points de démarrage n'ont pas encore été assignés aux joueurs, car le jeu n'a pas encore démarré." + offline: "{ce}Le joueur {0} n'est pas connecté." + noSpawnLocation: "{ce}Pas de localisation de démarrage enregistrée pour le joueur {0}." + teleported: "{cs}Le joueur {0} a été téléporté à son point de démarrage attribué." + notTeleportedNoSafeSpot: "{ce}Le joueur {0} n'a PAS été téléporté car aucun point de téléportation sûr n'a été trouvé." + notTeleportedNoSafeSpotCmd: "{ci}Utilisez {cc}/uh tpspawn {0} force{ci} pour le téléporter malgré tout." tp: NaN: "{ce}Les coordonnées doivent être trois nombres." diff --git a/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java b/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java index 7865bb9..761622d 100644 --- a/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java +++ b/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java @@ -48,11 +48,11 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(UHCReloaded.class) -public class TestCommandsAnnotation { - +public class TestCommandsAnnotation +{ @Test - public void testCommandAnnotationIsPresentEverywhere() { - + public void testCommandAnnotationIsPresentEverywhere() + { // Data Set executors = new HashSet<>(); executors.add(new UHCommandExecutor(TestsUtils.getMockedPluginInstance())); @@ -71,10 +71,12 @@ public void testCommandAnnotationIsPresentEverywhere() { * * @param command The command to start with. */ - private void testCommandAnnotationIsPresentEverywhere(AbstractCommand command) { + private void testCommandAnnotationIsPresentEverywhere(AbstractCommand command) + { Assert.assertTrue("Missing command annotation for the class " + command.getClass().getCanonicalName(), command.getClass().isAnnotationPresent(Command.class)); - for(AbstractCommand subCommand : command.getSubcommands().values()) { + for(AbstractCommand subCommand : command.getSubcommands().values()) + { testCommandAnnotationIsPresentEverywhere(subCommand); } }