PageRenderTime 100ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/src/ltguide/giveto/GiveTo.java

https://github.com/lithium3141/CraftBukkit-GiveTo
Java | 426 lines | 350 code | 76 blank | 0 comment | 128 complexity | 666c1e0618aad3b31e2fdeffddbfdf66 MD5 | raw file
  1. package ltguide.giveto;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.HashSet;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Set;
  14. import java.util.logging.Logger;
  15. import java.util.regex.Matcher;
  16. import java.util.regex.Pattern;
  17. import java.util.regex.PatternSyntaxException;
  18. import org.bukkit.ChatColor;
  19. import org.bukkit.command.Command;
  20. import org.bukkit.command.CommandSender;
  21. import org.bukkit.entity.Player;
  22. import org.bukkit.event.Event;
  23. import org.bukkit.event.Event.Priority;
  24. import org.bukkit.inventory.ItemStack;
  25. import org.bukkit.inventory.PlayerInventory;
  26. import org.bukkit.plugin.Plugin;
  27. import org.bukkit.plugin.java.JavaPlugin;
  28. import org.bukkit.util.config.Configuration;
  29. import org.bukkit.util.config.ConfigurationNode;
  30. import com.nijiko.permissions.PermissionHandler;
  31. import com.nijikokun.bukkit.Permissions.Permissions;
  32. import com.nijikokun.register.payment.Method;
  33. import com.nijikokun.register.payment.Method.MethodAccount;
  34. import com.nijikokun.register.payment.Methods;
  35. public class GiveTo extends JavaPlugin {
  36. private final Logger log = Logger.getLogger("Minecraft");
  37. private Configuration config;
  38. private HashMap<String, Integer> delayPlayers = new HashMap<String, Integer>();
  39. public PermissionHandler Permissions;
  40. public boolean checkPermissions;
  41. public Method Method;
  42. public boolean checkMethod;
  43. public void onDisable() {
  44. delayPlayers.clear();
  45. }
  46. public void onEnable() {
  47. getServer().getPluginManager().registerEvent(Event.Type.PLUGIN_DISABLE, new GiveToServerListener(this), Priority.Monitor, this);
  48. sendLog("v" + getDescription().getVersion() + " enabled (loaded items: " + reload() + ")");
  49. }
  50. private void sendMsg(CommandSender target, String msg) {
  51. sendMsg(target, msg, false);
  52. }
  53. private void sendMsg(CommandSender target, String msg, Boolean log) {
  54. if (target instanceof Player) {
  55. ((Player) target).sendMessage(msg);
  56. if (log) sendLog("->" + ((Player) target).getName() + " " + msg);
  57. }
  58. else sendLog("->*CONSOLE " + msg);
  59. }
  60. private void sendLog(String msg) {
  61. log.info("[" + getDescription().getName() + "] " + ChatColor.stripColor(msg));
  62. }
  63. private boolean writeResource(String resource, File outFile) {
  64. InputStream inStream = getClass().getResourceAsStream(resource);
  65. if (inStream == null) sendLog("unable to find " + resource + " in .jar");
  66. else {
  67. try {
  68. outFile.getParentFile().mkdirs();
  69. OutputStream outStream = new FileOutputStream(outFile);
  70. byte[] buf = new byte[1024];
  71. int len;
  72. while ((len = inStream.read(buf)) > -1)
  73. if (len > 0) outStream.write(buf, 0, len);
  74. inStream.close();
  75. outStream.flush();
  76. outStream.close();
  77. return true;
  78. }
  79. catch (FileNotFoundException e) {
  80. sendLog("error opening file:");
  81. }
  82. catch (IOException e) {
  83. sendLog("io error writing file");
  84. }
  85. }
  86. return false;
  87. }
  88. private int reload() {
  89. Permissions = null;
  90. checkPermissions = true;
  91. Method = null;
  92. checkMethod = false;
  93. if (config == null) config = getConfiguration();
  94. else config.load();
  95. boolean saveConfig = false;
  96. for (CommandMessage message : CommandMessage.values()) {
  97. String key = "messages." + message.name().toLowerCase();
  98. String value = config.getString(key);
  99. if (value == null) {
  100. config.setProperty(key, message.getMessage());
  101. saveConfig = true;
  102. }
  103. else message.setMessage(value);
  104. }
  105. if (saveConfig && !config.save()) sendLog("error saving config file");
  106. Map<String, ConfigurationNode> nodes = config.getNodes("items");
  107. if (nodes == null || nodes.size() == 0) {
  108. sendLog("unable to find any items in config.yml; copying default from .jar");
  109. if (writeResource("/resources/config.yml", new File(getDataFolder(), "config.yml"))) {
  110. config.load();
  111. nodes = config.getNodes("items");
  112. }
  113. }
  114. Pattern pattern = Pattern.compile("\\d+(?::\\d+)?");
  115. for (Map.Entry<String, ConfigurationNode> entry : nodes.entrySet()) {
  116. ConfigurationNode node = entry.getValue();
  117. Boolean discard = false;
  118. List<String> ids = getStringAsList(node, "id");
  119. if (ids.size() == 0) discard = true;
  120. else for (String id : ids)
  121. if (!pattern.matcher(id).matches()) discard = true;
  122. if (node.getDouble("cost", -1) > 0) checkMethod = true;
  123. if (discard) {
  124. sendLog("error in item " + entry.getKey() + "; skipping");
  125. config.removeProperty("items." + entry.getKey());
  126. }
  127. }
  128. if (config.getDouble("cost", -1) > 0) checkMethod = true;
  129. if (checkMethod) {
  130. try {
  131. Class.forName("com.nijikokun.register.payment.Method");
  132. }
  133. catch (ClassNotFoundException e) {
  134. checkMethod = false;
  135. sendLog("cost associated with items; copying Registry library from .jar");
  136. if (writeResource("/resources/Register.jar", new File("lib", "Register.jar"))) sendLog("must RELOAD server to load Registry library (items will be FREE)");
  137. }
  138. }
  139. return config.getKeys("items").size();
  140. }
  141. public Boolean hasPermission(CommandSender sender, String node) {
  142. if (!(sender instanceof Player)) return true;
  143. Player player = (Player) sender;
  144. if (Permissions == null && checkPermissions) {
  145. checkPermissions = false;
  146. Plugin plugin = getServer().getPluginManager().getPlugin("Permissions");
  147. if (plugin != null && plugin.isEnabled()) Permissions = ((Permissions) plugin).getHandler();
  148. if (Permissions == null) sendLog("no compatible permissions plugin found, so defaulting to OPs only");
  149. }
  150. if (Permissions != null) return Permissions.has(player, node);
  151. return player.isOp();
  152. }
  153. public boolean hasMethod() {
  154. if (Method == null && checkMethod) {
  155. checkMethod = false;
  156. Methods Methods = new Methods();
  157. Plugin[] plugins = getServer().getPluginManager().getPlugins();
  158. for (Plugin plugin : plugins)
  159. if (plugin.isEnabled() && Methods.setMethod(plugin)) {
  160. Method = Methods.getMethod();
  161. break;
  162. }
  163. if (Method == null) sendLog("cost associated with items; no compatible ecomony plugin found, so items are FREE");
  164. }
  165. return Method != null;
  166. }
  167. public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
  168. try {
  169. if (!hasPermission(sender, "giveto." + (command.getName().equalsIgnoreCase("giveme") ? "self" : "others"))) throw new CommandException(CommandMessage.PERMISSION);
  170. if (args.length == 0) {
  171. if (hasPermission(sender, "giveto.reload")) sendMsg(sender, CommandMessage.RELOADABLE.toString(label));
  172. throw new CommandException(CommandMessage.ARGLENGTH, command.getUsage().replace("<command>", label));
  173. }
  174. if (args[0].equalsIgnoreCase("reload")) {
  175. if (!hasPermission(sender, "giveto.reload")) throw new CommandException(CommandMessage.PERMISSION);
  176. sendMsg(sender, CommandMessage.RELOADDONE.toString(reload()), true);
  177. return true;
  178. }
  179. int lastArg = args.length - 1;
  180. int firstArg = 1;
  181. int count = 0;
  182. CommandSender to = sender;
  183. if (command.getName().equalsIgnoreCase("giveme")) firstArg--;
  184. else if (!args[0].equalsIgnoreCase("me")) {
  185. List<Player> matches = getServer().matchPlayer(args[0]);
  186. if (matches.size() == 0) throw new CommandException(CommandMessage.NOTARGET);
  187. if (matches.size() > 1) throw new CommandException(CommandMessage.TOOMANYTARGET, joinAsString(matches));
  188. to = matches.get(0);
  189. }
  190. if (!(to instanceof Player)) throw new CommandException(CommandMessage.CONSOLE);
  191. if (firstArg > lastArg) throw new CommandException(CommandMessage.ARGLENGTH, command.getUsage().replace("<command>", label));
  192. if (firstArg < lastArg && args[lastArg].matches("[1-9](?:[0-9]+)?")) {
  193. count = Integer.parseInt(args[lastArg]);
  194. lastArg--;
  195. }
  196. Item item = findItem(joinAsString(args, " ", firstArg, lastArg + 1).trim().toLowerCase());
  197. processItem(sender, count, item);
  198. giveItem(sender, (Player) to, item);
  199. }
  200. catch (CommandException e) {
  201. sendMsg(sender, e.getMessage());
  202. }
  203. return true;
  204. }
  205. private Item findItem(String query) throws CommandException {
  206. short durability = -1;
  207. String text = query;
  208. Matcher m = Pattern.compile("(.+):(\\d+)").matcher(query);
  209. if (m.matches()) {
  210. text = m.group(1);
  211. durability = Short.parseShort(m.group(2));
  212. }
  213. else query += ":-1";
  214. Pattern pattern;
  215. try {
  216. pattern = Pattern.compile(".*" + text.replaceAll("\\*", ".*").replaceAll(" ", ".* .*") + ".*", Pattern.CASE_INSENSITIVE);
  217. }
  218. catch (PatternSyntaxException e) {
  219. throw new CommandException(CommandMessage.BADSEARCH);
  220. }
  221. boolean isId = text.matches("\\d+");
  222. Set<Item> matches = new HashSet<Item>();
  223. Map<String, ConfigurationNode> nodes = config.getNodes("items");
  224. for (Map.Entry<String, ConfigurationNode> entry : nodes.entrySet()) {
  225. ConfigurationNode node = entry.getValue();
  226. Item item = new Item(entry.getKey(), durability, getStringAsList(node, "id"));
  227. if (isId) {
  228. if (item.ids.size() != 1) continue;
  229. String id = item.ids.get(0);
  230. if (id.equals(query)) return item;
  231. if (id.equals(text)) matches.add(item);
  232. }
  233. else {
  234. List<String> names = getStringAsList(node, "alias");
  235. names.add(item.name);
  236. for (String name : names) {
  237. if (text.equalsIgnoreCase(name)) return checkBetterMatch(item);
  238. if (pattern.matcher(name).matches()) matches.add(item);
  239. }
  240. }
  241. }
  242. if (matches.size() == 0) throw new CommandException(CommandMessage.NOMATCHES);
  243. if (matches.size() > 1) throw new CommandException(CommandMessage.TOOMANYMATCHES, Item.join(matches));
  244. Item item = matches.iterator().next();
  245. return isId ? item : checkBetterMatch(item);
  246. }
  247. private Item checkBetterMatch(Item item) {
  248. if (item.durability > -1 && item.ids.size() == 1) {
  249. try {
  250. Matcher m = Pattern.compile("(\\d+)(?::\\d+)?").matcher(item.ids.get(0));
  251. m.matches();
  252. return findItem(m.group(1) + ":" + item.durability);
  253. }
  254. catch (CommandException e) {}
  255. }
  256. return item;
  257. }
  258. private void processItem(CommandSender from, int count, Item item) throws CommandException {
  259. ConfigurationNode node = config.getNode("items." + item.name);
  260. if (count == 0) count = node.getInt("def", config.getInt("count.def", 64));
  261. count = Math.min(count, node.getInt("max", config.getInt("count.max", 512)));
  262. if (count < 1) count = 1;
  263. item.count = count;
  264. if (!(from instanceof Player)) return;
  265. String permission = node.getString("permission");
  266. if (permission != null && !hasPermission(from, "giveto.item." + permission)) throw new CommandException(CommandMessage.PERMISSION);
  267. String fromName = ((Player) from).getName();
  268. double cost = 0;
  269. MethodAccount account = null;
  270. if (!hasPermission(from, "giveto.exempt.cost")) {
  271. cost = node.getDouble("cost", -1);
  272. if (cost < 0) cost = config.getDouble("cost", 0);
  273. cost *= item.count;
  274. if (cost > 0 && hasMethod()) {
  275. if (!Method.hasAccount(fromName)) throw new CommandException(CommandMessage.NOACCOUNT);
  276. account = Method.getAccount(fromName);
  277. if (!account.hasEnough(cost)) throw new CommandException(CommandMessage.NOMONEY, Method.format(cost), Method.format(cost - account.balance()));
  278. item.costMsg = CommandMessage.SUBTRACTMONEY.toString(Method.format(cost), Method.format(account.balance() - cost));
  279. }
  280. else cost = 0;
  281. }
  282. if (!hasPermission(from, "giveto.exempt.delay")) {
  283. String type = "";
  284. int delay = node.getInt("delay", -1);
  285. if (delay > -1) type = item.name;
  286. else delay = config.getInt("delay", 0);
  287. if (delay > 0) {
  288. String key = fromName + type;
  289. int time = (int) (System.currentTimeMillis() / 1000);
  290. if (delayPlayers.containsKey(key) && delayPlayers.get(key) > time) throw new CommandException(CommandMessage.DELAY, secondsToTime(delayPlayers.get(key) - time), type.equals("") ? "another item" : item.name + " again");
  291. delayPlayers.put(key, time + delay);
  292. }
  293. }
  294. if (cost > 0) account.subtract(cost);
  295. }
  296. private String secondsToTime(int seconds) {
  297. char[] symbol = { 'd', 'h', 'm', 's' };
  298. int[] increment = { 86400, 3600, 60, 1 };
  299. StringBuilder sb = new StringBuilder();
  300. int times;
  301. for (int i = 0; i < 4; i++) {
  302. if ((times = seconds / increment[i]) == 0 && sb.length() == 0) continue;
  303. sb.append(times);
  304. sb.append(symbol[i]);
  305. seconds %= increment[i];
  306. }
  307. return sb.toString();
  308. }
  309. private void giveItem(CommandSender from, Player to, Item item) {
  310. if (to != from && from instanceof Player) {
  311. sendMsg(to, CommandMessage.GIVEFROM.toString(((Player) from).getName(), item.name), true);
  312. sendMsg(from, CommandMessage.GIVETO.toString(item.name, to.getName() + "'s", item.costMsg), true);
  313. }
  314. else sendMsg(to, CommandMessage.GIVETO.toString(item.name, "your", item.costMsg), true);
  315. Boolean fullInventory = false;
  316. PlayerInventory inventory = to.getInventory();
  317. Pattern pattern = Pattern.compile(":");
  318. if (item.durability < 0) item.durability = 0;
  319. for (String id : item.ids) {
  320. String[] parts = pattern.split(id);
  321. fullInventory = !inventory.addItem(new ItemStack(Integer.parseInt(parts[0]), item.count, parts.length == 2 ? Short.parseShort(parts[1]) : item.durability)).isEmpty();
  322. }
  323. updateInventory(to);
  324. if (fullInventory) sendMsg(to, CommandMessage.INVENTORYFULL.toString());
  325. }
  326. @SuppressWarnings("deprecation") private void updateInventory(Player player) {
  327. List<String> updateInventory = getStringAsList(config,"updateinventory");
  328. if (updateInventory.contains("*") || updateInventory.contains(player.getName())) player.updateInventory();
  329. }
  330. private String joinAsString(List<Player> players) {
  331. List<String> strings = new ArrayList<String>();
  332. for (Player player : players)
  333. strings.add(player.getName());
  334. return joinAsString(strings.toArray(), ", ", 0, strings.size());
  335. }
  336. private String joinAsString(Object[] objects, String separator, int first, int last) {
  337. StringBuilder sb = new StringBuilder(objects[first].toString());
  338. for (int i = first + 1; i < last; i++)
  339. sb.append(separator + objects[i].toString());
  340. return sb.toString();
  341. }
  342. @SuppressWarnings("unchecked")
  343. private List<String> getStringAsList(ConfigurationNode node, String key) {
  344. Object o = node.getProperty(key);
  345. if (o instanceof List) return (List<String>) o;
  346. List<String> ids = new ArrayList<String>();
  347. if (o != null) ids.add(o.toString());
  348. return ids;
  349. }
  350. }