diff --git a/src/main/java/org/maxgamer/QuickShop/Command/QS.java b/src/main/java/org/maxgamer/QuickShop/Command/QS.java index 355f656..3187040 100644 --- a/src/main/java/org/maxgamer/QuickShop/Command/QS.java +++ b/src/main/java/org/maxgamer/QuickShop/Command/QS.java @@ -574,7 +574,7 @@ public class QS implements CommandExecutor { if (shop != null) { shop.setUnlimited(!shop.isUnlimited()); shop.update(); - sender.sendMessage(MsgUtil.p("command.toggle-unlimited", (shop.isUnlimited() ? "unlimited" : "limited"))); + sender.sendMessage(MsgUtil.p("command.toggle-unlimited", (shop.isUnlimited() ? "无限模式" : "有限模式"))); return; } } diff --git a/src/main/java/org/maxgamer/QuickShop/Config/ConfigManager.java b/src/main/java/org/maxgamer/QuickShop/Config/ConfigManager.java index f10824e..0d832a5 100644 --- a/src/main/java/org/maxgamer/QuickShop/Config/ConfigManager.java +++ b/src/main/java/org/maxgamer/QuickShop/Config/ConfigManager.java @@ -10,36 +10,39 @@ import org.maxgamer.QuickShop.QuickShop; public class ConfigManager { /** Whether debug info should be shown in the console */ protected boolean debug = false; + /** Whether we should use display items or not */ + protected boolean display = true; + protected double feeForPriceChange = 0.0; + protected int findDistance = 30; + /** Whether or not to limit players shop amounts */ + protected boolean limit = false; + protected int limitdefault = 0; + protected final HashMap limits = new HashMap(); + protected boolean logAction = true; + protected boolean preventhopper = false; /** - * A set of players who have been warned - * ("Your shop isn't automatically locked") + * Whether we players are charged a fee to change the price on their shop + * (To help deter endless undercutting */ - protected HashSet warnings = new HashSet(); + protected boolean priceChangeRequiresFee = false; + protected boolean shopLock = true; + protected boolean showTax; /** Whether players are required to sneak to create/buy from a shop */ protected boolean sneak; /** Whether players are required to sneak to create a shop */ protected boolean sneakCreate; /** Whether players are required to sneak to trade with a shop */ protected boolean sneakTrade; - /** Whether we should use display items or not */ - protected boolean display = true; - /** - * Whether we players are charged a fee to change the price on their shop - * (To help deter endless undercutting - */ - protected boolean priceChangeRequiresFee = false; - /** Whether or not to limit players shop amounts */ - protected boolean limit = false; - protected int limitdefault = 0; - protected final HashMap limits = new HashMap(); - protected boolean logAction = true; - protected boolean shopLock = true; - protected int findDistance = 30; protected Material superItem = Material.GOLD_AXE; - protected double feeForPriceChange = 0.0; - protected boolean preventhopper = false; + protected double tax = 0; + protected String taxAccount; /** Use SpoutPlugin to get item / block names */ protected boolean useSpout = false; + /** + * A set of players who have been warned + * ("Your shop isn't automatically locked") + */ + protected HashSet warnings = new HashSet(); public ConfigManager(final QuickShop plugin) { @@ -56,6 +59,9 @@ public class ConfigManager { this.superItem = Enum.valueOf(Material.class, plugin.getConfig().getString("superitem")); } catch (final Exception e) { } + this.tax = plugin.getConfig().getDouble("tax"); + this.showTax = plugin.getConfig().getBoolean("show-tax"); + this.taxAccount = plugin.getConfig().getString("tax-account"); this.logAction = plugin.getConfig().getBoolean("log-actions"); this.shopLock = plugin.getConfig().getBoolean("shop.lock"); this.display = plugin.getConfig().getBoolean("shop.display-items"); @@ -88,6 +94,14 @@ public class ConfigManager { return superItem; } + public double getTax() { + return tax; + } + + public String getTaxAccount() { + return taxAccount; + } + public HashSet getWarnings() { return warnings; } @@ -120,6 +134,10 @@ public class ConfigManager { return shopLock; } + public boolean isShowTax() { + return showTax; + } + public boolean isSneak() { return sneak; } diff --git a/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java b/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java index 0084865..00b18c4 100644 --- a/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java +++ b/src/main/java/org/maxgamer/QuickShop/Listeners/PlayerListener.java @@ -159,6 +159,27 @@ public class PlayerListener implements Listener { plugin.getShopManager().getActions().remove(e.getPlayer().getName()); } + @EventHandler(priority = EventPriority.MONITOR) + public void onSuperItemClick(final PlayerInteractEvent e) { + if (e.getAction() == Action.LEFT_CLICK_BLOCK || e.getMaterial() != plugin.getConfigManager().getSuperItem()) { + return; + } + final Player p = e.getPlayer(); + final Block b = e.getClickedBlock(); + // If that wasn't a shop, search nearby shops + if (b.getType() == Material.WALL_SIGN) { + final Block attached = Util.getAttached(b); + final Shop shop = attached == null ? null : plugin.getShopManager().getShop(attached.getLocation()); + if (shop != null) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && p.hasPermission("quickshop.unlimited")) { + shop.setUnlimited(!shop.isUnlimited()); + shop.update(); + p.sendMessage(MsgUtil.p("command.toggle-unlimited", (shop.isUnlimited() ? "无限模式" : "有限模式"))); + } + } + } + } + @EventHandler public void onTeleport(final PlayerTeleportEvent e) { final PlayerMoveEvent me = new PlayerMoveEvent(e.getPlayer(), e.getFrom(), e.getTo()); diff --git a/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java b/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java index 3e9ad58..2f944b8 100644 --- a/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java +++ b/src/main/java/org/maxgamer/QuickShop/Shop/ShopManager.java @@ -25,73 +25,9 @@ import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.Util; public class ShopManager { - public class ShopIterator implements Iterator { - private Iterator shops; - private Iterator> chunks; - private final Iterator>> worlds; - private Shop current; - - public ShopIterator() { - worlds = getShops().values().iterator(); - } - - /** - * Returns true if there is still more shops to iterate over. - */ - @Override - public boolean hasNext() { - if (shops == null || !shops.hasNext()) { - if (chunks == null || !chunks.hasNext()) { - if (!worlds.hasNext()) { - return false; - } else { - chunks = worlds.next().values().iterator(); - return hasNext(); - } - } else { - shops = chunks.next().values().iterator(); - return hasNext(); - } - } - return true; - } - - /** - * Fetches the next shop. Throws NoSuchElementException if there are no - * more shops. - */ - @Override - public Shop next() { - if (shops == null || !shops.hasNext()) { - if (chunks == null || !chunks.hasNext()) { - if (!worlds.hasNext()) { - throw new NoSuchElementException("No more shops to iterate over!"); - } - chunks = worlds.next().values().iterator(); - } - shops = chunks.next().values().iterator(); - } - if (!shops.hasNext()) { - return this.next(); // Skip to the next one (Empty iterator?) - } - current = shops.next(); - return current; - } - - /** - * Removes the current shop. This method will delete the shop from - * memory and the database. - */ - @Override - public void remove() { - current.delete(false); - shops.remove(); - } - } - - private final QuickShop plugin; private final HashMap actions = new HashMap(); + private final QuickShop plugin; private final HashMap>> shops = new HashMap>>(); public ShopManager(final QuickShop plugin) { @@ -439,7 +375,7 @@ public class ShopManager { // 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 tax = plugin.getConfigManager().getTax(); final double total = amount * shop.getPrice(); if (!plugin.getEcon().withdraw(p.getName(), total)) { p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName())))); @@ -448,11 +384,11 @@ public class ShopManager { 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); + plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax); } } // Notify the shop owner - if (plugin.getConfig().getBoolean("show-tax")) { + if (plugin.getConfigManager().isShowTax()) { 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(), @@ -471,7 +407,7 @@ public class ShopManager { // 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()); + plugin.log(String.format("%s 从 %s 购买了 %s 件商品 花费 %s", p.getName(), shop.toString(), amount, shop.getPrice() * amount)); } else if (shop.isBuying()) { final int space = shop.getRemainingSpace(); if (space < amount) { @@ -498,7 +434,7 @@ public class ShopManager { // 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 tax = plugin.getConfigManager().getTax(); 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 @@ -513,7 +449,7 @@ public class ShopManager { return; } if (tax != 0) { - plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), total * tax); + plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax); } } // Give them the money after we know we succeeded @@ -527,7 +463,7 @@ public class ShopManager { } shop.buy(p, amount); MsgUtil.sendSellSuccess(p, shop, amount); - plugin.log(p.getName() + " sold " + amount + " for " + (shop.getPrice() * amount) + " to " + shop.toString()); + plugin.log(String.format("%s 出售了 %s 件商品 到 %s 获得 %s", p.getName(), amount, shop.toString(), shop.getPrice() * amount)); } shop.setSignText(); // Update the signs count } @@ -603,4 +539,68 @@ public class ShopManager { // Put the shop in its location in the chunk list. inChunk.put(shop.getLocation(), shop); } + + public class ShopIterator implements Iterator { + private Iterator> chunks; + private Shop current; + private Iterator shops; + private final Iterator>> worlds; + + public ShopIterator() { + worlds = getShops().values().iterator(); + } + + /** + * Returns true if there is still more shops to iterate over. + */ + @Override + public boolean hasNext() { + if (shops == null || !shops.hasNext()) { + if (chunks == null || !chunks.hasNext()) { + if (!worlds.hasNext()) { + return false; + } else { + chunks = worlds.next().values().iterator(); + return hasNext(); + } + } else { + shops = chunks.next().values().iterator(); + return hasNext(); + } + } + return true; + } + + /** + * Fetches the next shop. Throws NoSuchElementException if there are no + * more shops. + */ + @Override + public Shop next() { + if (shops == null || !shops.hasNext()) { + if (chunks == null || !chunks.hasNext()) { + if (!worlds.hasNext()) { + throw new NoSuchElementException("No more shops to iterate over!"); + } + chunks = worlds.next().values().iterator(); + } + shops = chunks.next().values().iterator(); + } + if (!shops.hasNext()) { + return this.next(); // Skip to the next one (Empty iterator?) + } + current = shops.next(); + return current; + } + + /** + * Removes the current shop. This method will delete the shop from + * memory and the database. + */ + @Override + public void remove() { + current.delete(false); + shops.remove(); + } + } } \ 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 3b410b3..129974a 100644 --- a/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java +++ b/src/main/java/org/maxgamer/QuickShop/Util/MsgUtil.java @@ -39,7 +39,7 @@ public class MsgUtil { * The player to message * @return true if success, false if the player is offline or null */ - public static boolean flush(final OfflinePlayer p) { // TODO Changed to UUID + public static boolean flush(final OfflinePlayer p) { if (p != null && p.isOnline()) { final String pName = p.getName(); final LinkedList msgs = player_messages.get(pName); @@ -47,7 +47,7 @@ public class MsgUtil { for (final String msg : msgs) { p.getPlayer().sendMessage(msg); } - plugin.getDB().execute("DELETE FROM messages WHERE owner = ?", pName.toString()); + plugin.getDB().execute("DELETE FROM messages WHERE owner = ?", pName); msgs.clear(); } return true; @@ -66,7 +66,7 @@ public class MsgUtil { /** * loads all player purchase messages from the database. */ - public static void loadTransactionMessages() { // TODO Converted to UUID + public static void loadTransactionMessages() { player_messages.clear(); // Delete old messages try { final ResultSet rs = plugin.getDB().getConnection().prepareStatement("SELECT * FROM messages").executeQuery(); @@ -82,14 +82,14 @@ public class MsgUtil { } } catch (final SQLException e) { e.printStackTrace(); - System.out.println("Could not load transaction messages from database. Skipping."); + System.out.println("无法从数据库获得玩家的交易记录 跳过..."); } } public static String p(final String loc, final String... args) { String raw = messages.getString(loc); if (raw == null || raw.isEmpty()) { - return "Invalid message: " + loc; + return "语言文件词条丢失: " + loc; } if (args == null) { return raw; @@ -108,7 +108,7 @@ public class MsgUtil { * they're online. Else, if they're not online, queues it for * them in the database. */ - public static void send(final String player, final String message) { // TODO Converted to UUID + public static void send(final String player, final String message) { @SuppressWarnings("deprecation") final OfflinePlayer p = Bukkit.getOfflinePlayer(player); if (p == null || !p.isOnline()) { diff --git a/src/main/java/org/maxgamer/QuickShop/Util/Util.java b/src/main/java/org/maxgamer/QuickShop/Util/Util.java index b7ee41a..561c10f 100644 --- a/src/main/java/org/maxgamer/QuickShop/Util/Util.java +++ b/src/main/java/org/maxgamer/QuickShop/Util/Util.java @@ -227,7 +227,7 @@ public class Util { public static String getToolPercentage(final ItemStack item) { final double dura = item.getDurability(); final double max = item.getType().getMaxDurability(); - return String.format("%.2f(%s/%s)", (1 - dura / max) * 100.0, dura, max); + return String.format("%.2f%%(剩余耐久%s/总耐久%s)", (1 - dura / max) * 100.0, max - dura, max); } public static void initialize() { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1cced9e..9c0d68f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,11 +2,11 @@ Version: 1.1 #超级工具(OP可以用该工具在创造模式打破所有商店) superitem: GOLD_AXE -#阻止漏洞吸取商店物品(非特殊情况不要开启) +#阻止漏斗吸取商店物品(非特殊情况不要开启) preventhopper: false #Tax amount (decimal) - Eg, P1 buys $50 worth of stuff from P2. Therefore, P1 loses $50, P2 gains $(1-0.05)*50, and tax-account gains $(0.05)*50. -tax: 0.05 +tax: 0.00 #The fake player who money from taxing people goes to tax-account: tax #Whether or not to show taxes paid when selling to a shop @@ -53,23 +53,23 @@ shop-blocks: - TRAPPED_CHEST shop: - #Cost to make a stall - cost: 10 - #Should we refund when their shops are deleted/removed/broken? + #创建商店需花费 + cost: 0 + #是否需要再次扣费 当玩家 删除/移除/破坏 商店的时候? refund: false - #Is there a fee for changing prices on a shop (Help deter endless undercutting) - price-change-requires-fee: true - #If price changes require a fee, how much is the fee - fee-for-price-change: 50 + #是否需要在玩家修改商店价格的时候扣费 + price-change-requires-fee: false + #玩家修改商店价格时的扣费金额 + fee-for-price-change: 0 - #Should we try and lock their shops from other players, so people can't steal from them? + #是否需要锁定箱子防止其他玩家破坏 lock: true - #Should we require players be sneaking to create and use shops? + #是否需要玩家按住Shift才可以创建或交易? sneak-to-create: false sneak-to-trade: false - #Should we automatically create the sign for the chest? + #是否需要自动创建木牌在箱子上? auto-sign: true #If a player owns an unlimited shop, should they receive the cash from it or not? #If you buy from YOUR unlimited shop, you will NEVER be charged $$, regardless of this setting diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index e9c3300..6c71b08 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -1,7 +1,7 @@ # Colors: # &0-9, &a-f # {0}, {1}, {2}, etc are variables. You can swap them around, but adding a new variable won't work. Removing them will work -Version: 1.0 +Version: 1.1 not-looking-at-shop: "&c没找到快捷商店. 你必须看着那个箱子." no-permission: "&4你没有此命令的权限." @@ -9,7 +9,7 @@ no-creative-break: "&c你不能在创造模式中打破其他玩家的商店,请 no-double-chests: "&c你没有权限创建一个大箱子商店,请使用一个箱子." shop-already-owned: "&c这已经是一个箱子了." chest-was-removed: "&c商店已被移除." -price-too-cheap: "&c商品价格不能低于 &e¥0.01" +price-too-cheap: "&c商品价格不能低于 &e{0}" no-price-change: "&c商店价格未改变!" you-cant-afford-a-new-shop: "&c创建一个新的商店需要花费 {0} 你没有足够的钱!." you-cant-afford-to-change-price: "&c改变商店的价格需要花费 {0} 你没有足够的钱!." @@ -44,7 +44,7 @@ empty-success: "&a库存清理成功" menu: successful-purchase: "&a商品购买成功:" successfully-sold: "&a商品出售成功:" - item-name-and-price: "&a花费:&e{2} &a获得 &e{0} &a件 &e{1}&b(查看详情) &a商品" + item-name-and-price: "&d交易成功 &e{0} &a件 &e{1}&b(查看详情) &a商品 &b金额 &e{2}" shop-information: "&a商店信息:" owner: "&a所有者: {0}" @@ -53,12 +53,12 @@ menu: stock: "&a库存: &e{0}" price-per: "&a单价: &e{1}元" total-value-of-chest: "&a所有存货总价格: &c{0}元" - damage-percent-remaining: "&a耐久剩余: &e{0}% ." + damage-percent-remaining: "&a耐久剩余: &e{0}." this-shop-is-buying: "&a此商店只 &d购买&a 物品." this-shop-is-selling: "&a此商店只 &b出售&a 商品." bypassing-lock: "&c无视快捷商店锁!" -that-is-locked: "&c此商店已上锁." +that-is-locked: "&c此快捷商店已上锁." how-many-buy: "&a请输入 &b购买商品数量&a 在聊天栏." how-many-sell: "&a请输入 &d出售商品数量&a 在聊天栏. 你目前有 &e{0}&a 件物品"