Fixed subcommand aliases. Added admin tp command.

While writing the admin tp command, I realized that subcommand aliases
were not working. Also, it was not possible to tell what alias had been
used for a command. I added that capability. i.e., if the alias is used,
then the label of that command is set to the alias.
This commit is contained in:
Tastybento 2018-01-21 12:58:35 -08:00
parent c3c0a87dbb
commit f6ca7f7866
6 changed files with 217 additions and 57 deletions

View File

@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@ -31,14 +32,14 @@ import us.tastybento.bskyblock.util.Util;
public abstract class CompositeCommand extends Command implements PluginIdentifiableCommand, BSBCommand {
private static final boolean DEBUG = false;
/**
* This is the command level. 0 is the top, 1 is the first level sub command.
*/
private final int subCommandLevel;
/**
* True if the command is for the player only (not for the console)
*/
private boolean onlyPlayer = false;
/**
* The parameters string for this command. It is the commands followed by a locale reference.
*/
private String parameters = "";
/**
* The parent command to this one. If this is a top-level command it will be empty.
*/
@ -47,14 +48,19 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
* The permission required to execute this command
*/
private String permission = "";
/**
* This is the command level. 0 is the top, 1 is the first level sub command.
*/
private final int subCommandLevel;
/**
* Map of sub commands
*/
private Map<String, CompositeCommand> subCommands;
/**
* The parameters string for this command. It is the commands followed by a locale reference.
* Map of aliases for subcommands
*/
private String parameters = "";
private Map<String, CompositeCommand> subCommandAliases;
/**
* The command chain from the very top, e.g., island team promote
*/
@ -70,6 +76,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
setUsage("");
this.subCommandLevel = 0; // Top level
this.subCommands = new LinkedHashMap<>();
this.subCommandAliases = new LinkedHashMap<>();
this.setup();
if (!this.getSubCommand("help").isPresent() && !label.equals("help"))
new DefaultHelpCommand(this);
@ -91,6 +98,11 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
parent.getSubCommands().put(label, this);
this.setAliases(new ArrayList<>(Arrays.asList(aliases)));
this.subCommands = new LinkedHashMap<>();
this.subCommandAliases = new LinkedHashMap<>();
// Add aliases to the parent for this command
for (String alias : aliases) {
parent.subCommandAliases.put(alias, this);
}
setUsage("");
this.setup();
// If this command does not define its own help class, then use the default help command
@ -104,17 +116,18 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
/**
* This is the top-level command constructor for commands that have no parent.
* @param label - string for this command
* @param string - aliases for this command
* @param aliases - aliases for this command
*/
public CompositeCommand(String label, String... string) {
public CompositeCommand(String label, String... aliases) {
super(label);
if (DEBUG)
Bukkit.getLogger().info("DEBUG: top level command registering..." + label);
this.setAliases(new ArrayList<>(Arrays.asList(string)));
this.setAliases(new ArrayList<>(Arrays.asList(aliases)));
this.parent = null;
setUsage("");
this.subCommandLevel = 0; // Top level
this.subCommands = new LinkedHashMap<>();
this.subCommandAliases = new LinkedHashMap<>();
// Register command if it is not already registered
if (getPlugin().getCommand(label) == null) {
getPlugin().getCommandsManager().registerCommand(this);
@ -160,7 +173,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
if (event.isCancelled()) {
return true;
}
// Execute and trim args
return cmd.execute(user, Arrays.asList(args).subList(cmd.subCommandLevel, args.length));
}
@ -174,7 +187,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
CompositeCommand subCommand = this;
// Run through any arguments
if (DEBUG)
Bukkit.getLogger().info("DEBUG: Running through args: " + args.toString());
Bukkit.getLogger().info("DEBUG: Running through args: " + Arrays.asList(args).toString());
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
if (DEBUG)
@ -188,6 +201,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
subCommand = subCommand.getSubCommand(args[i]).get();
if (DEBUG)
Bukkit.getLogger().info("DEBUG: Moved to " + subCommand.getLabel());
// Set the label
subCommand.setLabel(args[i]);
} else {
return subCommand;
}
@ -219,6 +234,13 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
return subCommandLevel;
}
/**
* @return Logger
*/
public Logger getLogger() {
return getPlugin().getLogger();
}
/**
* Convenience method to obtain team members
* @param user
@ -251,12 +273,13 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
protected PlayersManager getPlayers() {
return getPlugin().getPlayers();
}
@Override
public BSkyBlock getPlugin() {
return BSkyBlock.getInstance();
}
/**
* @return Settings object
*/
@ -266,18 +289,26 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
/**
* Returns the CompositeCommand object refering to this command label
* Returns the CompositeCommand object referring to this command label
* @param label - command label or alias
* @return CompositeCommand or null if none found
*/
public Optional<CompositeCommand> getSubCommand(String label) {
if (DEBUG)
Bukkit.getLogger().info("DEBUG: label = " + label);
for (Map.Entry<String, CompositeCommand> entry : subCommands.entrySet()) {
if (DEBUG)
Bukkit.getLogger().info("DEBUG: " + entry.getKey());
if (entry.getKey().equalsIgnoreCase(label)) return Optional.of(subCommands.get(label));
else if (entry.getValue().getAliases().contains(label)) return Optional.of(subCommands.get(entry.getValue().getLabel()));
}
// Try aliases
for (Map.Entry<String, CompositeCommand> entry : subCommandAliases.entrySet()) {
if (DEBUG)
Bukkit.getLogger().info("DEBUG: alias " + entry.getKey());
if (entry.getKey().equalsIgnoreCase(label)) return Optional.of(subCommandAliases.get(label));
}
return Optional.empty();
}
/**
* @return Map of sub commands for this command
@ -294,22 +325,22 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
protected UUID getTeamLeader(User user) {
return getPlugin().getIslands().getTeamLeader(user.getUniqueId());
}
@Override
public String getUsage() {
return "/" + usage;
}
/**
* Check if this command has a specific sub command
* @param subCommand
* @return true if this command has this sub command
*/
private boolean hasSubCommand(String subCommand) {
return subCommands.containsKey(subCommand);
return subCommands.containsKey(subCommand) || subCommandAliases.containsKey(subCommand);
}
/**
* Check if this command has any sub commands
* @return true if this command has subcommands
@ -352,6 +383,10 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
this.onlyPlayer = onlyPlayer;
}
/**
* Sets the command parameters to be shown in help
* @param parameters
*/
public void setParameters(String parameters) {
this.parameters = parameters;
}
@ -360,7 +395,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
public void setPermission(String permission) {
this.permission = permission;
}
/**
* This creates the full linking chain of commands
*/
@ -376,7 +411,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
this.usage = this.usage.trim();
return this;
}
@Override
public List<String> tabComplete(final CommandSender sender, final String alias, final String[] args) {
List<String> options = new ArrayList<>();

View File

@ -6,6 +6,7 @@ import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.CompositeCommand;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.commands.admin.AdminReloadCommand;
import us.tastybento.bskyblock.commands.admin.AdminTeleportCommand;
import us.tastybento.bskyblock.commands.admin.AdminVersionCommand;
public class AdminCommand extends CompositeCommand {
@ -21,6 +22,7 @@ public class AdminCommand extends CompositeCommand {
this.setDescription("admin.help.description");
new AdminVersionCommand(this);
new AdminReloadCommand(this);
new AdminTeleportCommand(this);
}
@Override

View File

@ -0,0 +1,57 @@
package us.tastybento.bskyblock.commands.admin;
import java.util.List;
import java.util.UUID;
import org.bukkit.Location;
import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.CompositeCommand;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.util.SafeSpotTeleport;
public class AdminTeleportCommand extends CompositeCommand {
public AdminTeleportCommand(CompositeCommand parent) {
super(parent, "tp", "tpnether", "tpend");
}
@Override
public void setup() {
this.setPermission(Constants.PERMPREFIX + "admin.tp");
this.setOnlyPlayer(true);
this.setDescription("commands.admin.tp.description");
}
@Override
public boolean execute(User user, List<String> args) {
if (args.isEmpty()) {
user.sendMessage("commands.admin.tp.help");
return true;
}
// Convert name to a UUID
final UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("errors.unknown-player");
return true;
} else {
if (getPlayers().hasIsland(targetUUID) || getPlayers().inTeam(targetUUID)) {
Location warpSpot = getIslands().getIslandLocation(targetUUID).toVector().toLocation(getPlugin().getIslandWorldManager().getIslandWorld());
if (this.getLabel().equals("tpnether")) {
warpSpot = getIslands().getIslandLocation(targetUUID).toVector().toLocation(getPlugin().getIslandWorldManager().getNetherWorld());
} else if (this.getLabel().equals("tpend")) {
warpSpot = getIslands().getIslandLocation(targetUUID).toVector().toLocation(getPlugin().getIslandWorldManager().getEndWorld());
}
// Other wise, go to a safe spot
String failureMessage = user.getTranslation("commands.admin.tp.manual", "[location]", warpSpot.getBlockX() + " " + warpSpot.getBlockY() + " "
+ warpSpot.getBlockZ());
new SafeSpotTeleport(getPlugin(), user.getPlayer(), warpSpot, failureMessage);
return true;
}
user.sendMessage("command.admin.tp.no-island");
return true;
}
}
}

View File

@ -16,6 +16,7 @@ import org.bukkit.entity.Player;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.database.objects.Players;
@ -29,6 +30,7 @@ public class PlayersManager{
private HashMap<UUID, Players> playerCache;
private Set<UUID> inTeleport;
private HashMap<String, UUID> nameCache;
/**
* Provides a memory cache of online player information
@ -47,6 +49,7 @@ public class PlayersManager{
inTeleport = new HashSet<>();
}
/**
* Load all players - not normally used as to load all players into memory will be wasteful
*/
@ -317,27 +320,19 @@ public class PlayersManager{
}
/**
* Attempts to return a UUID for a given player's name. Only uses online or cached information.
* Attempts to return a UUID for a given player's name.
* @param string
* @return UUID of player or null if unknown
*/
public UUID getUUID(String string) {
return getUUID(string, false);
}
/**
* Attempts to return a UUID for a given player's name
* @param string
* @param adminCheck - if made via an admin call, this will go out to the 'net and grab - may cause lag
* @return UUID of player or null if unknown
*/
@SuppressWarnings("deprecation")
public UUID getUUID(String string, boolean adminCheck) {
// Look in the database if it ready
// TODO: finish this!
public UUID getUUID(String string) {
// See if this is a UUID
try {
UUID uuid = UUID.fromString(string);
return uuid;
} catch (Exception e) {}
// Look in the name cache
return Bukkit.getOfflinePlayer(string).getUniqueId();
//return database.getUUID(string, adminCheck);
}
/**
@ -345,12 +340,11 @@ public class PlayersManager{
* @param uniqueId
* @param name
*/
public void setPlayerName(UUID uniqueId, String name) {
public void setPlayerName(User user) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Setting player name to " + name + " for " + uniqueId);
addPlayer(uniqueId);
playerCache.get(uniqueId).setPlayerName(name);
//database.savePlayerName(name, uniqueId);
plugin.getLogger().info("DEBUG: Setting player name to " + user.getName() + " for " + user.getUniqueId());
addPlayer(user.getUniqueId());
playerCache.get(user.getUniqueId()).setPlayerName(user.getName());
}
/**
@ -600,7 +594,7 @@ public class PlayersManager{
if (DEBUG)
plugin.getLogger().info("DEBUG: saving player by uuid " + player.getPlayerName() + " " + playerUUID + " saved");
handler.saveObject(player);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | SecurityException
| InstantiationException | NoSuchMethodException
@ -613,5 +607,11 @@ public class PlayersManager{
}
}
public boolean isKnown(String string) {
UUID uuid = this.getUUID(string);
if (uuid == null) return false;
return false;
}
}

View File

@ -0,0 +1,68 @@
/**
*
*/
package us.tastybento.bskyblock.database.objects;
import java.util.HashMap;
import java.util.UUID;
import us.tastybento.bskyblock.api.commands.User;
/**
* A bean to hold name to UUID lookup
* @author tastybento
*
*/
public class NameToUUID implements DataObject {
public HashMap<String, UUID> namesToUUID;
public NameToUUID() {}
/**
* @return the namesToUUID
*/
public HashMap<String, UUID> getNamesToUUID() {
return namesToUUID;
}
/**
* @param namesToUUID the namesToUUID to set
*/
public void setNamesToUUID(HashMap<String, UUID> namesToUUID) {
this.namesToUUID = namesToUUID;
}
/* (non-Javadoc)
* @see us.tastybento.bskyblock.database.objects.DataObject#getUniqueId()
*/
@Override
public String getUniqueId() {
return "names-uuid";
}
/* (non-Javadoc)
* @see us.tastybento.bskyblock.database.objects.DataObject#setUniqueId(java.lang.String)
*/
@Override
public void setUniqueId(String uniqueId) {
// Do nothing
}
/**
* Add or update a name
* @param user
*/
public void addName(User user) {
this.namesToUUID.put(user.getName(), user.getUniqueId());
}
/**
* Get UUID for name
* @param name
* @return UUID or null if not found
*/
public UUID getUUID(String name) {
return this.namesToUUID.get(name);
}
}

View File

@ -2,7 +2,6 @@ package us.tastybento.bskyblock.listeners;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@ -31,15 +30,14 @@ public class JoinLeaveListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerJoin(final PlayerJoinEvent event) {
Player player = event.getPlayer();
if (player == null) {
if (event.getPlayer() == null) {
return;
}
UUID playerUUID = player.getUniqueId();
if (playerUUID == null) {
User user = User.getInstance(event.getPlayer());
if (user.getUniqueId() == null) {
return;
}
User user = User.getInstance(player);
UUID playerUUID = user.getUniqueId();
if (plugin.getPlayers().isKnown(playerUUID)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: known player");
@ -52,10 +50,10 @@ public class JoinLeaveListener implements Listener {
if (DEBUG)
plugin.getLogger().info("DEBUG: Setting player's name");
// Set the player's name (it may have changed), but only if it isn't empty
if (!player.getName().isEmpty()) {
if (!user.getName().isEmpty()) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Player name is " + player.getName());
players.setPlayerName(playerUUID, player.getName());
plugin.getLogger().info("DEBUG: Player name is " + user.getName());
players.setPlayerName(user);
if (DEBUG)
plugin.getLogger().info("DEBUG: Saving player");
players.save(playerUUID);
@ -65,19 +63,19 @@ public class JoinLeaveListener implements Listener {
if (plugin.getSettings().isRemoveMobsOnLogin()) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Removing mobs");
plugin.getIslands().removeMobs(player.getLocation());
plugin.getIslands().removeMobs(user.getLocation());
}
// Check if they logged in to a locked island and expel them or if they are banned
Island currentIsland = plugin.getIslands().getIslandAt(player.getLocation());
if (currentIsland != null && (currentIsland.isLocked() || plugin.getPlayers().isBanned(currentIsland.getOwner(),player.getUniqueId()))) {
Island currentIsland = plugin.getIslands().getIslandAt(user.getLocation());
if (currentIsland != null && (currentIsland.isLocked() || plugin.getPlayers().isBanned(currentIsland.getOwner(),user.getUniqueId()))) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Current island is locked, or player is banned");
if (!currentIsland.getMembers().contains(playerUUID) && !player.hasPermission(Constants.PERMPREFIX + "mod.bypassprotect")) {
if (!currentIsland.getMembers().contains(playerUUID) && !user.hasPermission(Constants.PERMPREFIX + "mod.bypassprotect")) {
if (DEBUG)
plugin.getLogger().info("DEBUG: No bypass - teleporting");
user.sendMessage("locked.islandlocked");
plugin.getIslands().homeTeleport(player);
plugin.getIslands().homeTeleport(user.getPlayer());
}
}
} else {