diff --git a/src/main/java/org/maxgamer/QuickShop/Command/QS.java b/src/main/java/org/maxgamer/QuickShop/Command/QS.java index b3a722f..525e2bd 100644 --- a/src/main/java/org/maxgamer/QuickShop/Command/QS.java +++ b/src/main/java/org/maxgamer/QuickShop/Command/QS.java @@ -14,7 +14,6 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.util.BlockIterator; @@ -31,407 +30,55 @@ import org.maxgamer.QuickShop.Util.MsgUtil; public class QS implements CommandExecutor { QuickShop plugin; - public QS(QuickShop plugin) { + public QS(final QuickShop plugin) { this.plugin = plugin; } - private void setUnlimited(CommandSender sender) { - if (sender instanceof Player && sender.hasPermission("quickshop.unlimited")) { - BlockIterator bIt = new BlockIterator((Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null) { - shop.setUnlimited(!shop.isUnlimited()); - shop.update(); - sender.sendMessage(MsgUtil.p("command.toggle-unlimited", (shop.isUnlimited() ? "unlimited" : "limited"))); - return; - } + /** + * Returns loc with modified pitch/yaw angles so it faces lookat + * + * @param loc + * The location a players head is + * @param lookat + * The location they should be looking + * @return The location the player should be facing to have their crosshairs + * on the location lookAt Kudos to bergerkiller for most of this + * function + */ + public Location lookAt(Location loc, final Location lookat) { + // Clone the loc to prevent applied changes to the input loc + loc = loc.clone(); + // Values of change in distance (make it relative) + final double dx = lookat.getX() - loc.getX(); + final double dy = lookat.getY() - loc.getY(); + final double dz = lookat.getZ() - loc.getZ(); + // Set yaw + if (dx != 0) { + // Set yaw start value based on dx + if (dx < 0) { + loc.setYaw((float) (1.5 * Math.PI)); + } else { + loc.setYaw((float) (0.5 * Math.PI)); } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } else { - sender.sendMessage(MsgUtil.p("no-permission")); - return; + loc.setYaw(loc.getYaw() - (float) Math.atan(dz / dx)); + } else if (dz < 0) { + loc.setYaw((float) Math.PI); } - } - - private void remove(CommandSender sender, String[] args) { - if (sender instanceof Player == false) { - sender.sendMessage(ChatColor.RED + "Only players may use that command."); - return; - } - if (!sender.hasPermission("quickshop.delete")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to use that command. Try break the shop instead?"); - return; - } - Player p = (Player) sender; - BlockIterator bIt = new BlockIterator(p, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null) { - if (shop.getOwner().equals(p.getUniqueId())) { - shop.delete(); - sender.sendMessage(ChatColor.GREEN + "Success. Deleted shop."); - } else { - p.sendMessage(ChatColor.RED + "That's not your shop!"); - } - return; - } - } - p.sendMessage(ChatColor.RED + "No shop found!"); - } - - private void export(CommandSender sender, String[] args) { - if (args.length < 2) { - sender.sendMessage(ChatColor.RED + "Usage: /qs export mysql|sqlite"); - return; - } - String type = args[1].toLowerCase(); - if (type.startsWith("mysql")) { - if (plugin.getDB().getCore() instanceof MySQLCore) { - sender.sendMessage(ChatColor.RED + "Database is already MySQL"); - return; - } - ConfigurationSection cfg = plugin.getConfig().getConfigurationSection("database"); - String host = cfg.getString("host"); - String port = cfg.getString("port"); - String user = cfg.getString("user"); - String pass = cfg.getString("password"); - String name = cfg.getString("database"); - MySQLCore core = new MySQLCore(host, user, pass, name, port); - Database target; - try { - target = new Database(core); - QuickShop.instance.getDB().copyTo(target); - sender.sendMessage(ChatColor.GREEN + "Success - Exported to MySQL " + user + "@" + host + "." + name); - } catch (Exception e) { - e.printStackTrace(); - sender.sendMessage(ChatColor.RED + "Failed to export to MySQL " + user + "@" + host + "." + name + ChatColor.DARK_RED + " Reason: " + e.getMessage()); - } - return; - } - if (type.startsWith("sql") || type.contains("file")) { - if (plugin.getDB().getCore() instanceof SQLiteCore) { - sender.sendMessage(ChatColor.RED + "Database is already SQLite"); - return; - } - File file = new File(plugin.getDataFolder(), "shops.db"); - if (file.exists()) { - if (file.delete() == false) { - sender.sendMessage(ChatColor.RED + "Warning: Failed to delete old shops.db file. This may cause errors."); - } - } - SQLiteCore core = new SQLiteCore(file); - try { - Database target = new Database(core); - QuickShop.instance.getDB().copyTo(target); - sender.sendMessage(ChatColor.GREEN + "Success - Exported to SQLite: " + file.toString()); - } catch (Exception e) { - e.printStackTrace(); - sender.sendMessage(ChatColor.RED + "Failed to export to SQLite: " + file.toString() + " Reason: " + e.getMessage()); - } - return; - } - sender.sendMessage(ChatColor.RED + "No target given. Usage: /qs export mysql|sqlite"); - } - - private void setOwner(CommandSender sender, String[] args) { - if (sender instanceof Player && sender.hasPermission("quickshop.setowner")) { - if (args.length < 2) { - sender.sendMessage(MsgUtil.p("command.no-owner-given")); - return; - } - BlockIterator bIt = new BlockIterator((Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null) { - @SuppressWarnings("deprecation") - OfflinePlayer p = this.plugin.getServer().getOfflinePlayer(args[1]); - shop.setOwner(p.getUniqueId()); - shop.update(); - sender.sendMessage(MsgUtil.p("command.new-owner", this.plugin.getServer().getOfflinePlayer(shop.getOwner()).getName())); - return; - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } else { - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - } - - private void refill(CommandSender sender, String[] args) { - if (sender instanceof Player && sender.hasPermission("quickshop.refill")) { - if (args.length < 2) { - sender.sendMessage(MsgUtil.p("command.no-amount-given")); - return; - } - int add; - try { - add = Integer.parseInt(args[1]); - } catch (NumberFormatException e) { - sender.sendMessage(MsgUtil.p("thats-not-a-number")); - return; - } - BlockIterator bIt = new BlockIterator((LivingEntity) (Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null) { - shop.add(shop.getItem(), add); - sender.sendMessage(MsgUtil.p("refill-success")); - return; - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } else { - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - } - - private void empty(CommandSender sender, String[] args) { - if (sender instanceof Player && sender.hasPermission("quickshop.refill")) { - BlockIterator bIt = new BlockIterator((LivingEntity) (Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null) { - if (shop instanceof ContainerShop) { - ContainerShop cs = (ContainerShop) shop; - cs.getInventory().clear(); - sender.sendMessage(MsgUtil.p("empty-success")); - return; - } else { - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } else { - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - } - - private void find(CommandSender sender, String[] args) { - if (sender instanceof Player && sender.hasPermission("quickshop.find")) { - if (args.length < 2) { - sender.sendMessage(MsgUtil.p("command.no-type-given")); - return; - } - StringBuilder sb = new StringBuilder(args[1]); - for (int i = 2; i < args.length; i++) { - sb.append(" " + args[i]); - } - String lookFor = sb.toString(); - lookFor = lookFor.toLowerCase(); - Player p = (Player) sender; - Location loc = p.getEyeLocation().clone(); - double minDistance = plugin.getConfig().getInt("shop.find-distance"); - double minDistanceSquared = minDistance * minDistance; - int chunkRadius = (int) minDistance / 16 + 1; - Shop closest = null; - Chunk c = loc.getChunk(); - for (int x = -chunkRadius + c.getX(); x < chunkRadius + c.getX(); x++) { - for (int z = -chunkRadius + c.getZ(); z < chunkRadius + c.getZ(); z++) { - Chunk d = c.getWorld().getChunkAt(x, z); - HashMap inChunk = plugin.getShopManager().getShops(d); - if (inChunk == null) - continue; - for (Shop shop : inChunk.values()) { - if (shop.getDataName().toLowerCase().contains(lookFor) && shop.getLocation().distanceSquared(loc) < minDistanceSquared) { - closest = shop; - minDistanceSquared = shop.getLocation().distanceSquared(loc); - } - } - } - } - if (closest == null) { - sender.sendMessage(MsgUtil.p("no-nearby-shop", args[1])); - return; - } - Location lookat = closest.getLocation().clone().add(0.5, 0.5, 0.5); - // Hack fix to make /qs find not used by /back - p.teleport(this.lookAt(loc, lookat).add(0, -1.62, 0), TeleportCause.UNKNOWN); - p.sendMessage(MsgUtil.p("nearby-shop-this-way", "" + (int) Math.floor(Math.sqrt(minDistanceSquared)))); - return; - } else { - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - } - - private void setBuy(CommandSender sender) { - if (sender instanceof Player && sender.hasPermission("quickshop.create.buy")) { - BlockIterator bIt = new BlockIterator((LivingEntity) (Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null && shop.getOwner().equals(((Player) sender).getUniqueId())) { - shop.setShopType(ShopType.BUYING); - shop.setSignText(); - shop.update(); - sender.sendMessage(MsgUtil.p("command.now-buying", shop.getDataName())); - return; - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - - private void setSell(CommandSender sender) { - if (sender instanceof Player && sender.hasPermission("quickshop.create.sell")) { - BlockIterator bIt = new BlockIterator((LivingEntity) (Player) sender, 10); - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null && shop.getOwner().equals(((Player) sender).getUniqueId())) { - shop.setShopType(ShopType.SELLING); - shop.setSignText(); - shop.update(); - sender.sendMessage(MsgUtil.p("command.now-selling", shop.getDataName())); - return; - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - - @SuppressWarnings("deprecation") - private void setPrice(CommandSender sender, String[] args) { - if (sender instanceof Player && sender.hasPermission("quickshop.create.changeprice")) { - Player p = (Player) sender; - if (args.length < 2) { - sender.sendMessage(MsgUtil.p("no-price-given")); - return; - } - double price; - try { - price = Double.parseDouble(args[1]); - } catch (NumberFormatException e) { - sender.sendMessage(MsgUtil.p("thats-not-a-number")); - return; - } - if (price < 0.01) { - sender.sendMessage(MsgUtil.p("price-too-cheap")); - return; - } - double fee = 0; - if (plugin.priceChangeRequiresFee) { - fee = plugin.getConfig().getDouble("shop.fee-for-price-change"); - if (fee > 0 && plugin.getEcon().getBalance(p.getUniqueId()) < fee) { - sender.sendMessage(MsgUtil.p("you-cant-afford-to-change-price", plugin.getEcon().format(fee))); - return; - } - } - BlockIterator bIt = new BlockIterator(p, 10); - // Loop through every block they're looking at upto 10 blocks away - while (bIt.hasNext()) { - Block b = bIt.next(); - Shop shop = plugin.getShopManager().getShop(b.getLocation()); - if (shop != null && (shop.getOwner().equals(((Player) sender).getUniqueId()) || sender.hasPermission("quickshop.other.price"))) { - if (shop.getPrice() == price) { - // Stop here if there isn't a price change - sender.sendMessage(MsgUtil.p("no-price-change")); - return; - } - if (fee > 0) { - if (!plugin.getEcon().withdraw(p.getUniqueId(), fee)) { - sender.sendMessage(MsgUtil.p("you-cant-afford-to-change-price", plugin.getEcon().format(fee))); - return; - } - sender.sendMessage(MsgUtil.p("fee-charged-for-price-change", plugin.getEcon().format(fee))); - plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), fee); - } - // Update the shop - shop.setPrice(price); - shop.setSignText(); - shop.update(); - sender.sendMessage(MsgUtil.p("price-is-now", plugin.getEcon().format(shop.getPrice()))); - // Chest shops can be double shops. - if (shop instanceof ContainerShop) { - ContainerShop cs = (ContainerShop) shop; - if (cs.isDoubleShop()) { - Shop nextTo = cs.getAttachedShop(); - if (cs.isSelling()) { - if (cs.getPrice() < nextTo.getPrice()) { - sender.sendMessage(MsgUtil.p("buying-more-than-selling")); - } - } else { - // Buying - if (cs.getPrice() > nextTo.getPrice()) { - sender.sendMessage(MsgUtil.p("buying-more-than-selling")); - } - } - } - } - return; - } - } - sender.sendMessage(MsgUtil.p("not-looking-at-shop")); - return; - } - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - - private void clean(CommandSender sender) { - if (sender.hasPermission("quickshop.clean")) { - sender.sendMessage(MsgUtil.p("command.cleaning")); - Iterator shIt = plugin.getShopManager().getShopIterator(); - int i = 0; - while (shIt.hasNext()) { - Shop shop = shIt.next(); - - try { - if (shop.getLocation().getWorld() != null && shop.isSelling() && shop.getRemainingStock() == 0 && shop instanceof ContainerShop) { - ContainerShop cs = (ContainerShop) shop; - if (cs.isDoubleShop()) - continue; - shIt.remove(); // Is selling, but has no stock, and is a chest shop, but is not a double shop. Can be deleted safely. - i++; - } - } catch (IllegalStateException e) { - shIt.remove(); // The shop is not there anymore, remove it - } - } - MsgUtil.clean(); - sender.sendMessage(MsgUtil.p("command.cleaned", "" + i)); - return; - } - sender.sendMessage(MsgUtil.p("no-permission")); - return; - } - - private void reload(CommandSender sender) { - if (sender.hasPermission("quickshop.reload")) { - sender.sendMessage(MsgUtil.p("command.reloading")); - Bukkit.getPluginManager().disablePlugin(plugin); - Bukkit.getPluginManager().enablePlugin(plugin); - return; - } - sender.sendMessage(MsgUtil.p("no-permission")); - return; + // Get the distance from dx/dz + final double dxz = Math.sqrt(Math.pow(dx, 2) + Math.pow(dz, 2)); + final float pitch = (float) -Math.atan(dy / dxz); + // Set values, convert to degrees + // Minecraft yaw (vertical) angles are inverted (negative) + loc.setYaw(-loc.getYaw() * 180f / (float) Math.PI + 360); + // But pitch angles are normal + loc.setPitch(pitch * 180f / (float) Math.PI); + return loc; } @Override - public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + public boolean onCommand(final CommandSender sender, final Command cmd, final String commandLabel, final String[] args) { if (args.length > 0) { - String subArg = args[0].toLowerCase(); + final String subArg = args[0].toLowerCase(); if (subArg.equals("unlimited")) { setUnlimited(sender); return true; @@ -472,11 +119,11 @@ public class QS implements CommandExecutor { int buying, selling, doubles, chunks, worlds; buying = selling = doubles = chunks = worlds = 0; int nostock = 0; - for (HashMap> inWorld : plugin.getShopManager().getShops().values()) { + for (final HashMap> inWorld : plugin.getShopManager().getShops().values()) { worlds++; - for (HashMap inChunk : inWorld.values()) { + for (final HashMap inChunk : inWorld.values()) { chunks++; - for (Shop shop : inChunk.values()) { + for (final Shop shop : inChunk.values()) { if (shop.isBuying()) { buying++; } else if (shop.isSelling()) { @@ -509,68 +156,432 @@ public class QS implements CommandExecutor { return true; } - /** - * Returns loc with modified pitch/yaw angles so it faces lookat - * - * @param loc - * The location a players head is - * @param lookat - * The location they should be looking - * @return The location the player should be facing to have their crosshairs - * on the location lookAt Kudos to bergerkiller for most of this - * function - */ - public Location lookAt(Location loc, Location lookat) { - // Clone the loc to prevent applied changes to the input loc - loc = loc.clone(); - // Values of change in distance (make it relative) - double dx = lookat.getX() - loc.getX(); - double dy = lookat.getY() - loc.getY(); - double dz = lookat.getZ() - loc.getZ(); - // Set yaw - if (dx != 0) { - // Set yaw start value based on dx - if (dx < 0) { - loc.setYaw((float) (1.5 * Math.PI)); - } else { - loc.setYaw((float) (0.5 * Math.PI)); - } - loc.setYaw((float) loc.getYaw() - (float) Math.atan(dz / dx)); - } else if (dz < 0) { - loc.setYaw((float) Math.PI); + public void sendHelp(final CommandSender s) { + s.sendMessage(MsgUtil.p("command.description.title")); + if (s.hasPermission("quickshop.unlimited")) { + s.sendMessage(ChatColor.GREEN + "/qs unlimited" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.unlimited")); + } + if (s.hasPermission("quickshop.setowner")) { + s.sendMessage(ChatColor.GREEN + "/qs setowner " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.setowner")); + } + if (s.hasPermission("quickshop.create.buy")) { + s.sendMessage(ChatColor.GREEN + "/qs buy" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.buy")); + } + if (s.hasPermission("quickshop.create.sell")) { + s.sendMessage(ChatColor.GREEN + "/qs sell" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.sell")); + } + if (s.hasPermission("quickshop.create.changeprice")) { + s.sendMessage(ChatColor.GREEN + "/qs price" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.price")); + } + if (s.hasPermission("quickshop.clean")) { + s.sendMessage(ChatColor.GREEN + "/qs clean" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.clean")); + } + if (s.hasPermission("quickshop.find")) { + s.sendMessage(ChatColor.GREEN + "/qs find " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.find")); + } + if (s.hasPermission("quickshop.refill")) { + s.sendMessage(ChatColor.GREEN + "/qs refill " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.refill")); + } + if (s.hasPermission("quickshop.empty")) { + s.sendMessage(ChatColor.GREEN + "/qs empty" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.empty")); + } + if (s.hasPermission("quickshop.export")) { + s.sendMessage(ChatColor.GREEN + "/qs export mysql|sqlite" + ChatColor.YELLOW + " - Exports the database to SQLite or MySQL"); } - // Get the distance from dx/dz - double dxz = Math.sqrt(Math.pow(dx, 2) + Math.pow(dz, 2)); - float pitch = (float) -Math.atan(dy / dxz); - // Set values, convert to degrees - // Minecraft yaw (vertical) angles are inverted (negative) - loc.setYaw(-loc.getYaw() * 180f / (float) Math.PI + 360); - // But pitch angles are normal - loc.setPitch(pitch * 180f / (float) Math.PI); - return loc; } - public void sendHelp(CommandSender s) { - s.sendMessage(MsgUtil.p("command.description.title")); - if (s.hasPermission("quickshop.unlimited")) - s.sendMessage(ChatColor.GREEN + "/qs unlimited" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.unlimited")); - if (s.hasPermission("quickshop.setowner")) - s.sendMessage(ChatColor.GREEN + "/qs setowner " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.setowner")); - if (s.hasPermission("quickshop.create.buy")) - s.sendMessage(ChatColor.GREEN + "/qs buy" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.buy")); - if (s.hasPermission("quickshop.create.sell")) - s.sendMessage(ChatColor.GREEN + "/qs sell" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.sell")); - if (s.hasPermission("quickshop.create.changeprice")) - s.sendMessage(ChatColor.GREEN + "/qs price" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.price")); - if (s.hasPermission("quickshop.clean")) - s.sendMessage(ChatColor.GREEN + "/qs clean" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.clean")); - if (s.hasPermission("quickshop.find")) - s.sendMessage(ChatColor.GREEN + "/qs find " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.find")); - if (s.hasPermission("quickshop.refill")) - s.sendMessage(ChatColor.GREEN + "/qs refill " + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.refill")); - if (s.hasPermission("quickshop.empty")) - s.sendMessage(ChatColor.GREEN + "/qs empty" + ChatColor.YELLOW + " - " + MsgUtil.p("command.description.empty")); - if (s.hasPermission("quickshop.export")) - s.sendMessage(ChatColor.GREEN + "/qs export mysql|sqlite" + ChatColor.YELLOW + " - Exports the database to SQLite or MySQL"); + private void clean(final CommandSender sender) { + if (sender.hasPermission("quickshop.clean")) { + sender.sendMessage(MsgUtil.p("command.cleaning")); + final Iterator shIt = plugin.getShopManager().getShopIterator(); + int i = 0; + while (shIt.hasNext()) { + final Shop shop = shIt.next(); + + try { + if (shop.getLocation().getWorld() != null && shop.isSelling() && shop.getRemainingStock() == 0 && shop instanceof ContainerShop) { + final ContainerShop cs = (ContainerShop) shop; + if (cs.isDoubleShop()) { + continue; + } + shIt.remove(); // Is selling, but has no stock, and is a chest shop, but is not a double shop. Can be deleted safely. + i++; + } + } catch (final IllegalStateException e) { + shIt.remove(); // The shop is not there anymore, remove it + } + } + MsgUtil.clean(); + sender.sendMessage(MsgUtil.p("command.cleaned", "" + i)); + return; + } + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + + private void empty(final CommandSender sender, final String[] args) { + if (sender instanceof Player && sender.hasPermission("quickshop.refill")) { + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null) { + if (shop instanceof ContainerShop) { + final ContainerShop cs = (ContainerShop) shop; + cs.getInventory().clear(); + sender.sendMessage(MsgUtil.p("empty-success")); + return; + } else { + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } else { + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + } + + private void export(final CommandSender sender, final String[] args) { + if (args.length < 2) { + sender.sendMessage(ChatColor.RED + "Usage: /qs export mysql|sqlite"); + return; + } + final String type = args[1].toLowerCase(); + if (type.startsWith("mysql")) { + if (plugin.getDB().getCore() instanceof MySQLCore) { + sender.sendMessage(ChatColor.RED + "Database is already MySQL"); + return; + } + final ConfigurationSection cfg = plugin.getConfig().getConfigurationSection("database"); + final String host = cfg.getString("host"); + final String port = cfg.getString("port"); + final String user = cfg.getString("user"); + final String pass = cfg.getString("password"); + final String name = cfg.getString("database"); + final MySQLCore core = new MySQLCore(host, user, pass, name, port); + Database target; + try { + target = new Database(core); + QuickShop.instance.getDB().copyTo(target); + sender.sendMessage(ChatColor.GREEN + "Success - Exported to MySQL " + user + "@" + host + "." + name); + } catch (final Exception e) { + e.printStackTrace(); + sender.sendMessage(ChatColor.RED + "Failed to export to MySQL " + user + "@" + host + "." + name + ChatColor.DARK_RED + " Reason: " + e.getMessage()); + } + return; + } + if (type.startsWith("sql") || type.contains("file")) { + if (plugin.getDB().getCore() instanceof SQLiteCore) { + sender.sendMessage(ChatColor.RED + "Database is already SQLite"); + return; + } + final File file = new File(plugin.getDataFolder(), "shops.db"); + if (file.exists()) { + if (file.delete() == false) { + sender.sendMessage(ChatColor.RED + "Warning: Failed to delete old shops.db file. This may cause errors."); + } + } + final SQLiteCore core = new SQLiteCore(file); + try { + final Database target = new Database(core); + QuickShop.instance.getDB().copyTo(target); + sender.sendMessage(ChatColor.GREEN + "Success - Exported to SQLite: " + file.toString()); + } catch (final Exception e) { + e.printStackTrace(); + sender.sendMessage(ChatColor.RED + "Failed to export to SQLite: " + file.toString() + " Reason: " + e.getMessage()); + } + return; + } + sender.sendMessage(ChatColor.RED + "No target given. Usage: /qs export mysql|sqlite"); + } + + private void find(final CommandSender sender, final String[] args) { + if (sender instanceof Player && sender.hasPermission("quickshop.find")) { + if (args.length < 2) { + sender.sendMessage(MsgUtil.p("command.no-type-given")); + return; + } + final StringBuilder sb = new StringBuilder(args[1]); + for (int i = 2; i < args.length; i++) { + sb.append(" " + args[i]); + } + String lookFor = sb.toString(); + lookFor = lookFor.toLowerCase(); + final Player p = (Player) sender; + final Location loc = p.getEyeLocation().clone(); + final double minDistance = plugin.getConfig().getInt("shop.find-distance"); + double minDistanceSquared = minDistance * minDistance; + final int chunkRadius = (int) minDistance / 16 + 1; + Shop closest = null; + final Chunk c = loc.getChunk(); + for (int x = -chunkRadius + c.getX(); x < chunkRadius + c.getX(); x++) { + for (int z = -chunkRadius + c.getZ(); z < chunkRadius + c.getZ(); z++) { + final Chunk d = c.getWorld().getChunkAt(x, z); + final HashMap inChunk = plugin.getShopManager().getShops(d); + if (inChunk == null) { + continue; + } + for (final Shop shop : inChunk.values()) { + if (shop.getDataName().toLowerCase().contains(lookFor) && shop.getLocation().distanceSquared(loc) < minDistanceSquared) { + closest = shop; + minDistanceSquared = shop.getLocation().distanceSquared(loc); + } + } + } + } + if (closest == null) { + sender.sendMessage(MsgUtil.p("no-nearby-shop", args[1])); + return; + } + final Location lookat = closest.getLocation().clone().add(0.5, 0.5, 0.5); + // Hack fix to make /qs find not used by /back + p.teleport(this.lookAt(loc, lookat).add(0, -1.62, 0), TeleportCause.UNKNOWN); + p.sendMessage(MsgUtil.p("nearby-shop-this-way", "" + (int) Math.floor(Math.sqrt(minDistanceSquared)))); + return; + } else { + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + } + + private void refill(final CommandSender sender, final String[] args) { + if (sender instanceof Player && sender.hasPermission("quickshop.refill")) { + if (args.length < 2) { + sender.sendMessage(MsgUtil.p("command.no-amount-given")); + return; + } + int add; + try { + add = Integer.parseInt(args[1]); + } catch (final NumberFormatException e) { + sender.sendMessage(MsgUtil.p("thats-not-a-number")); + return; + } + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null) { + shop.add(shop.getItem(), add); + sender.sendMessage(MsgUtil.p("refill-success")); + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } else { + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + } + + private void reload(final CommandSender sender) { + if (sender.hasPermission("quickshop.reload")) { + sender.sendMessage(MsgUtil.p("command.reloading")); + Bukkit.getPluginManager().disablePlugin(plugin); + Bukkit.getPluginManager().enablePlugin(plugin); + return; + } + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + + private void remove(final CommandSender sender, final String[] args) { + if (sender instanceof Player == false) { + sender.sendMessage(ChatColor.RED + "Only players may use that command."); + return; + } + if (!sender.hasPermission("quickshop.delete")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command. Try break the shop instead?"); + return; + } + final Player p = (Player) sender; + final BlockIterator bIt = new BlockIterator(p, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null) { + if (shop.getOwner().equals(p.getUniqueId())) { + shop.delete(); + sender.sendMessage(ChatColor.GREEN + "Success. Deleted shop."); + } else { + p.sendMessage(ChatColor.RED + "That's not your shop!"); + } + return; + } + } + p.sendMessage(ChatColor.RED + "No shop found!"); + } + + private void setBuy(final CommandSender sender) { + if (sender instanceof Player && sender.hasPermission("quickshop.create.buy")) { + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null && shop.getOwner().equals(((Player) sender).getUniqueId())) { + shop.setShopType(ShopType.BUYING); + shop.setSignText(); + shop.update(); + sender.sendMessage(MsgUtil.p("command.now-buying", shop.getDataName())); + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + + @SuppressWarnings("deprecation") + private void setOwner(final CommandSender sender, final String[] args) { + if (sender instanceof Player && sender.hasPermission("quickshop.setowner")) { + if (args.length < 2) { + sender.sendMessage(MsgUtil.p("command.no-owner-given")); + return; + } + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null) { + final OfflinePlayer p = this.plugin.getServer().getOfflinePlayer(args[1]); + shop.setOwner(p.getName()); + shop.update(); + sender.sendMessage(MsgUtil.p("command.new-owner", this.plugin.getServer().getOfflinePlayer(shop.getOwner()).getName())); + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } else { + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + } + + @SuppressWarnings("deprecation") + private void setPrice(final CommandSender sender, final String[] args) { + if (sender instanceof Player && sender.hasPermission("quickshop.create.changeprice")) { + final Player p = (Player) sender; + if (args.length < 2) { + sender.sendMessage(MsgUtil.p("no-price-given")); + return; + } + double price; + try { + price = Double.parseDouble(args[1]); + } catch (final NumberFormatException e) { + sender.sendMessage(MsgUtil.p("thats-not-a-number")); + return; + } + if (price < 0.01) { + sender.sendMessage(MsgUtil.p("price-too-cheap")); + return; + } + double fee = 0; + if (plugin.priceChangeRequiresFee) { + fee = plugin.getConfig().getDouble("shop.fee-for-price-change"); + if (fee > 0 && plugin.getEcon().getBalance(p.getUniqueId()) < fee) { + sender.sendMessage(MsgUtil.p("you-cant-afford-to-change-price", plugin.getEcon().format(fee))); + return; + } + } + final BlockIterator bIt = new BlockIterator(p, 10); + // Loop through every block they're looking at upto 10 blocks away + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null && (shop.getOwner().equals(((Player) sender).getUniqueId()) || sender.hasPermission("quickshop.other.price"))) { + if (shop.getPrice() == price) { + // Stop here if there isn't a price change + sender.sendMessage(MsgUtil.p("no-price-change")); + return; + } + if (fee > 0) { + if (!plugin.getEcon().withdraw(p.getUniqueId(), fee)) { + sender.sendMessage(MsgUtil.p("you-cant-afford-to-change-price", plugin.getEcon().format(fee))); + return; + } + sender.sendMessage(MsgUtil.p("fee-charged-for-price-change", plugin.getEcon().format(fee))); + plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), fee); + } + // Update the shop + shop.setPrice(price); + shop.setSignText(); + shop.update(); + sender.sendMessage(MsgUtil.p("price-is-now", plugin.getEcon().format(shop.getPrice()))); + // Chest shops can be double shops. + if (shop instanceof ContainerShop) { + final ContainerShop cs = (ContainerShop) shop; + if (cs.isDoubleShop()) { + final Shop nextTo = cs.getAttachedShop(); + if (cs.isSelling()) { + if (cs.getPrice() < nextTo.getPrice()) { + sender.sendMessage(MsgUtil.p("buying-more-than-selling")); + } + } else { + // Buying + if (cs.getPrice() > nextTo.getPrice()) { + sender.sendMessage(MsgUtil.p("buying-more-than-selling")); + } + } + } + } + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + + private void setSell(final CommandSender sender) { + if (sender instanceof Player && sender.hasPermission("quickshop.create.sell")) { + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null && shop.getOwner().equals(((Player) sender).getUniqueId())) { + shop.setShopType(ShopType.SELLING); + shop.setSignText(); + shop.update(); + sender.sendMessage(MsgUtil.p("command.now-selling", shop.getDataName())); + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } + + private void setUnlimited(final CommandSender sender) { + if (sender instanceof Player && sender.hasPermission("quickshop.unlimited")) { + final BlockIterator bIt = new BlockIterator((Player) sender, 10); + while (bIt.hasNext()) { + final Block b = bIt.next(); + final Shop shop = plugin.getShopManager().getShop(b.getLocation()); + if (shop != null) { + shop.setUnlimited(!shop.isUnlimited()); + shop.update(); + sender.sendMessage(MsgUtil.p("command.toggle-unlimited", (shop.isUnlimited() ? "unlimited" : "limited"))); + return; + } + } + sender.sendMessage(MsgUtil.p("not-looking-at-shop")); + return; + } else { + sender.sendMessage(MsgUtil.p("no-permission")); + return; + } } } \ No newline at end of file diff --git a/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java b/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java index a098815..6985702 100644 --- a/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java +++ b/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.UUID; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -14,6 +13,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; @@ -26,6 +26,7 @@ import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.Shop.Info; import org.maxgamer.QuickShop.Shop.Shop; import org.maxgamer.QuickShop.Shop.ShopAction; +import org.maxgamer.QuickShop.Util.MarkUtil; import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.Util; @@ -47,11 +48,11 @@ public class PlayerListener implements Listener { * * clazz = clazz.getSuperclass(); } return classes; } */ + @SuppressWarnings("deprecation") /** * Handles players left clicking a chest. Left click a NORMAL chest with * item : Send creation menu Left click a SHOP chest : Send purchase menu */ - @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.MONITOR) public void onClick(final PlayerInteractEvent e) { if (e.getAction() != Action.LEFT_CLICK_BLOCK) { @@ -131,6 +132,15 @@ public class PlayerListener implements Listener { } } + @EventHandler + public void onItemClick(final InventoryClickEvent e) { + final ItemStack ci = e.getCurrentItem(); + if (MarkUtil.hasMark(ci)) { + ci.setType(Material.AIR); + e.setCancelled(true); + } + } + @EventHandler public void onJoin(final PlayerJoinEvent e) { // Notify the player any messages they were sent @@ -169,15 +179,8 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerPickup(final PlayerPickupItemEvent e) { - final ItemStack stack = e.getItem().getItemStack(); - try { - if (stack.getItemMeta().getDisplayName().startsWith(ChatColor.RED + "QuickShop ")) { - e.setCancelled(true); - // You shouldn't be able to pick up that... - } - } catch (final NullPointerException ex) { - } // if meta/displayname/stack is null. We don't really care in that - // case. + final ItemStack ci = e.getItem().getItemStack(); + e.setCancelled(!MarkUtil.hasMark(ci)); } @EventHandler diff --git a/src/main/java/org/maxgamer/QuickShop/QuickShop.java b/src/main/java/org/maxgamer/QuickShop/QuickShop.java index 7eadb01..a4373ac 100644 --- a/src/main/java/org/maxgamer/QuickShop/QuickShop.java +++ b/src/main/java/org/maxgamer/QuickShop/QuickShop.java @@ -12,7 +12,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map.Entry; -import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -27,7 +26,6 @@ import org.bukkit.scheduler.BukkitTask; import org.maxgamer.QuickShop.Command.QS; import org.maxgamer.QuickShop.Config.ItemConfig; import org.maxgamer.QuickShop.Database.Database; -import org.maxgamer.QuickShop.Database.Database.ConnectionException; import org.maxgamer.QuickShop.Database.DatabaseCore; import org.maxgamer.QuickShop.Database.DatabaseHelper; import org.maxgamer.QuickShop.Database.MySQLCore; @@ -45,7 +43,6 @@ import org.maxgamer.QuickShop.Shop.ContainerShop; import org.maxgamer.QuickShop.Shop.Shop; import org.maxgamer.QuickShop.Shop.ShopManager; import org.maxgamer.QuickShop.Shop.ShopType; -import org.maxgamer.QuickShop.Util.Converter; import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.Util; import org.maxgamer.QuickShop.Watcher.ItemWatcher; @@ -59,7 +56,7 @@ public class QuickShop extends JavaPlugin { public static QuickShop instance; // private Metrics metrics; /** Whether debug info should be shown in the console */ - public static boolean debug = true; + public static boolean debug = false; /** The economy we hook into for transactions */ private Economy economy; /** The Shop Manager used to store shops */ @@ -233,7 +230,7 @@ public class QuickShop extends JavaPlugin { this.shopManager = new ShopManager(this); if (this.display) { // Display item handler thread - getLogger().info("Starting item scheduler"); + getLogger().info("开启悬浮物品刷新线程..."); final ItemWatcher itemWatcher = new ItemWatcher(this); itemWatcherTask = Bukkit.getScheduler().runTaskTimer(this, itemWatcher, 600, 600); } @@ -248,7 +245,7 @@ public class QuickShop extends JavaPlugin { } ConfigurationSection limitCfg = this.getConfig().getConfigurationSection("limits"); if (limitCfg != null) { - getLogger().info("Limit cfg found..."); + getLogger().info("发现物品限制配置..."); this.limit = limitCfg.getBoolean("use", false); getLogger().info("Limits.use: " + limit); limitCfg = limitCfg.getConfigurationSection("ranks"); @@ -261,6 +258,7 @@ public class QuickShop extends JavaPlugin { final ConfigurationSection dbCfg = getConfig().getConfigurationSection("database"); DatabaseCore dbCore; if (dbCfg.getBoolean("mysql")) { + getLogger().info("启用MySQL 开始连接数据库..."); // MySQL database - Required database be created first. final String user = dbCfg.getString("user"); final String pass = dbCfg.getString("password"); @@ -275,14 +273,11 @@ public class QuickShop extends JavaPlugin { this.database = new Database(dbCore); // Make the database up to date DatabaseHelper.setup(getDB()); - } catch (final ConnectionException e) { + } catch (final Exception e) { + getLogger().warning("数据库连接错误或配置错误..."); + getLogger().warning("错误信息: " + e.getMessage()); e.printStackTrace(); - getLogger().severe("Error connecting to database. Aborting plugin load."); - getServer().getPluginManager().disablePlugin(this); - return; - } catch (final SQLException e) { - e.printStackTrace(); - getLogger().severe("Error setting up database. Aborting plugin load."); + getLogger().warning("关闭插件!!!"); getServer().getPluginManager().disablePlugin(this); return; } @@ -290,15 +285,7 @@ public class QuickShop extends JavaPlugin { int count = 0; // Shops count Connection con; try { - getLogger().info("Loading shops from database..."); - final int res = Converter.convert(); - if (res < 0) { - System.out.println("Could not convert shops. Exitting."); - return; - } - if (res > 0) { - System.out.println("Conversion success. Continuing..."); - } + getLogger().info("从数据看载入商店数据..."); con = database.getConnection(); final PreparedStatement ps = con.prepareStatement("SELECT * FROM shops"); final ResultSet rs = ps.executeQuery(); @@ -320,7 +307,7 @@ public class QuickShop extends JavaPlugin { final Location loc = new Location(world, x, y, z); /* Skip invalid shops, if we know of any */ if (world != null && (loc.getBlock().getState() instanceof InventoryHolder) == false) { - getLogger().info("Shop is not an InventoryHolder in " + rs.getString("world") + " at: " + x + ", " + y + ", " + z + ". Deleting."); + getLogger().info("商店不是一个可存储的方块 坐标 " + rs.getString("world") + " at: " + x + ", " + y + ", " + z + ". 删除..."); final PreparedStatement delps = getDB().getConnection().prepareStatement("DELETE FROM shops WHERE x = ? AND y = ? and z = ? and world = ?"); delps.setInt(1, x); delps.setInt(2, y); @@ -330,7 +317,7 @@ public class QuickShop extends JavaPlugin { continue; } final int type = rs.getInt("type"); - final Shop shop = new ContainerShop(loc, price, item, UUID.fromString(owner)); + final Shop shop = new ContainerShop(loc, price, item, owner); shop.setUnlimited(rs.getBoolean("unlimited")); shop.setShopType(ShopType.fromID(type)); shopManager.loadShop(rs.getString("world"), shop); @@ -341,9 +328,9 @@ public class QuickShop extends JavaPlugin { } catch (final Exception e) { errors++; e.printStackTrace(); - getLogger().severe("Error loading a shop! Coords: " + worldName + " (" + x + ", " + y + ", " + z + ")..."); + getLogger().warning("载入商店数据时发生错误! 商店位置: " + worldName + " (" + x + ", " + y + ", " + z + ")..."); if (errors < 3) { - getLogger().info("Deleting the shop..."); + getLogger().warning("删除错误的商店数据..."); final PreparedStatement delps = getDB().getConnection().prepareStatement("DELETE FROM shops WHERE x = ? AND y = ? and z = ? and world = ?"); delps.setInt(1, x); delps.setInt(2, y); @@ -351,21 +338,22 @@ public class QuickShop extends JavaPlugin { delps.setString(4, worldName); delps.execute(); } else { - getLogger().severe("Multiple errors in shops - Something seems to be wrong with your shops database! Please check it out immediately!"); + getLogger().warning("过多的错误数据 可能您的数据库文件已损坏! 请检查数据库文件!"); e.printStackTrace(); } } } } catch (final SQLException e) { + getLogger().warning("无法载入商店数据..."); + getLogger().warning("错误信息: " + e.getMessage()); e.printStackTrace(); - getLogger().severe("Could not load shops."); } - getLogger().info("Loaded " + count + " shops."); + getLogger().info("已载入 " + count + " 个商店..."); MsgUtil.loadTransactionMessages(); MsgUtil.clean(); // Register events - getLogger().info("Registering Listeners"); + getLogger().info("注册监听器..."); Bukkit.getServer().getPluginManager().registerEvents(blockListener, this); Bukkit.getServer().getPluginManager().registerEvents(playerListener, this); if (this.display) { @@ -374,8 +362,6 @@ public class QuickShop extends JavaPlugin { Bukkit.getServer().getPluginManager().registerEvents(worldListener, this); if (this.getConfig().getBoolean("force-bukkit-chat-handler", false) && Bukkit.getPluginManager().getPlugin("Herochat") != null) { this.getLogger().info("Found Herochat... Hooking!"); - // this.heroChatListener = new HeroChatListener(this); - // Bukkit.getServer().getPluginManager().registerEvents(heroChatListener, this); } else { this.chatListener = new ChatListener(this); Bukkit.getServer().getPluginManager().registerEvents(chatListener, this); @@ -384,7 +370,7 @@ public class QuickShop extends JavaPlugin { final QS commandExecutor = new QS(this); getCommand("qs").setExecutor(commandExecutor); if (getConfig().getInt("shop.find-distance") > 100) { - getLogger().severe("Shop.find-distance is too high! Pick a number under 100!"); + getLogger().warning("商店查找半径过大 可能导致服务器Lag! 推荐使用低于 100 的配置!"); } new VersionChecker(this); try { diff --git a/src/main/java/org/maxgamer/QuickShop/Shop/ContainerShop.java b/src/main/java/org/maxgamer/QuickShop/Shop/ContainerShop.java index 85803da..75516b1 100644 --- a/src/main/java/org/maxgamer/QuickShop/Shop/ContainerShop.java +++ b/src/main/java/org/maxgamer/QuickShop/Shop/ContainerShop.java @@ -3,7 +3,6 @@ package org.maxgamer.QuickShop.Shop; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.logging.Level; import org.bukkit.Bukkit; @@ -26,7 +25,7 @@ import org.maxgamer.QuickShop.Util.Util; public class ContainerShop implements Shop { private final Location loc; private double price; - private UUID owner; + private String owner; private final ItemStack item; private DisplayItem displayItem; private boolean unlimited; @@ -46,7 +45,7 @@ public class ContainerShop implements Shop { * @param owner * The player who owns this shop. */ - public ContainerShop(final Location loc, final double price, final ItemStack item, final UUID owner) { + public ContainerShop(final Location loc, final double price, final ItemStack item, final String owner) { this.loc = loc; this.price = price; this.owner = owner; @@ -185,6 +184,7 @@ public class ContainerShop implements Shop { * True if you are *NOT* iterating over this currently, *false if * you are iterating* */ + @SuppressWarnings("deprecation") @Override public void delete(final boolean fromMemory) { // Delete the display item @@ -301,7 +301,7 @@ public class ContainerShop implements Shop { * @return The name of the player who owns the shop. */ @Override - public UUID getOwner() { + public String getOwner() { return this.owner; } @@ -562,7 +562,7 @@ public class ContainerShop implements Shop { * it after a reboot. */ @Override - public void setOwner(final UUID owner) { + public void setOwner(final String owner) { this.owner = owner; } diff --git a/src/main/java/org/maxgamer/QuickShop/Shop/Shop.java b/src/main/java/org/maxgamer/QuickShop/Shop/Shop.java index bfce7b6..f1827fa 100644 --- a/src/main/java/org/maxgamer/QuickShop/Shop/Shop.java +++ b/src/main/java/org/maxgamer/QuickShop/Shop/Shop.java @@ -1,7 +1,6 @@ package org.maxgamer.QuickShop.Shop; import java.util.List; -import java.util.UUID; import org.bukkit.Location; import org.bukkit.block.Block; @@ -10,69 +9,69 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public abstract interface Shop { - public abstract Shop clone(); - - public abstract int getRemainingStock(); - - public abstract int getRemainingSpace(); - - public abstract boolean matches(ItemStack paramItemStack); - - public abstract Location getLocation(); - - public abstract double getPrice(); - - public abstract void setPrice(double paramDouble); - - public abstract void update(); - - public abstract short getDurability(); - - public abstract UUID getOwner(); - - public abstract ItemStack getItem(); - - public abstract void remove(ItemStack paramItemStack, int paramInt); - public abstract void add(ItemStack paramItemStack, int paramInt); - public abstract void sell(Player paramPlayer, int paramInt); - public abstract void buy(Player paramPlayer, int paramInt); - public abstract void setOwner(UUID paramString); + public abstract Shop clone(); - public abstract void setUnlimited(boolean paramBoolean); + public abstract void delete(); - public abstract boolean isUnlimited(); + public abstract void delete(boolean paramBoolean); + + public abstract String getDataName(); + + public abstract short getDurability(); + + public abstract ItemStack getItem(); + + public abstract Location getLocation(); + + public abstract String getOwner(); + + public abstract double getPrice(); + + public abstract int getRemainingSpace(); + + public abstract int getRemainingStock(); public abstract ShopType getShopType(); + public abstract List getSigns(); + + public abstract boolean isAttached(Block paramBlock); + public abstract boolean isBuying(); public abstract boolean isSelling(); + public abstract boolean isUnlimited(); + + public abstract boolean isValid(); + + public abstract boolean matches(ItemStack paramItemStack); + + public abstract void onClick(); + + public abstract void onLoad(); + + public abstract void onUnload(); + + public abstract void remove(ItemStack paramItemStack, int paramInt); + + public abstract void sell(Player paramPlayer, int paramInt); + + public abstract void setOwner(String paramString); + + public abstract void setPrice(double paramDouble); + public abstract void setShopType(ShopType paramShopType); public abstract void setSignText(); public abstract void setSignText(String[] paramArrayOfString); - public abstract List getSigns(); + public abstract void setUnlimited(boolean paramBoolean); - public abstract boolean isAttached(Block paramBlock); - - public abstract String getDataName(); - - public abstract void delete(); - - public abstract void delete(boolean paramBoolean); - - public abstract boolean isValid(); - - public abstract void onUnload(); - - public abstract void onLoad(); - - public abstract void onClick(); + public abstract void update(); } \ No newline at end of file diff --git a/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java b/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java index 74537ea..cf83805 100644 --- a/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java +++ b/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java @@ -25,542 +25,10 @@ import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.Util; public class ShopManager { - private QuickShop plugin; - private HashMap actions = new HashMap(); - private HashMap>> shops = new HashMap>>(); - - public ShopManager(QuickShop plugin) { - this.plugin = plugin; - } - - public Database getDatabase() { - return plugin.getDB(); - } - - /** - * @return Returns the HashMap. Info contains what - * their last question etc was. - */ - public HashMap getActions() { - return this.actions; - } - - public void createShop(Shop shop) { - Location loc = shop.getLocation(); - ItemStack item = shop.getItem(); - try { - // Write it to the database - String q = "INSERT INTO shops (owner, price, itemConfig, x, y, z, world, unlimited, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; - plugin.getDB().execute(q, shop.getOwner().toString(), shop.getPrice(), Util.serialize(item), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), loc.getWorld().getName(), (shop.isUnlimited() ? 1 : 0), shop.getShopType().toID()); - // Add it to the world - addShop(loc.getWorld().getName(), shop); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("Could not create shop! Changes will revert after a reboot!"); - } - } - - /** - * Loads the given shop into storage. This method is used for loading data - * from the database. Do not use this method to create a shop. - * - * @param world - * The world the shop is in - * @param shop - * The shop to load - */ - public void loadShop(String world, Shop shop) { - this.addShop(world, shop); - } - - /** - * Returns a hashmap of World -> Chunk -> Shop - * - * @return a hashmap of World -> Chunk -> Shop - */ - public HashMap>> getShops() { - return this.shops; - } - - /** - * Returns a hashmap of Chunk -> Shop - * - * @param world - * The name of the world (case sensitive) to get the list of - * shops from - * @return a hashmap of Chunk -> Shop - */ - public HashMap> getShops(String world) { - return this.shops.get(world); - } - - /** - * Returns a hashmap of Shops - * - * @param c - * The chunk to search. Referencing doesn't matter, only - * coordinates and world are used. - * @return - */ - public HashMap getShops(Chunk c) { - // long start = System.nanoTime(); - HashMap shops = getShops(c.getWorld().getName(), c.getX(), c.getZ()); - // long end = System.nanoTime(); - // System.out.println("Chunk lookup in " + ((end - start)/1000000.0) + - // "ms."); - return shops; - } - - public HashMap getShops(String world, int chunkX, int chunkZ) { - HashMap> inWorld = this.getShops(world); - if (inWorld == null) { - return null; - } - ShopChunk shopChunk = new ShopChunk(world, chunkX, chunkZ); - return inWorld.get(shopChunk); - } - - /** - * Gets a shop in a specific location - * - * @param loc - * The location to get the shop from - * @return The shop at that location - */ - public Shop getShop(Location loc) { - HashMap inChunk = getShops(loc.getChunk()); - if (inChunk == null) { - return null; - } - // We can do this because WorldListener updates the world reference so - // the world in loc is the same as world in inChunk.get(loc) - return inChunk.get(loc); - } - - /** - * Adds a shop to the world. Does NOT require the chunk or world to be - * loaded - * - * @param world - * The name of the world - * @param shop - * The shop to add - */ - private void addShop(String world, Shop shop) { - HashMap> inWorld = this.getShops().get(world); - // There's no world storage yet. We need to create that hashmap. - if (inWorld == null) { - inWorld = new HashMap>(3); - // Put it in the data universe - this.getShops().put(world, inWorld); - } - // Calculate the chunks coordinates. These are 1,2,3 for each chunk, NOT - // location rounded to the nearest 16. - int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0); - int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0); - // Get the chunk set from the world info - ShopChunk shopChunk = new ShopChunk(world, x, z); - HashMap inChunk = inWorld.get(shopChunk); - // That chunk data hasn't been created yet - Create it! - if (inChunk == null) { - inChunk = new HashMap(1); - // Put it in the world - inWorld.put(shopChunk, inChunk); - } - // Put the shop in its location in the chunk list. - inChunk.put(shop.getLocation(), shop); - } - - /** - * Removes a shop from the world. Does NOT remove it from the database. * - * REQUIRES * the world to be loaded - * - * @param shop - * The shop to remove - */ - public void removeShop(Shop shop) { - Location loc = shop.getLocation(); - String world = loc.getWorld().getName(); - HashMap> inWorld = this.getShops().get(world); - int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0); - int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0); - ShopChunk shopChunk = new ShopChunk(world, x, z); - HashMap inChunk = inWorld.get(shopChunk); - inChunk.remove(loc); - } - - /** - * Removes all shops from memory and the world. Does not delete them from - * the database. Call this on plugin disable ONLY. - */ - public void clear() { - if (plugin.display) { - for (World world : Bukkit.getWorlds()) { - for (Chunk chunk : world.getLoadedChunks()) { - HashMap inChunk = this.getShops(chunk); - if (inChunk == null) - continue; - for (Shop shop : inChunk.values()) { - shop.onUnload(); - } - } - } - } - this.actions.clear(); - this.shops.clear(); - } - - /** - * Checks other plugins to make sure they can use the chest they're making a - * shop. - * - * @param p - * The player to check - * @param b - * The block to check - * @return True if they're allowed to place a shop there. - */ - public boolean canBuildShop(Player p, Block b, BlockFace bf) { - if (plugin.limit) { - int owned = 0; - Iterator it = getShopIterator(); - while (it.hasNext()) { - if (it.next().getOwner().equals(p.getUniqueId())) { - owned++; - } - } - int max = plugin.getShopLimit(p); - if (owned + 1 > max) { - p.sendMessage(ChatColor.RED + "You have already created a maximum of " + owned + "/" + max + " shops!"); - return false; - } - } - PlayerInteractEvent pie = new PlayerInteractEvent(p, Action.RIGHT_CLICK_BLOCK, new ItemStack(Material.AIR), b, bf); // PIE = PlayerInteractEvent - What else? - Bukkit.getPluginManager().callEvent(pie); - pie.getPlayer().closeInventory(); // If the player has chat open, this - // will close their chat. - if (pie.isCancelled()) { - return false; - } - ShopPreCreateEvent spce = new ShopPreCreateEvent(p, b.getLocation()); - Bukkit.getPluginManager().callEvent(spce); - if (spce.isCancelled()) { - return false; - } - return true; - } - - public void handleChat(final Player p, String msg) { - final String message = ChatColor.stripColor(msg); - // Use from the main thread, because Bukkit hates life - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { - @SuppressWarnings("deprecation") - @Override - public void run() { - HashMap actions = getActions(); - // They wanted to do something. - Info info = actions.remove(p.getUniqueId()); - if (info == null) - return; // multithreaded means this can happen - if (info.getLocation().getWorld() != p.getLocation().getWorld()) { - p.sendMessage(MsgUtil.p("shop-creation-cancelled")); - return; - } - if (info.getLocation().distanceSquared(p.getLocation()) > 25) { - p.sendMessage(MsgUtil.p("shop-creation-cancelled")); - return; - } - /* Creation handling */ - if (info.getAction() == ShopAction.CREATE) { - try { - // Checking the shop can be created - if (plugin.getShopManager().getShop(info.getLocation()) != null) { - p.sendMessage(MsgUtil.p("shop-already-owned")); - return; - } - if (Util.getSecondHalf(info.getLocation().getBlock()) != null && !p.hasPermission("quickshop.create.double")) { - p.sendMessage(MsgUtil.p("no-double-chests")); - return; - } - if (Util.canBeShop(info.getLocation().getBlock()) == false) { - p.sendMessage(MsgUtil.p("chest-was-removed")); - return; - } - // Price per item - double price; - if (plugin.getConfig().getBoolean("whole-number-prices-only")) { - price = Integer.parseInt(message); - } else { - price = Double.parseDouble(message); - } - if (price < 0.01) { - p.sendMessage(MsgUtil.p("price-too-cheap")); - return; - } - double tax = plugin.getConfig().getDouble("shop.cost"); - // Tax refers to the cost to create a shop. Not actual - // tax, that would be silly - if (tax != 0 && plugin.getEcon().getBalance(p.getName()) < tax) { - p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax))); - return; - } - // Create the sample shop. - Shop shop = new ContainerShop(info.getLocation(), price, info.getItem(), p.getUniqueId()); - shop.onLoad(); - ShopCreateEvent e = new ShopCreateEvent(shop, p); - Bukkit.getPluginManager().callEvent(e); - if (e.isCancelled()) { - shop.onUnload(); - return; - } - // This must be called after the event has been called. - // Else, if the event is cancelled, they won't get their - // money back. - if (tax != 0) { - if (!plugin.getEcon().withdraw(p.getName(), tax)) { - p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax))); - shop.onUnload(); - return; - } - plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), tax); - } - /* The shop has hereforth been successfully created */ - createShop(shop); - Location loc = shop.getLocation(); - plugin.log(p.getName() + " created a " + shop.getDataName() + " shop at (" + loc.getWorld().getName() + " - " + loc.getX() + "," + loc.getY() + "," + loc.getZ() + ")"); - if (!plugin.getConfig().getBoolean("shop.lock")) { - // Warn them if they haven't been warned since - // reboot - if (!plugin.warnings.contains(p.getName())) { - p.sendMessage(MsgUtil.p("shops-arent-locked")); - plugin.warnings.add(p.getName()); - } - } - // Figures out which way we should put the sign on and - // sets its text. - if (info.getSignBlock() != null && info.getSignBlock().getType() == Material.AIR && plugin.getConfig().getBoolean("shop.auto-sign")) { - BlockState bs = info.getSignBlock().getState(); - BlockFace bf = info.getLocation().getBlock().getFace(info.getSignBlock()); - bs.setType(Material.WALL_SIGN); - Sign sign = (Sign) bs.getData(); - sign.setFacingDirection(bf); - bs.update(true); - shop.setSignText(); - /* - * Block b = shop.getLocation().getBlock(); - * ItemFrame iFrame = (ItemFrame) - * b.getWorld().spawnEntity(b.getLocation(), - * EntityType.ITEM_FRAME); - * - * BlockFace[] faces = new - * BlockFace[]{BlockFace.NORTH, BlockFace.EAST, - * BlockFace.SOUTH, BlockFace.WEST}; for(BlockFace - * face : faces){ if(face == bf) continue; //This is - * the sign's location iFrame.setFacingDirection(bf, - * true); //iFrame.setItem(shop.getItem()); - * ItemStack iStack = shop.getItem().clone(); - * iStack.setAmount(0); iFrame.setItem(iStack); /* - * Field handleField = - * iFrame.getClass().getField("entity"); - * handleField.setAccessible(true); Object handle = - * handleField.get(iFrame); - * - * ItemStack bukkitStack = shop.getItem(); - * - * Field itemStackHandle = - * - * Method setItemStack = - * handle.getClass().getMethod("a", Object.class); - * setItemStack. - */ - // } - } - if (shop instanceof ContainerShop) { - ContainerShop cs = (ContainerShop) shop; - if (cs.isDoubleShop()) { - Shop nextTo = cs.getAttachedShop(); - if (nextTo.getPrice() > shop.getPrice()) { - // The one next to it must always be a - // buying shop. - p.sendMessage(MsgUtil.p("buying-more-than-selling")); - } - } - } - } - /* They didn't enter a number. */ - catch (NumberFormatException ex) { - p.sendMessage(MsgUtil.p("shop-creation-cancelled")); - return; - } - } - /* Purchase Handling */ - else if (info.getAction() == ShopAction.BUY) { - int amount = 0; - try { - amount = Integer.parseInt(message); - } catch (NumberFormatException e) { - p.sendMessage(MsgUtil.p("shop-purchase-cancelled")); - return; - } - // Get the shop they interacted with - Shop shop = plugin.getShopManager().getShop(info.getLocation()); - // It's not valid anymore - if (shop == null || Util.canBeShop(info.getLocation().getBlock()) == false) { - p.sendMessage(MsgUtil.p("chest-was-removed")); - return; - } - if (info.hasChanged(shop)) { - p.sendMessage(MsgUtil.p("shop-has-changed")); - return; - } - if (shop.isSelling()) { - int stock = shop.getRemainingStock(); - if (stock < amount) { - p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), shop.getDataName())); - return; - } - if (amount == 0) { - // Dumb. - MsgUtil.sendPurchaseSuccess(p, shop, amount); - return; - } else if (amount < 0) { - // & Dumber - p.sendMessage(MsgUtil.p("negative-amount")); - return; - } - int pSpace = Util.countSpace(p.getInventory(), shop.getItem()); - if (amount > pSpace) { - p.sendMessage(MsgUtil.p("not-enough-space", "" + pSpace)); - return; - } - ShopPurchaseEvent e = new ShopPurchaseEvent(shop, p, amount); - Bukkit.getPluginManager().callEvent(e); - if (e.isCancelled()) - return; // Cancelled - // Money handling - if (!p.getUniqueId().equals(shop.getOwner())) { - // Check their balance. Works with *most* economy - // plugins* - if (plugin.getEcon().getBalance(p.getName()) < amount * shop.getPrice()) { - p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName())))); - return; - } - // Don't tax them if they're purchasing from - // themselves. - // Do charge an amount of tax though. - double tax = plugin.getConfig().getDouble("tax"); - double total = amount * shop.getPrice(); - if (!plugin.getEcon().withdraw(p.getUniqueId(), total)) { - p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName())))); - return; - } - if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) { - plugin.getEcon().deposit(shop.getOwner(), total * (1 - tax)); - if (tax != 0) { - plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), total * tax); - } - } - // Notify the shop owner - if (plugin.getConfig().getBoolean("show-tax")) { - String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total))); - if (stock == amount) - msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName()); - MsgUtil.send(shop.getOwner(), msg); - } else { - String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName()); - if (stock == amount) - msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName()); - MsgUtil.send(shop.getOwner(), msg); - } - } - // Transfers the item from A to B - shop.sell(p, amount); - MsgUtil.sendPurchaseSuccess(p, shop, amount); - plugin.log(p.getName() + " bought " + amount + " for " + (shop.getPrice() * amount) + " from " + shop.toString()); - } else if (shop.isBuying()) { - int space = shop.getRemainingSpace(); - if (space < amount) { - p.sendMessage(MsgUtil.p("shop-has-no-space", "" + space, shop.getDataName())); - return; - } - int count = Util.countItems(p.getInventory(), shop.getItem()); - // Not enough items - if (amount > count) { - p.sendMessage(MsgUtil.p("you-dont-have-that-many-items", "" + count, shop.getDataName())); - return; - } - if (amount == 0) { - // Dumb. - MsgUtil.sendPurchaseSuccess(p, shop, amount); - return; - } else if (amount < 0) { - // & Dumber - p.sendMessage(MsgUtil.p("negative-amount")); - return; - } - // Money handling - if (!p.getUniqueId().equals(shop.getOwner())) { - // Don't tax them if they're purchasing from - // themselves. - // Do charge an amount of tax though. - double tax = plugin.getConfig().getDouble("tax"); - double total = amount * shop.getPrice(); - if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) { - // Tries to check their balance nicely to see if - // they can afford it. - if (plugin.getEcon().getBalance(shop.getOwner()) < amount * shop.getPrice()) { - p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner())))); - return; - } - // Check for plugins faking econ.has(amount) - if (!plugin.getEcon().withdraw(shop.getOwner(), total)) { - p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner())))); - return; - } - if (tax != 0) { - plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), total * tax); - } - } - // Give them the money after we know we succeeded - plugin.getEcon().deposit(p.getName(), total * (1 - tax)); - // Notify the owner of the purchase. - String msg = MsgUtil.p("player-sold-to-your-store", p.getName(), "" + amount, shop.getDataName()); - if (space == amount) - msg += "\n" + MsgUtil.p("shop-out-of-space", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ()); - MsgUtil.send(shop.getOwner(), msg); - } - shop.buy(p, amount); - MsgUtil.sendSellSuccess(p, shop, amount); - plugin.log(p.getName() + " sold " + amount + " for " + (shop.getPrice() * amount) + " to " + shop.toString()); - } - shop.setSignText(); // Update the signs count - } - /* If it was already cancelled (from destroyed) */ - else { - return; // It was cancelled, go away. - } - } - }); - } - - /** - * Returns a new shop iterator object, allowing iteration over shops easily, - * instead of sorting through a 3D hashmap. - * - * @return a new shop iterator object. - */ - public Iterator getShopIterator() { - return new ShopIterator(); - } - - public String format(double d) { - return plugin.getEcon().format(d); - } - public class ShopIterator implements Iterator { private Iterator shops; private Iterator> chunks; - private Iterator>> worlds; + private final Iterator>> worlds; private Shop current; public ShopIterator() { @@ -603,8 +71,9 @@ public class ShopManager { } shops = chunks.next().values().iterator(); } - if (!shops.hasNext()) + if (!shops.hasNext()) { return this.next(); // Skip to the next one (Empty iterator?) + } current = shops.next(); return current; } @@ -619,4 +88,546 @@ public class ShopManager { shops.remove(); } } + + private final QuickShop plugin; + private final HashMap actions = new HashMap(); + + private final HashMap>> shops = new HashMap>>(); + + public ShopManager(final QuickShop plugin) { + this.plugin = plugin; + } + + /** + * Checks other plugins to make sure they can use the chest they're making a + * shop. + * + * @param p + * The player to check + * @param b + * The block to check + * @return True if they're allowed to place a shop there. + */ + public boolean canBuildShop(final Player p, final Block b, final BlockFace bf) { + if (plugin.limit) { + int owned = 0; + final Iterator it = getShopIterator(); + while (it.hasNext()) { + if (it.next().getOwner().equals(p.getUniqueId())) { + owned++; + } + } + final int max = plugin.getShopLimit(p); + if (owned + 1 > max) { + p.sendMessage(ChatColor.RED + "You have already created a maximum of " + owned + "/" + max + " shops!"); + return false; + } + } + final PlayerInteractEvent pie = new PlayerInteractEvent(p, Action.RIGHT_CLICK_BLOCK, new ItemStack(Material.AIR), b, bf); // PIE = PlayerInteractEvent - What else? + Bukkit.getPluginManager().callEvent(pie); + pie.getPlayer().closeInventory(); // If the player has chat open, this + // will close their chat. + if (pie.isCancelled()) { + return false; + } + final ShopPreCreateEvent spce = new ShopPreCreateEvent(p, b.getLocation()); + Bukkit.getPluginManager().callEvent(spce); + if (spce.isCancelled()) { + return false; + } + return true; + } + + /** + * Removes all shops from memory and the world. Does not delete them from + * the database. Call this on plugin disable ONLY. + */ + public void clear() { + if (plugin.display) { + for (final World world : Bukkit.getWorlds()) { + for (final Chunk chunk : world.getLoadedChunks()) { + final HashMap inChunk = this.getShops(chunk); + if (inChunk == null) { + continue; + } + for (final Shop shop : inChunk.values()) { + shop.onUnload(); + } + } + } + } + this.actions.clear(); + this.shops.clear(); + } + + public void createShop(final Shop shop) { + final Location loc = shop.getLocation(); + final ItemStack item = shop.getItem(); + try { + // Write it to the database + final String q = "INSERT INTO shops (owner, price, itemConfig, x, y, z, world, unlimited, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + plugin.getDB().execute(q, shop.getOwner().toString(), shop.getPrice(), Util.serialize(item), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), loc.getWorld().getName(), + (shop.isUnlimited() ? 1 : 0), shop.getShopType().toID()); + // Add it to the world + addShop(loc.getWorld().getName(), shop); + } catch (final Exception e) { + e.printStackTrace(); + System.out.println("Could not create shop! Changes will revert after a reboot!"); + } + } + + public String format(final double d) { + return plugin.getEcon().format(d); + } + + /** + * @return Returns the HashMap. Info contains what + * their last question etc was. + */ + public HashMap getActions() { + return this.actions; + } + + public Database getDatabase() { + return plugin.getDB(); + } + + /** + * Gets a shop in a specific location + * + * @param loc + * The location to get the shop from + * @return The shop at that location + */ + public Shop getShop(final Location loc) { + final HashMap inChunk = getShops(loc.getChunk()); + if (inChunk == null) { + return null; + } + // We can do this because WorldListener updates the world reference so + // the world in loc is the same as world in inChunk.get(loc) + return inChunk.get(loc); + } + + /** + * Returns a new shop iterator object, allowing iteration over shops easily, + * instead of sorting through a 3D hashmap. + * + * @return a new shop iterator object. + */ + public Iterator getShopIterator() { + return new ShopIterator(); + } + + /** + * Returns a hashmap of World -> Chunk -> Shop + * + * @return a hashmap of World -> Chunk -> Shop + */ + public HashMap>> getShops() { + return this.shops; + } + + /** + * Returns a hashmap of Shops + * + * @param c + * The chunk to search. Referencing doesn't matter, only + * coordinates and world are used. + * @return + */ + public HashMap getShops(final Chunk c) { + // long start = System.nanoTime(); + final HashMap shops = getShops(c.getWorld().getName(), c.getX(), c.getZ()); + // long end = System.nanoTime(); + // System.out.println("Chunk lookup in " + ((end - start)/1000000.0) + + // "ms."); + return shops; + } + + /** + * Returns a hashmap of Chunk -> Shop + * + * @param world + * The name of the world (case sensitive) to get the list of + * shops from + * @return a hashmap of Chunk -> Shop + */ + public HashMap> getShops(final String world) { + return this.shops.get(world); + } + + public HashMap getShops(final String world, final int chunkX, final int chunkZ) { + final HashMap> inWorld = this.getShops(world); + if (inWorld == null) { + return null; + } + final ShopChunk shopChunk = new ShopChunk(world, chunkX, chunkZ); + return inWorld.get(shopChunk); + } + + public void handleChat(final Player p, final String msg) { + final String message = ChatColor.stripColor(msg); + // Use from the main thread, because Bukkit hates life + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + @SuppressWarnings("deprecation") + @Override + public void run() { + final HashMap actions = getActions(); + // They wanted to do something. + final Info info = actions.remove(p.getUniqueId()); + if (info == null) { + return; // multithreaded means this can happen + } + if (info.getLocation().getWorld() != p.getLocation().getWorld()) { + p.sendMessage(MsgUtil.p("shop-creation-cancelled")); + return; + } + if (info.getLocation().distanceSquared(p.getLocation()) > 25) { + p.sendMessage(MsgUtil.p("shop-creation-cancelled")); + return; + } + /* Creation handling */ + if (info.getAction() == ShopAction.CREATE) { + try { + // Checking the shop can be created + if (plugin.getShopManager().getShop(info.getLocation()) != null) { + p.sendMessage(MsgUtil.p("shop-already-owned")); + return; + } + if (Util.getSecondHalf(info.getLocation().getBlock()) != null && !p.hasPermission("quickshop.create.double")) { + p.sendMessage(MsgUtil.p("no-double-chests")); + return; + } + if (Util.canBeShop(info.getLocation().getBlock()) == false) { + p.sendMessage(MsgUtil.p("chest-was-removed")); + return; + } + // Price per item + double price; + if (plugin.getConfig().getBoolean("whole-number-prices-only")) { + price = Integer.parseInt(message); + } else { + price = Double.parseDouble(message); + } + if (price < 0.01) { + p.sendMessage(MsgUtil.p("price-too-cheap")); + return; + } + final double tax = plugin.getConfig().getDouble("shop.cost"); + // Tax refers to the cost to create a shop. Not actual + // tax, that would be silly + if (tax != 0 && plugin.getEcon().getBalance(p.getName()) < tax) { + p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax))); + return; + } + // Create the sample shop. + final Shop shop = new ContainerShop(info.getLocation(), price, info.getItem(), p.getName()); + shop.onLoad(); + final ShopCreateEvent e = new ShopCreateEvent(shop, p); + Bukkit.getPluginManager().callEvent(e); + if (e.isCancelled()) { + shop.onUnload(); + return; + } + // This must be called after the event has been called. + // Else, if the event is cancelled, they won't get their + // money back. + if (tax != 0) { + if (!plugin.getEcon().withdraw(p.getName(), tax)) { + p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax))); + shop.onUnload(); + return; + } + plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), tax); + } + /* The shop has hereforth been successfully created */ + createShop(shop); + final Location loc = shop.getLocation(); + plugin.log(p.getName() + " created a " + shop.getDataName() + " shop at (" + loc.getWorld().getName() + " - " + loc.getX() + "," + loc.getY() + "," + loc.getZ() + ")"); + if (!plugin.getConfig().getBoolean("shop.lock")) { + // Warn them if they haven't been warned since + // reboot + if (!plugin.warnings.contains(p.getName())) { + p.sendMessage(MsgUtil.p("shops-arent-locked")); + plugin.warnings.add(p.getName()); + } + } + // Figures out which way we should put the sign on and + // sets its text. + if (info.getSignBlock() != null && info.getSignBlock().getType() == Material.AIR && plugin.getConfig().getBoolean("shop.auto-sign")) { + final BlockState bs = info.getSignBlock().getState(); + final BlockFace bf = info.getLocation().getBlock().getFace(info.getSignBlock()); + bs.setType(Material.WALL_SIGN); + final Sign sign = (Sign) bs.getData(); + sign.setFacingDirection(bf); + bs.update(true); + shop.setSignText(); + /* + * Block b = shop.getLocation().getBlock(); + * ItemFrame iFrame = (ItemFrame) + * b.getWorld().spawnEntity(b.getLocation(), + * EntityType.ITEM_FRAME); + * + * BlockFace[] faces = new + * BlockFace[]{BlockFace.NORTH, BlockFace.EAST, + * BlockFace.SOUTH, BlockFace.WEST}; for(BlockFace + * face : faces){ if(face == bf) continue; //This is + * the sign's location iFrame.setFacingDirection(bf, + * true); //iFrame.setItem(shop.getItem()); + * ItemStack iStack = shop.getItem().clone(); + * iStack.setAmount(0); iFrame.setItem(iStack); /* + * Field handleField = + * iFrame.getClass().getField("entity"); + * handleField.setAccessible(true); Object handle = + * handleField.get(iFrame); + * + * ItemStack bukkitStack = shop.getItem(); + * + * Field itemStackHandle = + * + * Method setItemStack = + * handle.getClass().getMethod("a", Object.class); + * setItemStack. + */ + // } + } + if (shop instanceof ContainerShop) { + final ContainerShop cs = (ContainerShop) shop; + if (cs.isDoubleShop()) { + final Shop nextTo = cs.getAttachedShop(); + if (nextTo.getPrice() > shop.getPrice()) { + // The one next to it must always be a + // buying shop. + p.sendMessage(MsgUtil.p("buying-more-than-selling")); + } + } + } + } + /* They didn't enter a number. */ + catch (final NumberFormatException ex) { + p.sendMessage(MsgUtil.p("shop-creation-cancelled")); + return; + } + } + /* Purchase Handling */ + else if (info.getAction() == ShopAction.BUY) { + int amount = 0; + try { + amount = Integer.parseInt(message); + } catch (final NumberFormatException e) { + p.sendMessage(MsgUtil.p("shop-purchase-cancelled")); + return; + } + // Get the shop they interacted with + final Shop shop = plugin.getShopManager().getShop(info.getLocation()); + // It's not valid anymore + if (shop == null || Util.canBeShop(info.getLocation().getBlock()) == false) { + p.sendMessage(MsgUtil.p("chest-was-removed")); + return; + } + if (info.hasChanged(shop)) { + p.sendMessage(MsgUtil.p("shop-has-changed")); + return; + } + if (shop.isSelling()) { + final int stock = shop.getRemainingStock(); + if (stock < amount) { + p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), shop.getDataName())); + return; + } + if (amount == 0) { + // Dumb. + MsgUtil.sendPurchaseSuccess(p, shop, amount); + return; + } else if (amount < 0) { + // & Dumber + p.sendMessage(MsgUtil.p("negative-amount")); + return; + } + final int pSpace = Util.countSpace(p.getInventory(), shop.getItem()); + if (amount > pSpace) { + p.sendMessage(MsgUtil.p("not-enough-space", "" + pSpace)); + return; + } + final ShopPurchaseEvent e = new ShopPurchaseEvent(shop, p, amount); + Bukkit.getPluginManager().callEvent(e); + if (e.isCancelled()) { + return; // Cancelled + } + // Money handling + if (!p.getUniqueId().equals(shop.getOwner())) { + // Check their balance. Works with *most* economy + // plugins* + if (plugin.getEcon().getBalance(p.getName()) < amount * shop.getPrice()) { + p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName())))); + return; + } + // Don't tax them if they're purchasing from + // themselves. + // Do charge an amount of tax though. + final double tax = plugin.getConfig().getDouble("tax"); + final double total = amount * shop.getPrice(); + if (!plugin.getEcon().withdraw(p.getUniqueId(), total)) { + p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName())))); + return; + } + if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) { + plugin.getEcon().deposit(shop.getOwner(), total * (1 - tax)); + if (tax != 0) { + plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), total * tax); + } + } + // Notify the shop owner + if (plugin.getConfig().getBoolean("show-tax")) { + String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total))); + if (stock == amount) { + msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), + shop.getDataName()); + } + MsgUtil.send(shop.getOwner(), msg); + } else { + String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName()); + if (stock == amount) { + msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), + shop.getDataName()); + } + MsgUtil.send(shop.getOwner(), msg); + } + } + // Transfers the item from A to B + shop.sell(p, amount); + MsgUtil.sendPurchaseSuccess(p, shop, amount); + plugin.log(p.getName() + " bought " + amount + " for " + (shop.getPrice() * amount) + " from " + shop.toString()); + } else if (shop.isBuying()) { + final int space = shop.getRemainingSpace(); + if (space < amount) { + p.sendMessage(MsgUtil.p("shop-has-no-space", "" + space, shop.getDataName())); + return; + } + final int count = Util.countItems(p.getInventory(), shop.getItem()); + // Not enough items + if (amount > count) { + p.sendMessage(MsgUtil.p("you-dont-have-that-many-items", "" + count, shop.getDataName())); + return; + } + if (amount == 0) { + // Dumb. + MsgUtil.sendPurchaseSuccess(p, shop, amount); + return; + } else if (amount < 0) { + // & Dumber + p.sendMessage(MsgUtil.p("negative-amount")); + return; + } + // Money handling + if (!p.getUniqueId().equals(shop.getOwner())) { + // Don't tax them if they're purchasing from + // themselves. + // Do charge an amount of tax though. + final double tax = plugin.getConfig().getDouble("tax"); + final double total = amount * shop.getPrice(); + if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) { + // Tries to check their balance nicely to see if + // they can afford it. + if (plugin.getEcon().getBalance(shop.getOwner()) < amount * shop.getPrice()) { + p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner())))); + return; + } + // Check for plugins faking econ.has(amount) + if (!plugin.getEcon().withdraw(shop.getOwner(), total)) { + p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner())))); + return; + } + if (tax != 0) { + plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), total * tax); + } + } + // Give them the money after we know we succeeded + plugin.getEcon().deposit(p.getName(), total * (1 - tax)); + // Notify the owner of the purchase. + String msg = MsgUtil.p("player-sold-to-your-store", p.getName(), "" + amount, shop.getDataName()); + if (space == amount) { + msg += "\n" + MsgUtil.p("shop-out-of-space", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ()); + } + MsgUtil.send(shop.getOwner(), msg); + } + shop.buy(p, amount); + MsgUtil.sendSellSuccess(p, shop, amount); + plugin.log(p.getName() + " sold " + amount + " for " + (shop.getPrice() * amount) + " to " + shop.toString()); + } + shop.setSignText(); // Update the signs count + } + /* If it was already cancelled (from destroyed) */ + else { + return; // It was cancelled, go away. + } + } + }); + } + + /** + * Loads the given shop into storage. This method is used for loading data + * from the database. Do not use this method to create a shop. + * + * @param world + * The world the shop is in + * @param shop + * The shop to load + */ + public void loadShop(final String world, final Shop shop) { + this.addShop(world, shop); + } + + /** + * Removes a shop from the world. Does NOT remove it from the database. * + * REQUIRES * the world to be loaded + * + * @param shop + * The shop to remove + */ + public void removeShop(final Shop shop) { + final Location loc = shop.getLocation(); + final String world = loc.getWorld().getName(); + final HashMap> inWorld = this.getShops().get(world); + final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0); + final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0); + final ShopChunk shopChunk = new ShopChunk(world, x, z); + final HashMap inChunk = inWorld.get(shopChunk); + inChunk.remove(loc); + } + + /** + * Adds a shop to the world. Does NOT require the chunk or world to be + * loaded + * + * @param world + * The name of the world + * @param shop + * The shop to add + */ + private void addShop(final String world, final Shop shop) { + HashMap> inWorld = this.getShops().get(world); + // There's no world storage yet. We need to create that hashmap. + if (inWorld == null) { + inWorld = new HashMap>(3); + // Put it in the data universe + this.getShops().put(world, inWorld); + } + // Calculate the chunks coordinates. These are 1,2,3 for each chunk, NOT + // location rounded to the nearest 16. + final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0); + final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0); + // Get the chunk set from the world info + final ShopChunk shopChunk = new ShopChunk(world, x, z); + HashMap inChunk = inWorld.get(shopChunk); + // That chunk data hasn't been created yet - Create it! + if (inChunk == null) { + inChunk = new HashMap(1); + // Put it in the world + inWorld.put(shopChunk, inChunk); + } + // Put the shop in its location in the chunk list. + inChunk.put(shop.getLocation(), shop); + } } \ No newline at end of file diff --git a/src/main/java/org/maxgamer/QuickShop/Util/Converter.java b/src/main/java/org/maxgamer/QuickShop/Util/Converter.java deleted file mode 100644 index 2960d21..0000000 --- a/src/main/java/org/maxgamer/QuickShop/Util/Converter.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.maxgamer.QuickShop.Util; - -public class Converter { - /** - * Attempts to convert the quickshop database, if necessary. - * - * @return -1 for failure, 0 for no changes, 1 for success converting. - */ - public static int convert() { - return 0; - } -} \ No newline at end of file diff --git a/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java b/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java index 32f7cd4..8b0ff80 100644 --- a/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java +++ b/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java @@ -24,7 +24,7 @@ import mkremins.fanciful.FancyMessage; public class MsgUtil { private static QuickShop plugin; private static FileConfig messages; - private static HashMap> player_messages = new HashMap>(); + private static HashMap> player_messages = new HashMap>(); static { plugin = QuickShop.instance; @@ -82,7 +82,7 @@ public class MsgUtil { try { final ResultSet rs = plugin.getDB().getConnection().prepareStatement("SELECT * FROM messages").executeQuery(); while (rs.next()) { - final UUID owner = UUID.fromString(rs.getString("owner")); + final String owner = rs.getString("owner"); final String message = rs.getString("message"); LinkedList msgs = player_messages.get(owner); if (msgs == null) { @@ -119,7 +119,8 @@ public class MsgUtil { * they're online. Else, if they're not online, queues it for * them in the database. */ - public static void send(final UUID player, final String message) { // TODO Converted to UUID + public static void send(final String player, final String message) { // TODO Converted to UUID + @SuppressWarnings("deprecation") final OfflinePlayer p = Bukkit.getOfflinePlayer(player); if (p == null || !p.isOnline()) { LinkedList msgs = player_messages.get(player); @@ -219,6 +220,7 @@ public class MsgUtil { sendShopInfo(p, shop, shop.getRemainingStock()); } + @SuppressWarnings("deprecation") public static void sendShopInfo(final Player p, final Shop shop, final int stock) { // Potentially faster with an array? final ItemStack items = shop.getItem(); diff --git a/src/main/java/org/maxgamer/QuickShop/Util/NMS.java b/src/main/java/org/maxgamer/QuickShop/Util/NMS.java index 1a06c88..7f40985 100644 --- a/src/main/java/org/maxgamer/QuickShop/Util/NMS.java +++ b/src/main/java/org/maxgamer/QuickShop/Util/NMS.java @@ -3,156 +3,11 @@ package org.maxgamer.QuickShop.Util; import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.bukkit.ChatColor; import org.bukkit.entity.Item; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.maxgamer.QuickShop.QuickShop; public class NMS { - // private static ArrayList dependents = new ArrayList(); - private static int nextId = 0; - // private static NMSDependent nms; - - // static { - // NMSDependent dep; - // dep = new NMSDependent("v1_6_R3") { - // @Override - // public void safeGuard(Item item) { - // org.bukkit.inventory.ItemStack iStack = item.getItemStack(); - // net.minecraft.server.v1_6_R3.ItemStack nmsI = org.bukkit.craftbukkit.v1_6_R3.inventory.CraftItemStack.asNMSCopy(iStack); - // nmsI.count = 0; - // iStack = org.bukkit.craftbukkit.v1_6_R3.inventory.CraftItemStack.asBukkitCopy(nmsI); - // item.setItemStack(iStack); - // } - // - // @Override - // public byte[] getNBTBytes(org.bukkit.inventory.ItemStack iStack) { - // net.minecraft.server.v1_6_R3.ItemStack is = org.bukkit.craftbukkit.v1_6_R3.inventory.CraftItemStack.asNMSCopy(iStack); - // net.minecraft.server.v1_6_R3.NBTTagCompound itemCompound = new net.minecraft.server.v1_6_R3.NBTTagCompound(); - // itemCompound = is.save(itemCompound); - // return net.minecraft.server.v1_6_R3.NBTCompressedStreamTools.a(itemCompound); - // } - // - // @Override - // public org.bukkit.inventory.ItemStack getItemStack(byte[] bytes) { - // net.minecraft.server.v1_6_R3.NBTTagCompound c = net.minecraft.server.v1_6_R3.NBTCompressedStreamTools.a(bytes); - // net.minecraft.server.v1_6_R3.ItemStack is = net.minecraft.server.v1_6_R3.ItemStack.createStack(c); - // return org.bukkit.craftbukkit.v1_6_R3.inventory.CraftItemStack.asBukkitCopy(is); - // } - // }; - // dependents.add(dep); - // dep = new NMSDependent("v1_7_R1") { - // @Override - // public void safeGuard(Item item) { - // if(QuickShop.debug)System.out.println("safeGuard"); - // org.bukkit.inventory.ItemStack iStack = item.getItemStack(); - // net.minecraft.server.v1_7_R1.ItemStack nmsI = org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemStack.asNMSCopy(iStack); - // nmsI.count = 0; - // iStack = org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemStack.asBukkitCopy(nmsI); - // item.setItemStack(iStack); - // } - // - // @Override - // public byte[] getNBTBytes(org.bukkit.inventory.ItemStack iStack) { - // if(QuickShop.debug)System.out.println("getNBTBytes"); - // net.minecraft.server.v1_7_R1.ItemStack is = org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemStack.asNMSCopy(iStack); - // net.minecraft.server.v1_7_R1.NBTTagCompound itemCompound = new net.minecraft.server.v1_7_R1.NBTTagCompound(); - // itemCompound = is.save(itemCompound); - // return net.minecraft.server.v1_7_R1.NBTCompressedStreamTools.a(itemCompound); - // } - // - // @Override - // public org.bukkit.inventory.ItemStack getItemStack(byte[] bytes) { - // if(QuickShop.debug)System.out.println("getItemStack"); - // net.minecraft.server.v1_7_R1.NBTTagCompound c = net.minecraft.server.v1_7_R1.NBTCompressedStreamTools.a(bytes); - // net.minecraft.server.v1_7_R1.ItemStack is = net.minecraft.server.v1_7_R1.ItemStack.createStack(c); - // return org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemStack.asBukkitCopy(is); - // } - // }; - // dependents.add(dep); - // dep = new NMSDependent("v1_7_R3") { - // @Override - // public void safeGuard(Item item) { - // if(QuickShop.debug)System.out.println("safeGuard"); - // org.bukkit.inventory.ItemStack iStack = item.getItemStack(); - // net.minecraft.server.v1_7_R3.ItemStack nmsI = org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemStack.asNMSCopy(iStack); - // nmsI.count = 0; - // iStack = org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemStack.asBukkitCopy(nmsI); - // item.setItemStack(iStack); - // } - // - // @Override - // public byte[] getNBTBytes(org.bukkit.inventory.ItemStack iStack) { - // if(QuickShop.debug)System.out.println("getNBTBytes"); - // net.minecraft.server.v1_7_R3.ItemStack is = org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemStack.asNMSCopy(iStack); - // net.minecraft.server.v1_7_R3.NBTTagCompound itemCompound = new net.minecraft.server.v1_7_R3.NBTTagCompound(); - // itemCompound = is.save(itemCompound); - // return net.minecraft.server.v1_7_R3.NBTCompressedStreamTools.a(itemCompound); - // } - // - // @Override - // public org.bukkit.inventory.ItemStack getItemStack(byte[] bytes) { - // if(QuickShop.debug)System.out.println("getItemStack"); - // net.minecraft.server.v1_7_R3.NBTTagCompound c = net.minecraft.server.v1_7_R3.NBTCompressedStreamTools.a(bytes, null); - // net.minecraft.server.v1_7_R3.ItemStack is = net.minecraft.server.v1_7_R3.ItemStack.createStack(c); - // return org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemStack.asBukkitCopy(is); - // } - // }; - // dependents.add(dep); - // dep = new NMSDependent("v1_8") { - // @Override - // public void safeGuard(Item item) { - // if(QuickShop.debug)System.out.println("safeGuard"); - // org.bukkit.inventory.ItemStack iStack = item.getItemStack(); - // net.minecraft.server.v1_8_R1.ItemStack nmsI = org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack.asNMSCopy(iStack); - // nmsI.count = 0; - // iStack = org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack.asBukkitCopy(nmsI); - // item.setItemStack(iStack); - // } - // - // @Override - // public byte[] getNBTBytes(org.bukkit.inventory.ItemStack iStack) { - // try{ - // if(QuickShop.debug)System.out.println("getNBTBytes"); - // net.minecraft.server.v1_8_R1.ItemStack is = org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack.asNMSCopy(iStack); - // net.minecraft.server.v1_8_R1.NBTTagCompound itemCompound = new net.minecraft.server.v1_8_R1.NBTTagCompound(); - // itemCompound = is.save(itemCompound); - // ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); - // DataOutputStream dataoutputstream = new DataOutputStream(new GZIPOutputStream(bytearrayoutputstream)); - // try { - // net.minecraft.server.v1_8_R1.NBTCompressedStreamTools.a(itemCompound, (DataOutput) dataoutputstream); - // } finally { - // dataoutputstream.close(); - // } - // return bytearrayoutputstream.toByteArray(); - // }catch(Exception e){ - // return new byte[0]; - // } - // //return net.minecraft.server.v1_8_R1.NBTCompressedStreamTools.a(itemCompound); - // } - // - // @Override - // public org.bukkit.inventory.ItemStack getItemStack(byte[] bytes) { - // try{ - // if(QuickShop.debug)System.out.println("getItemStack"); - // DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(bytes)))); - // net.minecraft.server.v1_8_R1.NBTTagCompound nbttagcompound; - // try { - // nbttagcompound = net.minecraft.server.v1_8_R1.NBTCompressedStreamTools.a((DataInput) datainputstream, null); - // } finally { - // datainputstream.close(); - // } - // //net.minecraft.server.v1_8_R1.NBTTagCompound c = net.minecraft.server.v1_8_R1.NBTCompressedStreamTools.a(bytes, null); - // net.minecraft.server.v1_8_R1.ItemStack is = net.minecraft.server.v1_8_R1.ItemStack.createStack(nbttagcompound); - // return org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack.asBukkitCopy(is); - // }catch(Exception e){ - // return new ItemStack(Material.AIR); - // } - // } - // }; - // dependents.add(dep); - // } public static void safeGuard(final Item item) throws ClassNotFoundException { if (QuickShop.debug) { @@ -202,53 +57,7 @@ public class NMS { } } - // public static byte[] getNBTBytes(org.bukkit.inventory.ItemStack iStack) throws ClassNotFoundException { - // validate(); - // return nms.getNBTBytes(iStack); - // } - // - // public static ItemStack getItemStack(byte[] bytes) throws ClassNotFoundException { - // validate(); - // return nms.getItemStack(bytes); - // } - private static void rename(final ItemStack iStack) { - final ItemMeta meta = iStack.getItemMeta(); - meta.setDisplayName(ChatColor.RED + "QuickShop " + Util.getName(iStack) + " " + nextId++); - iStack.setItemMeta(meta); + MarkUtil.addMark(iStack); } - - // private static void validate() throws ClassNotFoundException { - // if (nms != null) { - // return; - // } - // String packageName = Bukkit.getServer().getClass().getPackage().getName(); - // packageName = packageName.substring(packageName.lastIndexOf(".") + 1); - // // System.out.println("Package: " + packageName); - // for (NMSDependent dep : dependents) { - // if ((packageName.startsWith(dep.getVersion())) || ((dep.getVersion().isEmpty()) && ((packageName.equals("bukkit")) || (packageName.equals("craftbukkit"))))) { - // nms = dep; - // return; - // } - // } - // throw new ClassNotFoundException("This version of QuickShop is incompatible."); - // } - - // private static abstract class NMSDependent { - // private String version; - // - // public String getVersion() { - // return this.version; - // } - // - // public NMSDependent(String version) { - // this.version = version; - // } - // - // public abstract void safeGuard(Item paramItem); - // - // public abstract byte[] getNBTBytes(org.bukkit.inventory.ItemStack paramItemStack); - // - // public abstract org.bukkit.inventory.ItemStack getItemStack(byte[] paramArrayOfByte); - // } } \ No newline at end of file diff --git a/src/main/java/org/maxgamer/QuickShop/Util/Util.java b/src/main/java/org/maxgamer/QuickShop/Util/Util.java index 67968d6..43f1296 100644 --- a/src/main/java/org/maxgamer/QuickShop/Util/Util.java +++ b/src/main/java/org/maxgamer/QuickShop/Util/Util.java @@ -22,8 +22,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.material.MaterialData; import org.bukkit.material.Sign; -import org.bukkit.potion.Potion; -import org.bukkit.potion.PotionEffect; import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.Config.ItemConfig; @@ -35,10 +33,6 @@ public class Util { private static HashSet transparent = new HashSet(); private static QuickShop plugin; - private static final String[] ROMAN = { "X", "IX", "V", "IV", "I" }; - - private static final int[] DECIMAL = { 10, 9, 5, 4, 1 }; - public static void addTransparentBlock(final Material m) { if (transparent.add(m) == false) { System.out.println("Already added as transparent: " + m.toString()); @@ -579,370 +573,4 @@ public class Util { cfg.set("item", iStack); return cfg.saveToString(); } - - /** - * Converts a given material and data value into a format similar to - * Material..toString(). Upper case, with underscores. Includes material - * name in result. - * - * @param mat - * The base material. - * @param damage - * The durability/damage of the item. - * @return A string with the name of the item. - */ - private static String getDataName(final Material mat, short damage) { - final int id = mat.getId(); - switch (id) { - case 35: - switch (damage) { - case 0: - return "WHITE_WOOL"; - case 1: - return "ORANGE_WOOL"; - case 2: - return "MAGENTA_WOOL"; - case 3: - return "LIGHT_BLUE_WOOL"; - case 4: - return "YELLOW_WOOL"; - case 5: - return "LIME_WOOL"; - case 6: - return "PINK_WOOL"; - case 7: - return "GRAY_WOOL"; - case 8: - return "LIGHT_GRAY_WOOL"; - case 9: - return "CYAN_WOOL"; - case 10: - return "PURPLE_WOOL"; - case 11: - return "BLUE_WOOL"; - case 12: - return "BROWN_WOOL"; - case 13: - return "GREEN_WOOL"; - case 14: - return "RED_WOOL"; - case 15: - return "BLACK_WOOL"; - } - return mat.toString(); - case 351: - switch (damage) { - case 0: - return "INK_SAC"; - case 1: - return "ROSE_RED"; - case 2: - return "CACTUS_GREEN"; - case 3: - return "COCOA_BEANS"; - case 4: - return "LAPIS_LAZULI"; - case 5: - return "PURPLE_DYE"; - case 6: - return "CYAN_DYE"; - case 7: - return "LIGHT_GRAY_DYE"; - case 8: - return "GRAY_DYE"; - case 9: - return "PINK_DYE"; - case 10: - return "LIME_DYE"; - case 11: - return "DANDELION_YELLOW"; - case 12: - return "LIGHT_BLUE_DYE"; - case 13: - return "MAGENTA_DYE"; - case 14: - return "ORANGE_DYE"; - case 15: - return "BONE_MEAL"; - } - return mat.toString(); - case 98: - switch (damage) { - case 0: - return "STONE_BRICKS"; - case 1: - return "MOSSY_STONE_BRICKS"; - case 2: - return "CRACKED_STONE_BRICKS"; - case 3: - return "CHISELED_STONE_BRICKS"; - } - return mat.toString(); - case 373: - // Special case,.. Why? - if (damage == 0) { - return "WATER_BOTTLE"; - } - Potion pot; - try { - pot = Potion.fromDamage(damage); - } catch (final Exception e) { - return "CUSTOM_POTION"; - } - String prefix = ""; - String suffix = ""; - if (pot.getLevel() > 0) { - suffix += "_" + pot.getLevel(); - } - if (pot.hasExtendedDuration()) { - prefix += "EXTENDED_"; - } - if (pot.isSplash()) { - prefix += "SPLASH_"; - } - if (pot.getEffects().isEmpty()) { - switch (pot.getNameId()) { - case 0: - return prefix + "MUNDANE_POTION" + suffix; - case 7: - return prefix + "CLEAR_POTION" + suffix; - case 11: - return prefix + "DIFFUSE_POTION" + suffix; - case 13: - return prefix + "ARTLESS_POTION" + suffix; - case 15: - return prefix + "THIN_POTION" + suffix; - case 16: - return prefix + "AWKWARD_POTION" + suffix; - case 32: - return prefix + "THICK_POTION" + suffix; - } - } else { - String effects = ""; - for (final PotionEffect effect : pot.getEffects()) { - effects += effect.toString().split(":")[0]; - } - return prefix + effects + suffix; - } - return mat.toString(); - case 6: - switch (damage) { - case 0: - return "OAK_SAPLING"; - case 1: - return "PINE_SAPLING"; - case 2: - return "BIRCH_SAPLING"; - case 3: - return "JUNGLE_TREE_SAPLING"; - } - return mat.toString(); - case 5: - switch (damage) { - case 0: - return "OAK_PLANKS"; - case 1: - return "PINE_PLANKS"; - case 2: - return "BIRCH_PLANKS"; - case 3: - return "JUNGLE_PLANKS"; - } - return mat.toString(); - case 17: - switch (damage) { - case 0: - return "OAK_LOG"; - case 1: - return "PINE_LOG"; - case 2: - return "BIRCH_LOG"; - case 3: - return "JUNGLE_LOG"; - } - return mat.toString(); - case 18: - damage = (short) (damage % 4); - switch (damage) { - case 0: - return "OAK_LEAVES"; - case 1: - return "PINE_LEAVES"; - case 2: - return "BIRCH_LEAVES"; - case 3: - return "JUNGLE_LEAVES"; - } - case 263: - switch (damage) { - case 0: - return "COAL"; - case 1: - return "CHARCOAL"; - } - return mat.toString(); - case 24: - switch (damage) { - case 0: - return "SANDSTONE"; - case 1: - return "CHISELED_SANDSTONE"; - case 2: - return "SMOOTH_SANDSTONE"; - } - return mat.toString(); - case 31: - switch (damage) { - case 0: - return "DEAD_SHRUB"; - case 1: - return "TALL_GRASS"; - case 2: - return "FERN"; - } - return mat.toString(); - case 44: - switch (damage) { - case 0: - return "STONE_SLAB"; - case 1: - return "SANDSTONE_SLAB"; - case 2: - return "WOODEN_SLAB"; - case 3: - return "COBBLESTONE_SLAB"; - case 4: - return "BRICK_SLAB"; - case 5: - return "STONE_BRICK_SLAB"; - } - return mat.toString(); - case 383: - switch (damage) { - case 50: - return "CREEPER_EGG"; - case 51: - return "SKELETON_EGG"; - case 52: - return "SPIDER_EGG"; - case 53: - return "GIANT_EGG"; - case 54: - return "ZOMBIE_EGG"; - case 55: - return "SLIME_EGG"; - case 56: - return "GHAST_EGG"; - case 57: - return "ZOMBIE_PIGMAN_EGG"; - case 58: - return "ENDERMAN_EGG"; - case 59: - return "CAVE_SPIDER_EGG"; - case 60: - return "SILVERFISH_EGG"; - case 61: - return "BLAZE_EGG"; - case 62: - return "MAGMA_CUBE_EGG"; - case 63: - return "ENDER_DRAGON_EGG"; - case 90: - return "PIG_EGG"; - case 91: - return "SHEEP_EGG"; - case 92: - return "COW_EGG"; - case 93: - return "CHICKEN_EGG"; - case 94: - return "SQUID_EGG"; - case 95: - return "WOLF_EGG"; - case 96: - return "MOOSHROOM_EGG"; - case 97: - return "SNOW_GOLEM_EGG"; - case 98: - return "OCELOT_EGG"; - case 99: - return "IRON_GOLEM_EGG"; - case 120: - return "VILLAGER_EGG"; - case 200: - return "ENDER_CRYSTAL_EGG"; - case 14: - return "PRIMED_TNT_EGG"; - case 66: - return "WITCH_EGG"; - case 65: - return "BAT_EGG"; - } - return mat.toString(); - case 397: - switch (damage) { - case 0: - return "SKELETON_SKULL"; - case 1: - return "WITHER_SKULL"; - case 2: - return "ZOMBIE_HEAD"; - case 3: - return "PLAYER_HEAD"; - case 4: - return "CREEPER_HEAD"; - } - break; - case 76: - return "REDSTONE_TORCH"; - case 115: - return "NETHER_WART"; - case 30: - return "COBWEB"; - case 102: - return "GLASS_PANE"; - case 101: - return "IRON_BARS"; - case 58: - return "CRAFTING_TABLE"; - case 123: - return "REDSTONE_LAMP"; - case 392: - return "POTATO"; - case 289: - return "GUNPOWDER"; - case 391: - return "CARROT"; - case 322: - switch (damage) { - case 0: - return "GOLDEN_APPLE"; - case 1: - return "ENCHANTED_GOLDEN_APPLE"; - } - break; - case 390: - return "FLOWER_POT"; - case 145: - switch (damage) { - case 0: - return "ANVIL"; - case 1: - return "SLIGHTLY_DAMAGED_ANVIL"; - case 2: - return "VERY_DAMAGED:ANVIL"; - } - break; - case 384: - return "BOTTLE_O'_ENCHANTING"; - case 402: - return "FIREWORK_STAR"; - case 385: - return "FIREWORK_CHARGE"; - } - if (damage == 0 || isTool(mat)) { - return mat.toString(); - } - return mat.toString() + ":" + damage; - } }