package com.gamingmesh.jobs.commands; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.gamingmesh.jobs.Jobs; import com.gamingmesh.jobs.JobsPlugin; import com.gamingmesh.jobs.container.ActionType; import com.gamingmesh.jobs.container.BoostMultiplier; import com.gamingmesh.jobs.container.Job; import com.gamingmesh.jobs.container.JobInfo; import com.gamingmesh.jobs.container.JobProgression; import com.gamingmesh.jobs.container.JobsPlayer; public class JobsCommands implements CommandExecutor { private static final String label = "jobs"; private static final String packagePath = "com.gamingmesh.jobs.commands.list"; private static final List hidenCommands = Arrays.asList(); Map CommandList = new HashMap(); final String baseCmd = "jobs"; protected JobsPlugin plugin; public JobsCommands(JobsPlugin plugin) { this.plugin = plugin; } public Map getCommands() { return CommandList; } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (sender instanceof Player) { if (!Jobs.getGCManager().canPerformActionInWorld(((Player) sender).getWorld()) && !sender.hasPermission("jobs.disabledworld.commands")) { sender.sendMessage(Jobs.getLanguage().getMessage("general.error.worldisdisabled")); return true; } } if (args.length == 0) return help(sender, 1); if ((args.length == 1 || args.length == 2) && (args[0].equalsIgnoreCase("?") || args[0].equalsIgnoreCase("help"))) { int page = 1; if (args.length == 2) try { page = Integer.parseInt(args[1]); } catch (NumberFormatException e) { sender.sendMessage(Jobs.getLanguage().getMessage("general.error.notNumber")); return true; } return help(sender, page); } String cmd = args[0].toLowerCase(); if (!hasCommandPermission(sender, cmd)) { sender.sendMessage(Jobs.getLanguage().getMessage("general.error.permission")); return true; } String[] myArgs = reduceArgs(args); if (myArgs.length > 0) { if (myArgs[myArgs.length - 1].equals("?")) { sendUsage(sender, cmd); return true; } } Cmd cmdClass = getCmdClass(cmd); if (cmdClass == null) { return help(sender, 1); } boolean back = cmdClass.perform(plugin, sender, myArgs); if (back) return true; if (!(sender instanceof Player)) return help(sender, 1); return help(sender, 1); } private static String[] reduceArgs(String[] args) { if (args.length <= 1) return new String[0]; return Arrays.copyOfRange(args, 1, args.length); } private static boolean hasCommandPermission(CommandSender sender, String cmd) { return sender.hasPermission("jobs.command." + cmd); } private static String getUsage(String cmd) { StringBuilder builder = new StringBuilder(); builder.append(ChatColor.GREEN.toString()); builder.append('/').append(label).append(' '); builder.append(cmd); builder.append(ChatColor.YELLOW); String key = "command." + cmd + ".help.args"; if (Jobs.getLanguage().containsKey(key)) { builder.append(' '); builder.append(Jobs.getLanguage().getMessage(key)); } return builder.toString(); } public static String getUsageNoCmd(String cmd) { StringBuilder builder = new StringBuilder(); builder.append(ChatColor.GREEN.toString()); builder.append('/').append(label).append(' '); builder.append(ChatColor.YELLOW); String key = "command." + cmd + ".help.args"; if (Jobs.getLanguage().containsKey(key)) { builder.append(' '); builder.append(Jobs.getLanguage().getMessage(key)); } return builder.toString(); } public void sendUsage(CommandSender sender, String cmd) { String message = ChatColor.YELLOW + Jobs.getLanguage().getMessage("command.help.output.usage"); message = message.replace("%usage%", getUsage(cmd)); sender.sendMessage(message); sender.sendMessage(ChatColor.YELLOW + "* " + Jobs.getLanguage().getMessage("command." + cmd + ".help.info")); } protected boolean help(CommandSender sender, int page) { Map commands = GetCommands(sender); if (commands.size() == 0) { sender.sendMessage(Jobs.getLanguage().getMessage("general.error.permission")); return true; } commands = sort(commands); int amountToShow = 7; int start = page * amountToShow - amountToShow; int end = page * amountToShow; int TotalPages = commands.size() / amountToShow; if (((commands.size() * 1.0) / (amountToShow * 1.0)) - TotalPages > 0) TotalPages++; if (start >= commands.size()) { start = page * amountToShow; end = start + amountToShow; } if (page > TotalPages || page < 1) { Jobs.getActionBar().send(sender, Jobs.getLanguage().getMessage("general.error.noHelpPage")); return true; } sender.sendMessage(Jobs.getLanguage().getMessage("command.help.output.title")); sender.sendMessage(Jobs.getLanguage().getMessage("command.help.output.page", "[1]", page, "[2]", TotalPages)); int i = -1; for (Entry one : commands.entrySet()) { i++; if (i < start) continue; if (i >= end) break; sender.sendMessage(getUsage(one.getKey()) + " - " + Jobs.getLanguage().getMessage("command." + one.getKey() + ".help.info")); } String prevCmd = "/" + baseCmd + " ? " + (page - 1); String prev = "[\"\",{\"text\":\"" + Jobs.getLanguage().getMessage("command.help.output.prev") + "\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"" + prevCmd + "\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"" + "<<<" + "\"}]}}}"; String nextCmd = "/" + baseCmd + " ? " + (page + 1); String next = " {\"text\":\"" + Jobs.getLanguage().getMessage("command.help.output.next") + "\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"" + nextCmd + "\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"" + ">>>" + "\"}]}}}]"; Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + prev + "," + next); return true; } public static List getClassesFromPackage(String pckgname) throws ClassNotFoundException { List result = new ArrayList(); try { for (URL jarURL : ((URLClassLoader) JobsPlugin.class.getClassLoader()).getURLs()) { try { result.addAll(getClassesInSamePackageFromJar(pckgname, jarURL.toURI().getPath())); } catch (URISyntaxException e) { } } } catch (NullPointerException x) { throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)"); } return result; } private static List getClassesInSamePackageFromJar(String packageName, String jarPath) { JarFile jarFile = null; List listOfCommands = new ArrayList(); try { jarFile = new JarFile(jarPath); Enumeration en = jarFile.entries(); while (en.hasMoreElements()) { JarEntry entry = en.nextElement(); String entryName = entry.getName(); packageName = packageName.replace(".", "/"); if (entryName != null && entryName.endsWith(".class") && entryName.startsWith(packageName)) { String name = entryName.replace(packageName, "").replace(".class", "").replace("/", ""); if (name.contains("$")) name = name.split("\\$")[0]; listOfCommands.add(name); } } } catch (Exception e) { } finally { if (jarFile != null) try { jarFile.close(); } catch (Exception e) { } } return listOfCommands; } public Map GetCommands(CommandSender sender) { Map temp = new HashMap(); for (Entry cmd : CommandList.entrySet()) { if (!hasCommandPermission(sender, cmd.getKey())) continue; temp.put(cmd.getKey(), cmd.getValue()); } return temp; } public void fillCommands() { List lm = new ArrayList(); HashMap> classes = new HashMap>(); try { lm = getClassesFromPackage(packagePath); } catch (ClassNotFoundException e) { e.printStackTrace(); } for (String one : lm) { Class newclass = getClass(one); if (newclass != null) classes.put(one, newclass); } for (Entry> OneClass : classes.entrySet()) { for (Method met : OneClass.getValue().getMethods()) { if (!met.isAnnotationPresent(JobCommand.class)) continue; String cmd = OneClass.getKey(); if (hidenCommands.contains(met.getName().toLowerCase())) continue; CommandList.put(cmd, met.getAnnotation(JobCommand.class).value()); break; } } } private static Class getClass(String cmd) { Class nmsClass = null; try { nmsClass = Class.forName(packagePath + "." + cmd.toLowerCase()); } catch (ClassNotFoundException e) { } catch (IllegalArgumentException e) { } catch (SecurityException e) { } return nmsClass; } private static Cmd getCmdClass(String cmd) { Cmd cmdClass = null; try { Class nmsClass; nmsClass = Class.forName(packagePath + "." + cmd.toLowerCase()); if (Cmd.class.isAssignableFrom(nmsClass)) { cmdClass = (Cmd) nmsClass.getConstructor().newInstance(); } } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { } catch (IllegalArgumentException e) { } catch (InvocationTargetException e) { } catch (NoSuchMethodException e) { } catch (SecurityException e) { } return cmdClass; } private static Map sort(Map unsortMap) { List> list = new LinkedList>(unsortMap.entrySet()); Collections.sort(list, new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return (o1.getValue()).compareTo(o2.getValue()); } }); Map sortedMap = new LinkedHashMap(); for (Iterator> it = list.iterator(); it.hasNext();) { Map.Entry entry = it.next(); sortedMap.put(entry.getKey(), entry.getValue()); } return sortedMap; } /** * Check Job joining permission */ public boolean hasJobPermission(Player sender, Job job) { return hasJobPermission((CommandSender) sender, job); } public boolean hasJobPermission(CommandSender sender, Job job) { if (!sender.hasPermission("jobs.use")) { return false; } return sender.hasPermission("jobs.join." + job.getName().toLowerCase()); } public void sendValidActions(CommandSender sender) { StringBuilder builder = new StringBuilder(); boolean first = true; for (ActionType action : ActionType.values()) { if (!first) builder.append(','); builder.append(action.getName()); first = false; } sender.sendMessage(Jobs.getLanguage().getMessage("command.info.help.actions", "%actions%", builder.toString())); } /** * Displays info about a job * @param player - the player of the job * @param job - the job we are displaying info about * @param type - type of info * @return the message */ public String jobInfoMessage(JobsPlayer player, Job job, String type) { if (job == null) { // job doesn't exist return ChatColor.RED + Jobs.getLanguage().getMessage("general.error.job"); } if (type == null) { type = ""; } else { type = type.toLowerCase(); } StringBuilder message = new StringBuilder(); int showAllTypes = 1; for (ActionType actionType : ActionType.values()) { if (type.startsWith(actionType.getName().toLowerCase())) { showAllTypes = 0; break; } } if (job.getExpBoost() != 1.0) message.append(ChatColor.GOLD + Jobs.getLanguage().getMessage("command.expboost.output.infostats", "%boost%", job.getExpBoost()) + "\n"); if (job.getMoneyBoost() != 1.0) message.append(ChatColor.GOLD + Jobs.getLanguage().getMessage("command.moneyboost.output.infostats", "%boost%", job.getMoneyBoost()) + "\n"); if (job.getPointBoost() != 1.0) message.append(ChatColor.GOLD + Jobs.getLanguage().getMessage("command.pointboost.output.infostats", "%boost%", job.getPointBoost()) + "\n"); if (Jobs.getGCManager().useDynamicPayment) if (job.getBonus() < 0) message.append(ChatColor.GOLD + Jobs.getLanguage().getMessage("command.info.help.penalty", "[penalty]", (int) (job.getBonus() * 100) / 100.0 * -1) + "\n"); else message.append(ChatColor.GOLD + Jobs.getLanguage().getMessage("command.info.help.bonus", "[bonus]", (int) (job.getBonus() * 100) / 100.0) + "\n"); for (ActionType actionType : ActionType.values()) { if (showAllTypes == 1 || type.startsWith(actionType.getName().toLowerCase())) { List info = job.getJobInfo(actionType); if (info != null && !info.isEmpty()) { message.append(jobInfoMessage(player, job, actionType)); } else if (showAllTypes == 0) { String myMessage = Jobs.getLanguage().getMessage("command.info.output." + actionType.getName().toLowerCase() + ".none"); myMessage = myMessage.replace("%jobname%", job.getChatColor() + job.getName() + ChatColor.WHITE); message.append(myMessage); } } } return message.toString(); } /** * Displays info about a particular action * @param player - the player of the job * @param prog - the job we are displaying info about * @param type - the type of action * @return the message */ public static String jobInfoMessage(JobsPlayer player, Job job, ActionType type) { // money exp boost BoostMultiplier finalBoost = Jobs.getPlayerManager().getFinalBonus(player, job); StringBuilder message = new StringBuilder(); message.append(Jobs.getLanguage().getMessage("command.info.output." + type.getName().toLowerCase() + ".info")); message.append(":\n"); int level = 1; JobProgression prog = player.getJobProgression(job); if (prog != null) level = prog.getLevel(); int numjobs = player.getJobProgression().size(); List jobInfo = job.getJobInfo(type); for (JobInfo info : jobInfo) { String materialName = info.getName().toLowerCase().replace('_', ' '); materialName = Character.toUpperCase(materialName.charAt(0)) + materialName.substring(1); materialName = Jobs.getNameTranslatorManager().Translate(materialName, info); materialName = org.bukkit.ChatColor.translateAlternateColorCodes('&', materialName); double income = info.getIncome(level, numjobs); // Jobs.getPlayerManager().getFinalBonus(player, prog) income = income + (income * finalBoost.getMoneyBoost() / 100); String incomeColor = income >= 0 ? "" : ChatColor.DARK_RED.toString(); double xp = info.getExperience(level, numjobs); xp = xp + (xp * finalBoost.getExpBoost() / 100); String xpColor = xp >= 0 ? "" : ChatColor.GRAY.toString(); double points = info.getPoints(level, numjobs); points = points + (points * finalBoost.getPointsBoost() / 100); String pointsColor = xp >= 0 ? "" : ChatColor.RED.toString(); if (income == 0D && points == 0D && xp == 0D) continue; message.append(" "); message.append(Jobs.getLanguage().getMessage("command.info.help.material", "%material%", materialName)); if (prog != null && !info.isInLevelRange(prog.getLevel())) message.append(org.bukkit.ChatColor.RED + " -> "); else message.append(" -> "); if (income != 0.0) message.append(Jobs.getLanguage().getMessage("command.info.help.money", "%money%", incomeColor + String.format("%.2f", income))); if (points != 0.0) message.append(Jobs.getLanguage().getMessage("command.info.help.points", "%points%", pointsColor + String.format("%.2f", points))); if (xp != 0.0) message.append(Jobs.getLanguage().getMessage("command.info.help.exp", "%exp%", xpColor + String.format("%.2f", xp))); if (info.getFromLevel() > 1 && info.getUntilLevel() != -1) message.append(Jobs.getLanguage().getMessage("command.info.help.levelRange", "%levelFrom%", info.getFromLevel(), "%levelUntil%", info.getUntilLevel())); if (info.getFromLevel() > 1 && info.getUntilLevel() == -1) message.append(Jobs.getLanguage().getMessage("command.info.help.levelFrom", "%levelFrom%", info.getFromLevel())); if (info.getFromLevel() == 1 && info.getUntilLevel() != -1) message.append(Jobs.getLanguage().getMessage("command.info.help.levelUntil", "%levelUntil%", info.getUntilLevel())); message.append('\n'); } return message.toString(); } /** * Displays job stats about a particular player's job * @param jobProg - the job progress of the players job * @return the message */ public String jobStatsMessage(JobProgression jobProg) { String message = Jobs.getLanguage().getMessage("command.stats.output", "%joblevel%", Integer.valueOf(jobProg.getLevel()).toString(), "%jobname%", jobProg.getJob().getChatColor() + jobProg.getJob().getName() + ChatColor.WHITE, "%jobxp%", Double.toString(Math.round(jobProg.getExperience() * 100.0) / 100.0), "%jobmaxxp%", Integer.toString(jobProg.getMaxExperience())); return " " + jobProgressMessage(jobProg.getMaxExperience(), jobProg.getExperience()) + " " + message; } public String jobProgressMessage(double max, double current) { String message = ""; String pos = ChatColor.DARK_GREEN + "\u258F"; String pros = ChatColor.YELLOW + "\u258F"; if (current < 0) current = 0; if (max < current) max = current; int percentage = (int) ((current * 50.0) / max); for (int i = 0; i < percentage; i++) { message += pos; } if (50 - percentage < 0) percentage = 50; for (int i = 0; i < 50 - percentage; i++) { message += pros; } return message; } /** * Displays job stats about a particular player's job from archive * @param jobInfo - jobinfo string line * @return the message */ public String jobStatsMessage(String jobInfo) { String[] splited = jobInfo.split(":"); if (Jobs.getJob(splited[0]) == null) return ""; String message = Jobs.getLanguage().getMessage("command.archive.output", "%joblevel%", Integer.valueOf(splited[1]).toString(), "%getbackjoblevel%", Integer.valueOf(splited[2]).toString(), "%jobname%", Jobs.getJob(splited[0]).getChatColor() + splited[0] + ChatColor.WHITE, "%jobxp%", Double.toString(Math.round(Double.valueOf(splited[3]) * 100.0) / 100.0)); return message; } }