public class BuckCommand extends BasicCommand
{
    public BuckCommand()
    {
        super("Buck");
        setDescription("Buck a player riding you");
        setUsage("/mob buck");
        setArgumentRange(0, 0);
        setIdentifiers("buck");
        setPermission("mobrider.command.buck");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (player.getPassenger() instanceof LivingEntity && DependencyUtils.hasPermission(player, "mobrider.command.buck")) {
                player.eject();
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }

}
 public class CommandHandler {

    private Map<String, Command> commands;

    public CommandHandler() {
        commands = new LinkedHashMap<String, Command>();
    }

    public void addCommand(Command command) {
        commands.put(command.getName().toLowerCase(), command);
    }

    public void removeCommand(Command command) {
        commands.remove(command.getName().toLowerCase());
    }

    public Command getCommand(String name) {
        return commands.get(name.toLowerCase());
    }

    public List<Command> getCommands() {
        return new ArrayList<Command>(commands.values());
    }

    public boolean dispatch(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) {
    	String[] arguments;
        if (args.length < 1) {
        	arguments = new String[]{ command.getName() };
        } else {
        	arguments = args;
        }
        
        for (int argsIncluded = arguments.length; argsIncluded >= 0; argsIncluded--) {
        	StringBuilder identifierBuilder = new StringBuilder();
            for (int i = 0; i < argsIncluded; i++) {
            	identifierBuilder.append(' ').append(arguments[i]);
            }
            
            String identifier = identifierBuilder.toString().trim();
            for (Command cmd : commands.values()) {
                if (cmd.isIdentifier(sender, identifier)) {
                    String[] realArgs = Arrays.copyOfRange(arguments, argsIncluded, arguments.length);

                    if (cmd.isNotInProgress(sender)) {
                        if (realArgs.length < cmd.getMinArguments() || realArgs.length > cmd.getMaxArguments()) {
                            displayCommandHelp(cmd, sender);
                            return true;
                        } else if (realArgs.length > 0 && "?".equals(realArgs[0])) {
                            displayCommandHelp(cmd, sender);
                            return true;
                        }
                    }

                    if (!hasPermission(sender, cmd.getPermission())) {
                        sender.sendMessage("Insufficient permission.");
                        return true;
                    }

                    cmd.execute(sender, identifier, realArgs);
                    return true;
                }
            }
        }

        return true;
    }

    private void displayCommandHelp(Command cmd, CommandSender sender) {
        sender.sendMessage("§cCommand:§e " + cmd.getName());
        sender.sendMessage("§cDescription:§e " + cmd.getDescription());
        sender.sendMessage("§cUsage:§e " + cmd.getUsage());
        if (cmd.getNotes() != null) {
            for (String note : cmd.getNotes()) {
                sender.sendMessage("§e" + note);
            }
        }
    }

    public boolean hasPermission(CommandSender sender, String permString) {
        if (!(sender instanceof Player) || permString == null || permString.isEmpty()) {
            return true;
        }

        Player player = (Player) sender;
        if (DependencyUtils.hasPermission()) {
            return DependencyUtils.getPermission().has(player, permString);
        }
        return player.hasPermission(permString);
    }
}
 public class AttackCommand extends BasicCommand
{
    private RiderManager riderManager;
    private GoalManager goalManager;

    public AttackCommand(MobRider plugin)
    {
        super("Attack");
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Attack another player or mob");
        setUsage("/mob attack §9<player|mobs>");
        setArgumentRange(1, 1);
        setIdentifiers("attack");
        setPermission("mobrider.command.attack");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (riderManager.isRider(player)) {
                Rider rider = riderManager.getRider(player);
                goalManager.setAttackGoal(rider, args[0]);
            }
            else {
                sender.sendMessage("You must be riding a mob to use this command!");
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }
}
 public class FollowCommand extends BasicCommand
{
    private RiderManager riderManager;
    private GoalManager goalManager;

    public FollowCommand(MobRider plugin)
    {
        super("Follow");
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Follow another player or mob");
        setUsage("/mob follow §9<player|mob>");
        setArgumentRange(1, 1);
        setIdentifiers("follow");
        setPermission("mobrider.command.follow");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (riderManager.isRider(player)) {
                Rider rider = riderManager.getRider(player);
                goalManager.setFollowGoal(rider, args[0]);
            }
            else {
                sender.sendMessage("You must be riding a mob to use this command!");
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }
}
 public class GoCommand extends BasicCommand
{
    private ConfigManager configManager;
    private RiderManager riderManager;
    private GoalManager goalManager;

    public GoCommand(MobRider plugin)
    {
        super("Go");
        configManager = plugin.getConfigManager();
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Travel a direction with optional distance");
        setUsage("/mob go §9<direction> [distance]");
        setArgumentRange(1, 2);
        setIdentifiers("go");
        setPermission("mobrider.command.go");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (riderManager.isRider(player)) {
                Rider rider = riderManager.getRider(player);

                if (args.length == 1 && DirectionType.fromName(args[0]) != null) {
                    goalManager.setDirection(rider, DirectionType.fromName(args[0]).getDirection());
                }
                else if (args.length == 2 && DirectionType.fromName(args[0]) != null && EntityUtils.isInteger(args[1])) {
                    goalManager.setDirection(rider, DirectionType.fromName(args[0]).getDirection(), Integer.parseInt(args[1]));
                }
                else {
                    MessageUtils.sendMessage(rider, configManager.goConfusedMessage);
                }
            }
            else {
                sender.sendMessage("You must be riding a mob to use this command!");
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }
}
 public class GotoCommand extends BasicCommand
{
    private static final double INTERIM_DISTANCE_SQUARED = 64.0D;

    private ConfigManager configManager;
    private RiderManager riderManager;
    private GoalManager goalManager;

    public GotoCommand(MobRider plugin)
    {
        super("Goto");
        configManager = plugin.getConfigManager();
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Go to a player, mob or location");
        setUsage("/mob goto §9<player|mob|location> | <x> <z>");
        setArgumentRange(1, 2);
        setIdentifiers("goto");
        setPermission("mobrider.command.goto");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (riderManager.isRider(player)) {
                Rider rider = riderManager.getRider(player);

                if (args.length == 1) {
                    goalManager.setGotoGoal(rider, args[0]);
                }
                else if (args.length == 2 && EntityUtils.isInteger(args[0]) && EntityUtils.isInteger(args[1])) {
                    goalManager.setDestination(rider, new Location(rider.getWorld(), Integer.parseInt(args[0]), INTERIM_DISTANCE_SQUARED, Integer.parseInt(args[1])));
                }
                else {
                    MessageUtils.sendMessage(rider, configManager.goConfusedMessage);
                }
            }
            else {
                sender.sendMessage("You must be riding a mob to use this command!");
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }
}
 public class HelpCommand extends BasicCommand
{
    private static final int CMDS_PER_PAGE = 8;
    private CommandHandler commandHandler;

    public HelpCommand(MobRider plugin)
    {
        super("Help");
        this.commandHandler = plugin.getCommandHandler();
        setDescription("Displays the help menu");
        setUsage("/mob help §8[page#]");
        setArgumentRange(0, 1);
        setIdentifiers("mob", "help");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        int page = 0;
        if (args.length != 0) {
            try {
                page = Integer.parseInt(args[0]) - 1;
            }
            catch (NumberFormatException ignored) {
            }
        }

        List<Command> commands = getCommandsForSender(sender);

        int numPages = commands.size() / CMDS_PER_PAGE;
        if (commands.size() % CMDS_PER_PAGE != 0) {
            numPages++;
        }

        if (page >= numPages || page < 0) {
            page = 0;
        }

        sender.sendMessage("§c-----[ " + "§fMobRider Help <" + (page + 1) + "/" + numPages + ">§c ]-----");
        int start = page * CMDS_PER_PAGE;
        int end = start + CMDS_PER_PAGE;
        if (end > commands.size()) {
            end = commands.size();
        }
        for (int c = start; c < end; c++) {
            Command cmd = commands.get(c);
            sender.sendMessage("  §a" + cmd.getUsage());
        }

        sender.sendMessage("§cFor more info on a particular command, type §f/<command> ?");

        return true;
    }

    private List<Command> getCommandsForSender(CommandSender sender)
    {
        List<Command> commands = new ArrayList<Command>();

        // Build list of permitted commands
        for (Command command : commandHandler.getCommands()) {
            if (command.isShownOnHelpMenu() && commandHandler.hasPermission(sender, command.getPermission())) {
                commands.add(command);
            }
        }

        return commands;
    }
}
 public class MountCommand extends BasicCommand
{
    private ConfigManager configManager;
    private RiderManager riderManager;
    private GoalManager goalManager;

    public MountCommand(MobRider plugin)
    {
        super("Mount");
        configManager = plugin.getConfigManager();
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Mount nearby mob");
        setUsage("/mob mount");
        setArgumentRange(0, 0);
        setIdentifiers("mount");
        setPermission("mobrider.command.mount");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;
            Entity vehicle = player.getVehicle();

            if (vehicle instanceof LivingEntity) {
                riderManager.removeRider(player);
            }
            else {
                LivingEntity target = EntityUtils.getNearByTarget(player, configManager.mountRange);
                if (player.getItemInHand().getType() == Material.SADDLE && RiderManager.canRide(player, target)) {
                    target.setPassenger(player);
                    Rider rider = riderManager.addRider(player);
                    goalManager.setStopGoal(rider);
                }
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }

}
 public class ReloadCommand extends BasicCommand
{
    private MobRider plugin;

    public ReloadCommand(MobRider plugin)
    {
        super("Reload");
        this.plugin = plugin;
        setDescription("Reload configuration");
        setUsage("/mob reload");
        setArgumentRange(0, 0);
        setIdentifiers("reload");
        setPermission("mobrider.admin.reload");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        plugin.reloadConfig();
        sender.sendMessage("MobRider config reloaded.");
        return true;
    }
}
 public class StopCommand extends BasicCommand
{
    private RiderManager riderManager;
    private GoalManager goalManager;

    public StopCommand(MobRider plugin)
    {
        super("Stop");
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
        setDescription("Stop your mob");
        setUsage("/mob stop");
        setArgumentRange(0, 0);
        setIdentifiers("stop");
        setPermission("mobrider.command.stop");
    }

    @Override
    public boolean execute(CommandSender sender, String identifier, String[] args)
    {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (riderManager.isRider(player)) {
                Rider rider = riderManager.getRider(player);
                goalManager.setStopGoal(rider);
            }
            else {
                sender.sendMessage("You must be riding a mob to use this command!");
            }
        }
        else {
            sender.sendMessage("Console cannot control mobs!");
        }

        return true;
    }
}
 public final class DependencyUtils
{
    private static Plugin vaultPlugin;
    private static WorldGuardPlugin worldGuardPlugin;
    private static DestinationFactory destinationFactory;
    private static Residence residencePlugin;
    private static RegiosAPI regiosAPI;
    private static Towny townyPlugin;
    private static Plugin factionsPlugin;
    private static Citizens citizensPlugin;

    private static Permission permission;
    private static Economy economy;

    private DependencyUtils()
    {
    }

    public static void init()
    {
        initPlugins();
        initVault();
    }

    private static void initPlugins()
    {
        vaultPlugin = getPlugin("Vault", "net.milkbowl.vault.Vault");
        worldGuardPlugin = (WorldGuardPlugin) getPlugin("WorldGuard", "com.sk89q.worldguard.bukkit.WorldGuardPlugin");
        residencePlugin = (Residence) getPlugin("Residence", "com.bekvon.bukkit.residence.Residence");
        citizensPlugin = (Citizens) getPlugin("Citizens", "net.citizensnpcs.Citizens");
        townyPlugin = (Towny) getPlugin("Towny", "com.palmergames.bukkit.towny.Towny");
        factionsPlugin = getPlugin("Factions", "com.massivecraft.factions.P");

        Plugin regiosPlugin = getPlugin("Regios", "net.jzx7.regiosapi.RegiosAPI");
        if (regiosPlugin != null) {
            regiosAPI = (RegiosAPI) regiosPlugin;
        }

        Plugin multiversePlugin = getPlugin("Multiverse-Core", "com.onarandombox.MultiverseCore.MultiverseCore");
        if (multiversePlugin != null) {
            destinationFactory = ((MultiverseCore) multiversePlugin).getDestFactory();
        }
    }

    private static void initVault()
    {
        if (hasVault()) {
            RegisteredServiceProvider<Permission> permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class);
            if (permissionProvider != null) {
                permission = permissionProvider.getProvider();
                LoggerUtil.getInstance().info("Found permission provider " + permission.getName());
            }

            RegisteredServiceProvider<Economy> economyProvider = Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
            if (economyProvider != null) {
                economy = economyProvider.getProvider();
                LoggerUtil.getInstance().info("Found economy provider " + economy.getName());
            }
        }

        if (!hasPermission()) {
            LoggerUtil.getInstance().warning("Did not find permission provider");
        }

        if (!hasEconomy()) {
            LoggerUtil.getInstance().warning("Did not find economy provider");
        }
    }

    public static boolean hasPermission(Player player, String perm)
    {
        if (hasPermission()) {
            return permission.has(player, perm);
        }
        else {
            return player.hasPermission(perm);
        }
    }

    public static boolean hasPermission()
    {
        return permission != null;
    }

    public static Permission getPermission()
    {
        return permission;
    }

    public static boolean hasEconomy()
    {
        return economy != null;
    }

    public static Economy getEconomy()
    {
        return economy;
    }

    private static boolean hasVault()
    {
        return vaultPlugin != null;
    }

    public static boolean hasCitizens()
    {
        boolean hasCitizens = false;

        try {
            hasCitizens = citizensPlugin != null && Double.parseDouble(citizensPlugin.getDescription().getVersion()) < 2.0;
        }
        catch (NumberFormatException e) {
            // do nothing
        }

        return hasCitizens;
    }

    public static boolean hasCitizens2()
    {
        boolean hasCitizens2 = false;

        try {
            hasCitizens2 = citizensPlugin != null && Double.parseDouble(citizensPlugin.getDescription().getVersion()) >= 2.0;
        }
        catch (NumberFormatException e) {
            // do nothing
        }

        return hasCitizens2;
    }

    public static Plugin getCitizens()
    {
        return citizensPlugin;
    }

    public static boolean hasResidence()
    {
        return residencePlugin != null;
    }

    public static boolean hasRegios()
    {
        return regiosAPI != null;
    }

    public static RegiosAPI getRegiosAPI()
    {
        return regiosAPI;
    }

    public static boolean hasWorldGuard()
    {
        return worldGuardPlugin != null;
    }

    public static RegionManager getRegionManager(World world)
    {
        return worldGuardPlugin.getRegionManager(world);
    }

    public static boolean hasMultiverse()
    {
        return destinationFactory != null;
    }

    public static DestinationFactory getMVDestinationFactory()
    {
        return destinationFactory;
    }

    public static boolean hasTowny()
    {
        return townyPlugin != null;
    }

    public static boolean hasFactions()
    {
        return factionsPlugin != null;
    }

    private static Plugin getPlugin(String pluginName, String className)
    {
        Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginName);
        try {
            Class<?> testClass = Class.forName(className);
            if (testClass.isInstance(plugin) && plugin.isEnabled()) {
                LoggerUtil.getInstance().info("Found plugin " + plugin.getDescription().getName());
                return plugin;
            }
        }
        catch (ClassNotFoundException e) {
            LoggerUtil.getInstance().warning("Did not find plugin " + pluginName);
        }
        return null;
    }
} public final class LoggerUtil
{
    private static final String LOG_NAME = "MobRider";
    private static LoggerUtil instance = new LoggerUtil();

    private Logger logger;
    private String name;
    private boolean isDebug;

    public static LoggerUtil getInstance()
    {
        return instance;
    }

    private LoggerUtil()
    {
        logger = Logger.getLogger("Minecraft");
        isDebug = false;
        name = LOG_NAME;
    }

    public boolean isDebug()
    {
        return isDebug;
    }

    public void setDebug(boolean isDebug)
    {
        this.isDebug = isDebug;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public void info(String msg)
    {
        logger.info(format(msg));
    }

    public void warning(String msg)
    {
        logger.warning(format(msg));
    }

    public void severe(String msg)
    {
        logger.severe(format(msg));
    }

    public void debug(String msg)
    {
        if (isDebug) {
            logger.info(format("DEBUG: " + msg));
        }
    }

    public String format(String msg)
    {
        return String.format("[%s] %s", name, msg);
    }
}
 public class UpdateTask implements Runnable
{
    private static final String DEV_BUKKIT_URL = "http://dev.bukkit.org/server-mods/mobrider";
    private static final long CHECK_DELAY = 0;
    private static final long CHECK_PERIOD = 432000;

    private String pluginName;
    private String pluginVersion;
    private String latestVersion;

    public UpdateTask(MobRider plugin)
    {
        pluginName = plugin.getName();
        pluginVersion = plugin.getDescription().getVersion().split("-")[0];
        latestVersion = pluginVersion;

        BukkitTask task = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, this, CHECK_DELAY, CHECK_PERIOD);
        if (task.getTaskId() < 0) {
            LoggerUtil.getInstance().warning("Failed to schedule UpdateTask task.");
        }
    }

    public void setPluginName(String pluginName)
    {
        this.pluginName = pluginName;
    }

    public String getPluginName()
    {
        return pluginName;
    }

    private void getLatestVersion()
    {
        try {
            URL url = new URL(DEV_BUKKIT_URL + "/files.rss");
            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.openConnection().getInputStream());
            doc.getDocumentElement().normalize();
            NodeList nodes = doc.getElementsByTagName("item");
            Node firstNode = nodes.item(0);
            if (firstNode.getNodeType() == 1) {
                Element firstElement = (Element) firstNode;
                NodeList firstElementTagName = firstElement.getElementsByTagName("title");
                Element firstNameElement = (Element) firstElementTagName.item(0);
                NodeList firstNodes = firstNameElement.getChildNodes();
                latestVersion = firstNodes.item(0).getNodeValue().replace(pluginName, "").replaceFirst("v", "").trim();
            }
        }
        catch (Exception e) {
            LoggerUtil.getInstance().warning(e.getMessage());
        }
    }

    private boolean isOutOfDate()
    {
        boolean isOutOfDate = false;

        getLatestVersion();
        try {
            isOutOfDate = Double.parseDouble(pluginVersion.replaceFirst("\\.", "")) < Double.parseDouble(latestVersion.replaceFirst("\\.", ""));
        }
        catch (NumberFormatException e) {
            LoggerUtil.getInstance().warning(e.getMessage());
        }

        return isOutOfDate;
    }

    @Override
    public void run()
    {
        if (isOutOfDate()) {
            LoggerUtil.getInstance().warning(pluginName + " " + latestVersion + " is out! You are running: " + pluginName + " " + pluginVersion);
            LoggerUtil.getInstance().warning("Update MobRider at: " + DEV_BUKKIT_URL);
        }
    }
}
 public class GoalManager
{
    private ConfigManager configManager;
    private static final List<LivingEntitySearch> findEntityStrategies = new ArrayList<LivingEntitySearch>();
    private static final List<LocationSearch> findLocationStrategies = new ArrayList<LocationSearch>();

    static {
        findEntityStrategies.add(new EntityIdSearchStrategy());
        findEntityStrategies.add(new PlayerSearchStrategy());
        findEntityStrategies.add(new CitizensSearchStrategy());
        findEntityStrategies.add(new Citizens2SearchStrategy());
        findEntityStrategies.add(new MobSearchStrategy());

        findLocationStrategies.add(new PortalSearchStrategy());
        findLocationStrategies.add(new ResidenceSearchStrategy());
        findLocationStrategies.add(new RegionSearchStrategy());
        findLocationStrategies.add(new RegiosSearchStrategy());
        findLocationStrategies.add(new TownSearchStrategy());
        findLocationStrategies.add(new FactionSearchStrategy());
    }

    public GoalManager(MobRider plugin)
    {
        configManager = plugin.getConfigManager();
    }

    public void update(Rider rider)
    {
        if (rider.hasGoal()) {
            if (rider.getGoal().isGoalDone()) {
                setStopGoal(rider);
            }
            rider.getGoal().update(rider, configManager.goalRange);
        }
    }

    public void setStopGoal(Rider rider)
    {
        if (!(rider.getGoal() instanceof StopGoal)) {
            rider.setGoal(new StopGoal());
            MessageUtils.sendMessage(rider, configManager.stopConfirmedMessage);
        }
    }

    public void setFollowGoal(Rider rider, String entityName)
    {
        LivingEntity entity = findLivingEntity(rider, entityName, configManager.maxSearchRange);

        if (entity != null) {
            rider.setGoal(new FollowGoal(entity));
            MessageUtils.sendMessage(rider, configManager.followConfirmedMessage);
        }
        else {
            MessageUtils.sendMessage(rider, configManager.followConfusedMessage);
        }
    }

    public void setGotoGoal(Rider rider, String goalName)
    {
        LivingEntity entity = findLivingEntity(rider, goalName, configManager.maxSearchRange);

        if (entity != null) {
            rider.setGoal(new LivingEntityGoal(entity));
            MessageUtils.sendMessage(rider, configManager.goConfirmedMessage);
        }
        else if (findLocation(rider, goalName)) {
            MessageUtils.sendMessage(rider, configManager.goConfirmedMessage);
        }
        else {
            MessageUtils.sendMessage(rider, configManager.goConfusedMessage);
        }
    }

    public void setAttackGoal(Rider rider, String entityName)
    {
        LivingEntity entity = findLivingEntity(rider, entityName, configManager.attackRange);

        if (entity != null) {
            setAttackGoal(rider, entity);
        }
        else {
            MessageUtils.sendMessage(rider, configManager.attackConfusedMessage);
        }
    }

    public void setAttackGoal(Rider rider, LivingEntity entity)
    {
        if (EntityUtils.isAggressive(rider.getRide())) {
            rider.setGoal(new AttackGoal(entity));
            MessageUtils.sendMessage(rider, configManager.attackConfirmedMessage);
        }
        else {
            MessageUtils.sendMessage(rider, configManager.attackConfusedMessage);
        }
    }

    public void setDirection(Rider rider, Vector direction)
    {
        setDirection(rider, direction, configManager.maxTravelDistance);
    }

    public void setDirection(Rider rider, Vector direction, int distance)
    {
        if (direction != null) {
            setDestination(rider, convertDirectionToLocation(rider, direction.normalize().multiply(Math.min(configManager.maxTravelDistance, distance))));
        }
        else {
            MessageUtils.sendMessage(rider, configManager.goConfusedMessage);
        }
    }

    public void setDestination(Rider rider, Location location)
    {
        if (location.getWorld().equals(rider.getWorld())) {
            rider.setGoal(new LocationGoal(location));
            // MessageUtils.sendMessage(rider, configManager.goConfirmedMessage);
        }
        else {
            MessageUtils.sendMessage(rider, configManager.goConfusedMessage);
        }
    }

    private static Location convertDirectionToLocation(Rider rider, Vector direction)
    {
        Location location = null;
        LivingEntity ride = rider.getRide();

        if (ride != null) {
            Location rideLocation = ride.getLocation();
            location = rider.getWorld().getHighestBlockAt(rideLocation.getBlockX() + direction.getBlockX(), rideLocation.getBlockZ() + direction.getBlockZ())
                    .getLocation();
        }

        return location;
    }

    private static LivingEntity findLivingEntity(Rider rider, String searchTerm, double searchRange)
    {
        LivingEntity foundEntity = null;

        for (LivingEntitySearch strategy : findEntityStrategies) {
            foundEntity = strategy.find(rider, searchTerm, searchRange);

            if (foundEntity != null) {
                return foundEntity;
            }
        }

        return foundEntity;
    }

    private static boolean findLocation(Rider rider, String locationName)
    {
        for (LocationSearch strategy : findLocationStrategies) {
            if (strategy.find(rider, locationName)) {
                return true;
            }
        }

        return false;
    }
} public class RiderDamageListener implements Listener
{
    private RiderManager riderManager;
    private GoalManager goalManager;

    public RiderDamageListener(MobRider plugin)
    {
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
    }

    @EventHandler(priority = EventPriority.MONITOR)
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event)
    {
        if (event.isCancelled()) {
            return;
        }

        Entity entity = event.getEntity();
        Entity damager = event.getDamager();

        if (damager instanceof Projectile) {
            damager = (Entity) ((Projectile) damager).getShooter();
        }

        // rider damaged by entity
        if (entity instanceof Player) {

            Rider rider = riderManager.getRider((Player) entity);

            if (rider.isValid()) {
                LivingEntity ride = rider.getRide();

                if (damager.equals(ride) && !(damager instanceof Player)) {
                    event.setCancelled(true); // riders get in the way of
                                              // skeleton arrows
                }
                else if (!damager.equals(ride) && !damager.equals(rider.getTarget())) {
                    goalManager.setAttackGoal(rider, (LivingEntity) damager);
                    return;
                }
            }
        }

        // entity damaged by rider
        if (damager instanceof Player) {

            Rider rider = riderManager.getRider((Player) damager);

            if (rider.isValid()) {
                LivingEntity ride = rider.getRide();

                if (!entity.equals(ride) && !entity.equals(rider.getTarget())) {
                    goalManager.setAttackGoal(rider, (LivingEntity) entity);
                    return;
                }
            }
        }

        // ride damaged by entity
        if (damager instanceof LivingEntity && entity.getPassenger() instanceof Player) {
            Player player = (Player) entity.getPassenger();
            Rider rider = riderManager.getRider((Player) entity.getPassenger());

            if (rider.isValid() && !damager.equals(player)) {
                goalManager.setAttackGoal(rider, (LivingEntity) damager);
            }
        }
    }

    @EventHandler(priority = EventPriority.MONITOR)
    public void onEntityDamageByBlock(EntityDamageByBlockEvent event)
    {
        Entity entity = event.getEntity();

        if (entity instanceof Player) {
            // rider damaged by drowning or suffocation
            Rider rider = riderManager.getRider((Player) entity);

            if (rider.isValid()) {
                switch (event.getCause()) {
                    case SUFFOCATION:
                        event.setCancelled(true);
                        break;
                    case DROWNING:
                        if (rider.hasWaterCreature()) {
                            event.setCancelled(true);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
 public class RiderTargetListener implements Listener
{
    public RiderTargetListener()
    {
    }

    @EventHandler(priority = EventPriority.NORMAL)
    public void onEntityTarget(EntityTargetEvent event)
    {
        if (event.isCancelled()) {
            return;
        }

        Entity passenger = event.getEntity().getPassenger();
        Entity target = event.getTarget();

        if ((passenger != null) && (target != null) && (target.equals(passenger))) {
            event.setCancelled(true);
        }
    }
}
 public class RiderPlayerListener implements Listener
{
    private static final int FIRST_SLOT = 0;
    private static final int LAST_SLOT = 8;
    private static final float SPEED_INCREMENT = 0.05F;
    
    private ConfigManager configManager;
    private RiderManager riderManager;
    private GoalManager goalManager;

    public RiderPlayerListener(MobRider plugin)
    {
        configManager = plugin.getConfigManager();
        riderManager = plugin.getRiderManager();
        goalManager = plugin.getGoalManager();
    }

    @EventHandler(priority = EventPriority.MONITOR)
    public void onPlayerInteract(PlayerInteractEvent event)
    {
        Player player = event.getPlayer();

        if (player.getItemInHand().getType() == configManager.controlItem && riderManager.isRider(player) && !riderManager.getRider(player).getGoal().isWithinHysteresisThreshold()) {
            if (event.getAction() == Action.LEFT_CLICK_AIR) {
                goalManager.setDirection(riderManager.getRider(player), player.getLocation().getDirection().normalize());
            }
            else if (event.getAction() == Action.RIGHT_CLICK_AIR) {
                goalManager.setStopGoal(riderManager.getRider(player));
            }
        }
    }

    @EventHandler(priority = EventPriority.MONITOR)
    public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
    {
        Player player = event.getPlayer();
        Entity vehicle = player.getVehicle();
        Entity target = event.getRightClicked();

        if (vehicle instanceof LivingEntity && vehicle.equals(target) && riderManager.isRider(player)) {
            if (configManager.isFood(player.getItemInHand().getType())) {
                riderManager.feedRide(riderManager.getRider(player));
            }
            else {
                riderManager.removeRider(player);
            }

            if (vehicle instanceof Pig) {
                event.setCancelled(true);
            }
        }
        else if (player.getItemInHand().getType() == Material.SADDLE && RiderManager.canRide(player, target)) {
            target.setPassenger(player);
            goalManager.setStopGoal(riderManager.addRider(player));
        }
        else if (target instanceof Pig && ((Pig) target).hasSaddle() && RiderManager.canRide(player, target)) {
            target.setPassenger(player);
            goalManager.setStopGoal(riderManager.addRider(player));
            event.setCancelled(true);
        }
    }

    @EventHandler(priority = EventPriority.MONITOR)
    public void onItemHeldChange(PlayerItemHeldEvent event)
    {
        Player player = event.getPlayer();

        // Holding down SHIFT(sneak) and mouse scrolling adjusts speed
        if (riderManager.isRider(player) && player.isSneaking()) {
            int newSlot = event.getNewSlot();
            int prevSlot = event.getPreviousSlot();
            boolean increase = (prevSlot - newSlot) > 0;

            if (((prevSlot == FIRST_SLOT) && (newSlot == LAST_SLOT)) || ((prevSlot == LAST_SLOT) && (newSlot == FIRST_SLOT))) {
                increase = !increase;
            }

            Rider rider = riderManager.getRider(player);
            rider.setSpeed(increase ? rider.getSpeed() + SPEED_INCREMENT : rider.getSpeed() - SPEED_INCREMENT);
        }
    }
}
 public class RideMetrics
{
    private Map<String, Integer> typeCount;
    private Metrics metrics;
    private Graph graph;

    public RideMetrics(Plugin plugin)
    {
        try {
            metrics = new Metrics(plugin);
        }
        catch (IOException e) {
            LoggerUtil.getInstance().warning("Metrics failed to load.");
        }

        if (metrics != null) {
            typeCount = new Hashtable<String, Integer>();
            graph = metrics.createGraph("Ride Types");
            metrics.start();
        }
    }

    public void addCount(EntityType rideType)
    {
        addCount(getRideTypeName(rideType));
    }

    private void addCount(String name)
    {
        if (name == null) {
            LoggerUtil.getInstance().warning("Null type name passed into metrics.");
            return;
        }

        if (graph != null) {
            if (!typeCount.containsKey(name)) {
                typeCount.put(name, 0);
                graph.addPlotter(new Plotter(name) {
                    @Override
                    public int getValue()
                    {
                        return typeCount.get(getColumnName());
                    }
                });
            }

            typeCount.put(name, typeCount.get(name) + 1);
        }
    }

    private String getRideTypeName(EntityType rideType)
    {
        return rideType.getName() != null ? rideType.getName() : rideType.toString();
    }
} public class RiderManager implements Runnable
{
    private static final String SPAWNEGG_TAG_MDID = "MobRider.spawnEgg";
    private static final long UPDATE_DELAY = 0L;
    private static final long MAX_UPDATE_PERIOD = 20L;
    private static final int HEALTH_INCREMENT = 5;
    private static Random random = new Random();

    private MobRider plugin;
    private RideMetrics metrics;
    private ConfigManager configManager;
    private GoalManager goalManager;
    private Map<String, Rider> riders;

    private final FixedMetadataValue spawnEggTag;
    
    public RiderManager(MobRider plugin)
    {
        this.plugin = plugin;
        metrics = plugin.getMetricsManager();
        configManager = plugin.getConfigManager();
        goalManager = plugin.getGoalManager();

        riders = new ConcurrentHashMap<String, Rider>();
        spawnEggTag = new FixedMetadataValue(plugin, true);

        if (Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this, UPDATE_DELAY, Math.min(configManager.updatePeriod, MAX_UPDATE_PERIOD)) < 0) {
            Bukkit.getPluginManager().disablePlugin(plugin);
            LoggerUtil.getInstance().severe("Failed to schedule RiderManager task.");
        }
    }

    @Override
    public void run()
    {
        for (Entry<String, Rider> entry : riders.entrySet()) {
            String playerName = entry.getKey();
            Rider rider = entry.getValue();

            if (rider.isValid()) {
                goalManager.update(rider);
            }
            else {
                rider.setTarget(null);
                riders.remove(playerName);
            }
        }
    }

    public Rider addRider(Player player)
    {
        Rider rider = null;

        if (player != null) {
            String playerName = player.getName();
            rider = new Rider(playerName);
            goalManager.setStopGoal(rider);
            riders.put(playerName, rider);

            if (rider.getRide() != null) {
                metrics.addCount(rider.getRide().getType());
            }
        }

        return rider != null ? rider : new Rider(null);
    }

    public void removeRider(Player player)
    {
        Entity entity = player.getVehicle();

        if (entity instanceof LivingEntity) {
            LivingEntity target = (LivingEntity) entity;
            entity.eject();
            if (DependencyUtils.hasPermission(player, "mobrider.spawnegg")) {
                scheduleSpawnEgg(target);
            }
        }
    }

    private void scheduleSpawnEgg(LivingEntity target)
    {
        synchronized (target) {
            if (hasSpawnEgg(target) && !target.hasMetadata(SPAWNEGG_TAG_MDID)) {
                target.setMetadata(SPAWNEGG_TAG_MDID, spawnEggTag);
                SpawnEggTask spawnEggTask = new SpawnEggTask(target);
                spawnEggTask.setTaskId(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, spawnEggTask, 0, 1));
            }
        }
    }

    private static boolean hasSpawnEgg(Entity entity)
    {
        boolean hasSpawnEgg = false;

        if (entity instanceof LivingEntity) {
            EntityType type = entity.getType();
            switch (type) {
                case ENDER_DRAGON:
                case GIANT:
                case SNOWMAN:
                case IRON_GOLEM:
                case PLAYER:
                    hasSpawnEgg = false;
                    break;
                default:
                    hasSpawnEgg = true;
            }
        }

        return hasSpawnEgg;
    }

    public Rider getRider(Player player)
    {
        Rider rider = null;

        if (player != null) {
            rider = riders.get(player.getName());
        }

        return rider != null ? rider : new Rider(null);
    }

    public boolean isRider(Player player)
    {
        if (player != null) {
            Entity vehicle = player.getVehicle();
            if (vehicle instanceof LivingEntity) {
                if (!riders.containsKey(player.getName())) {
                    addRider(player);
                }
                return true;
            }
        }
        return false;
    }

    public void feedRide(Rider rider)
    {
        if (rider.isFullHealth()) {
            MessageUtils.sendMessage(rider, configManager.fedConfusedMessage);
        }
        else {
            rider.setHealth(Math.min(rider.getHealth() + HEALTH_INCREMENT, rider.getMaxHealth()));
            EntityUtils.removeItemInHand(rider.getPlayer());
            MessageUtils.sendMessage(rider, configManager.fedConfirmedMessage);
        }
    }

    public static boolean canRide(Player player, Entity entity)
    {
        return isAllowed(player, entity) && (player.isOp() || isOwner(player, entity) || isWinner(player, entity) && isWithdrawSuccess(player, entity));
    }

    private static boolean isAllowed(Player player, Entity entity)
    {
        if (player == null || entity == null) {
            return false;
        }

        if (entity.getPassenger() != null) {
            player.sendMessage("That creature already has a rider.");
            return false;
        }

        if (entity instanceof Animals || entity instanceof Squid || entity instanceof Golem || entity instanceof Villager || entity instanceof Bat) {
            if (DependencyUtils.hasPermission(player, "mobrider.animals") || DependencyUtils.hasPermission(player, "mobrider.animals." + EntityUtils.getCreatureName(entity).toLowerCase())) {
                return true;
            }
            else {
                player.sendMessage("You do not have permission to ride that animal.");
                return false;
            }
        }

        if (entity instanceof Monster || entity instanceof Ghast || entity instanceof Slime || entity instanceof EnderDragon) {
            if (DependencyUtils.hasPermission(player, "mobrider.monsters") || DependencyUtils.hasPermission(player, "mobrider.monsters." + EntityUtils.getCreatureName(entity).toLowerCase())) {
                return true;
            }
            else {
                player.sendMessage("You do not have permission to ride that monster.");
                return false;
            }
        }

        if (entity instanceof Player) {
            if (DependencyUtils.hasPermission(player, "mobrider.players") || DependencyUtils.hasPermission(player, "mobrider.players." + ((Player) entity).getName().toLowerCase())) {
                return true;
            }
            else {
                player.sendMessage("You do not have permission to ride that player.");
                return false;
            }
        }

        return false;
    }

    private static boolean isWinner(Player player, Entity entity)
    {
        boolean isWinner = RideType.fromType(entity.getType()) == null || random.nextDouble() * 100D < RideType.fromType(entity.getType()).getChance();

        if (!isWinner && player != null) {
            player.sendMessage("You have bad luck trying to ride that creature.");
        }

        return isWinner;
    }

    private static boolean isWithdrawSuccess(Player player, Entity entity)
    {
        if (!DependencyUtils.hasEconomy()) {
            return true;
        }

        if (player == null || entity == null) {
            return false;
        }

        double cost = RideType.fromType(entity.getType()).getCost();

        if (cost == 0.0) {
            return true;
        }

        EconomyResponse response = DependencyUtils.getEconomy().withdrawPlayer(Bukkit.getOfflinePlayer(player.getName()), cost);
        if (response.transactionSuccess()) {
            player.sendMessage("You were charged " + DependencyUtils.getEconomy().format(response.amount) + " for riding this creature.");
        }
        else {
            player.sendMessage("You have insufficient funds to ride that creature.");
        }

        return response.transactionSuccess();
    }

    private static boolean isOwner(Player player, Entity entity)
    {
        if (entity instanceof Tameable) {
            Tameable tameable = (Tameable) entity;

            if (tameable.isTamed() && tameable.getOwner() instanceof Player) {
                Player owner = (Player) tameable.getOwner();
                if (owner.getName().equals(player.getName())) {
                    return true;
                }
            }
        }
        return false;
    }
}

import com.edwardhand.mobrider.commands.BuckCommand;
import com.edwardhand.mobrider.commands.CommandHandler;
import com.edwardhand.mobrider.commands.AttackCommand;
import com.edwardhand.mobrider.commands.FollowCommand;
import com.edwardhand.mobrider.commands.GoCommand;
import com.edwardhand.mobrider.commands.GotoCommand;
import com.edwardhand.mobrider.commands.HelpCommand;
import com.edwardhand.mobrider.commands.MountCommand;
import com.edwardhand.mobrider.commands.ReloadCommand;
import com.edwardhand.mobrider.commands.StopCommand;
import com.edwardhand.mobrider.commons.DependencyUtils;
import com.edwardhand.mobrider.commons.LoggerUtil;
import com.edwardhand.mobrider.commons.UpdateTask;
import com.edwardhand.mobrider.goals.GoalManager;
import com.edwardhand.mobrider.listeners.RiderDamageListener;
import com.edwardhand.mobrider.listeners.RiderTargetListener;
import com.edwardhand.mobrider.listeners.RiderPlayerListener;
import com.edwardhand.mobrider.metrics.RideMetrics;
import com.edwardhand.mobrider.rider.RiderManager;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;

/*
 * This file is part of MobRider.
 *
 * Copyright (c) 2011-2015, R. Ramos <http://github.com/mung3r/>
 * MobRider is licensed under the GNU Lesser General Public License.
 *
 * MobRider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MobRider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.edwardhand.mobrider;



public class MobRider extends JavaPlugin
{
    private CommandHandler commandHandler;
    private RiderManager riderManager;

    private GoalManager goalManager;
