diff --git a/src/main/java/com/io/yutian/auchestshop/AuChestShop.java b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java index 826e3a4..0899796 100644 --- a/src/main/java/com/io/yutian/auchestshop/AuChestShop.java +++ b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java @@ -6,14 +6,11 @@ import com.io.yutian.auchestshop.listener.ShopListener; import com.io.yutian.auchestshop.manager.InteractiveManager; import com.io.yutian.auchestshop.manager.ShopManager; import com.io.yutian.aulib.lang.Lang; -import net.milkbowl.vault.Vault; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; -import java.math.BigInteger; - public class AuChestShop extends JavaPlugin { private static AuChestShop instance; @@ -35,9 +32,12 @@ public class AuChestShop extends JavaPlugin { e.printStackTrace(); } + System.out.println(economyProvider); + if (economyProvider != null) { economy = economyProvider.getProvider(); } + System.out.println(economy); sqlIO = new SQLIO(); commandManager = new CommandManager(); diff --git a/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java index 7c1d7f3..be6274b 100644 --- a/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java +++ b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java @@ -8,6 +8,7 @@ import com.io.yutian.auchestshop.util.ShopUtil; import com.io.yutian.aulib.lang.Lang; import com.io.yutian.aulib.listener.IListener; import it.unimi.dsi.fastutil.Pair; +import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -48,9 +49,8 @@ public class ShopListener extends IListener { if (!AuChestShop.getInteractiveManager().containsKey(uuid)) { return; } - AuChestShop.getInteractiveManager().handler(player, event.getMessage()); + Bukkit.getScheduler().runTask(AuChestShop.inst(), () -> AuChestShop.getInteractiveManager().handler(player, event.getMessage())); event.setCancelled(true); - AuChestShop.getInteractiveManager().remove(player.getUniqueId()); } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) diff --git a/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java b/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java index 665d3de..56716a0 100644 --- a/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java +++ b/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java @@ -4,6 +4,7 @@ import com.io.yutian.auchestshop.AuChestShop; import com.io.yutian.auchestshop.shop.Shop; import com.io.yutian.auchestshop.shop.ShopAction; import com.io.yutian.auchestshop.shop.ShopInteractiveInfo; +import com.io.yutian.auchestshop.util.TradeHelper; import com.io.yutian.aulib.lang.Lang; import com.io.yutian.aulib.util.StringUtil; import org.bukkit.entity.Player; @@ -18,11 +19,11 @@ public class InteractiveManager { private final Map actions = new HashMap<>(); public void handler(Player player, String message) { + ShopInteractiveInfo info = actions.remove(player.getUniqueId()); if (message.equalsIgnoreCase("cancel") || message.equalsIgnoreCase("取消")) { player.sendMessage(Lang.get("auchestshop.action.cancel")); return; } - ShopInteractiveInfo info = actions.get(player.getUniqueId()); ShopAction action = info.getAction(); String arg = message.trim(); Shop shop = info.getShop(); @@ -37,7 +38,7 @@ public class InteractiveManager { } double i = Double.parseDouble(arg); if (i <= 0) { - player.sendMessage(Lang.get("auchestshop.action.error-2")); + player.sendMessage(Lang.get("auchestshop.action.error-6")); return; } int length = arg.contains(".") ? arg.length() - arg.indexOf(".") + 1 : 0; @@ -55,7 +56,26 @@ public class InteractiveManager { AuChestShop.getSQLIO().saveShop(shop); player.sendMessage(Lang.get("auchestshop.action.success-create")); } else if (action == ShopAction.PURCHASE) { - + boolean all = arg.equalsIgnoreCase("all"); + int i = 0; + if (all) { + i = -1; + } else { + if (!StringUtil.isInt(arg)) { + player.sendMessage(Lang.get("auchestshop.action.error-1")); + return; + } + i = Integer.parseInt(arg); + if (i <= 0) { + player.sendMessage(Lang.get("auchestshop.action.error-2")); + return; + } + if (i >= Integer.MAX_VALUE) { + player.sendMessage(Lang.get("auchestshop.action.error-4")); + return; + } + } + TradeHelper.trade(player, shop, i); } } diff --git a/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java index 8d6c568..efc481d 100644 --- a/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java +++ b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java @@ -75,7 +75,7 @@ public class ShopManager { } ItemStack item = shop.getItem(); Inventory inventory = shop.getInventory(); - int i = shop.getShopType() == ShopType.BUYING ? ItemStackUtil.countSpace(inventory, item) : ItemStackUtil.countItems(inventory, item); + int i = shop.getShopType() == ShopType.BUYING ? ItemStackUtil.countItems(player.getInventory(), item) : ItemStackUtil.countItems(inventory, item); player.sendMessage(Lang.get("auchestshop.action.message-" + (shop.getShopType() == ShopType.BUYING ? 2 : 3), ItemStackUtil.getItemName(item), i)); ShopInteractiveInfo interactiveInfo = new ShopInteractiveInfo(null, shop.getLocation(), shop, ShopAction.PURCHASE, clickType, System.currentTimeMillis()); AuChestShop.getInteractiveManager().put(player.getUniqueId(), interactiveInfo); @@ -85,7 +85,7 @@ public class ShopManager { } ItemStack item = shop.getItem(); Inventory inventory = shop.getInventory(); - int i = shop.getShopType() == ShopType.BUYING ? ItemStackUtil.countSpace(inventory, item) : ItemStackUtil.countItems(inventory, item); + int i = shop.getShopType() == ShopType.BUYING ? ItemStackUtil.countItems(player.getInventory(), item) : ItemStackUtil.countItems(inventory, item); player.sendMessage(Lang.get("auchestshop.action.message-" + (shop.getShopType() == ShopType.BUYING ? 2 : 3), ItemStackUtil.getItemName(item), i)); ShopInteractiveInfo interactiveInfo = new ShopInteractiveInfo(null, shop.getLocation(), shop, ShopAction.PURCHASE, clickType, System.currentTimeMillis()); AuChestShop.getInteractiveManager().put(player.getUniqueId(), interactiveInfo); diff --git a/src/main/java/com/io/yutian/auchestshop/util/ItemStackUtil.java b/src/main/java/com/io/yutian/auchestshop/util/ItemStackUtil.java index ca7bf9b..c596cb4 100644 --- a/src/main/java/com/io/yutian/auchestshop/util/ItemStackUtil.java +++ b/src/main/java/com/io/yutian/auchestshop/util/ItemStackUtil.java @@ -3,6 +3,7 @@ package com.io.yutian.auchestshop.util; import com.io.yutian.aulib.nbt.NBTCompound; import com.io.yutian.aulib.nbt.NBTItem; import com.io.yutian.aulib.util.LangUtil; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -10,8 +11,28 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + public class ItemStackUtil { + public static List mergeItems(ItemStack item, int amount) { + int maxStackSize = item.getMaxStackSize(); + int totalAmount = amount; + int remainder = totalAmount % maxStackSize; + int quotient = totalAmount / maxStackSize; + List items = new ArrayList<>(); + for (int i = 0; i < quotient; i++) { + ItemStack itemStack = item.clone(); + itemStack.setAmount(maxStackSize); + items.add(itemStack); + } + ItemStack itemStack = item.clone(); + itemStack.setAmount(remainder); + items.add(itemStack); + return items; + } + public static boolean matches(@Nullable ItemStack original, @Nullable ItemStack tester) { if (original == null || tester == null) { return false; @@ -20,7 +41,9 @@ public class ItemStackUtil { original.setAmount(1); tester = tester.clone(); tester.setAmount(1); - if (!original.isSimilar(tester)) { + Material comparisonType = original.getType().isLegacy() ? Bukkit.getUnsafe().fromLegacy(original.getData(), true) : original.getType(); + boolean flag = comparisonType == tester.getType() && original.getDurability() == tester.getDurability() && original.hasItemMeta() == tester.hasItemMeta() && (!original.hasItemMeta() || Bukkit.getItemFactory().equals(original.getItemMeta(), tester.getItemMeta())); + if (!flag) { return false; } NBTItem nbtOriginal = new NBTItem(original); diff --git a/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java index dc2a41e..e5aa33e 100644 --- a/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java +++ b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java @@ -7,6 +7,7 @@ import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -21,6 +22,26 @@ public class ShopUtil { SHOPABLES.add(Material.TRAPPED_CHEST); } + public static void takeShopItemStack(Inventory inventory, ItemStack itemStack, int amount) { + int index = -1; + int a = amount; + while (index < inventory.getSize() && a > 0) { + ++index; + ItemStack i = inventory.getItem(index); + if (i != null && ItemStackUtil.matches(itemStack, i)) { + int k = i.getAmount(); + if (k < a) { + i.setType(Material.AIR); + } else { + int l = k - a; + i.setAmount(l); + } + a -= k; + } + } + + } + public static boolean isShopItem(ItemStack itemStack) { NBTItem nbtItem = new NBTItem(itemStack); if (!nbtItem.has("item_type", NBTString.TYPE_ID)) { diff --git a/src/main/java/com/io/yutian/auchestshop/util/TradeHelper.java b/src/main/java/com/io/yutian/auchestshop/util/TradeHelper.java new file mode 100644 index 0000000..03eb67b --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/util/TradeHelper.java @@ -0,0 +1,71 @@ +package com.io.yutian.auchestshop.util; + +import com.io.yutian.auchestshop.AuChestShop; +import com.io.yutian.auchestshop.shop.Shop; +import com.io.yutian.auchestshop.shop.ShopType; +import com.io.yutian.aulib.lang.Lang; +import com.io.yutian.aulib.util.PlayerInventoryUtil; +import net.milkbowl.vault.economy.EconomyResponse; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class TradeHelper { + + public static void trade(Player player, Shop shop, int amount) { + ShopType shopType = shop.getShopType(); + Inventory shopInventory = shop.getInventory(); + if (shopType == ShopType.SELLING) { + ItemStack itemStack = shop.getItem(); + int freeSize = PlayerInventoryUtil.getFreeSize(player); + if (freeSize < amount) { + player.sendMessage(Lang.get("auchestshop.action.error-9", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + int allAmount = ItemStackUtil.countItems(shopInventory, itemStack); + if (allAmount < amount) { + player.sendMessage(Lang.get("auchestshop.action.error-11", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + double allPrice = shop.getPrice() * amount; + EconomyResponse economyResponse = AuChestShop.getEconomy().withdrawPlayer(player, allPrice); + if (!economyResponse.transactionSuccess()) { + player.sendMessage(Lang.get("auchestshop.action.error-7", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + List itemStacks = ItemStackUtil.mergeItems(itemStack, amount); + ShopUtil.takeShopItemStack(shopInventory, itemStack, amount); + for (ItemStack item : itemStacks) { + PlayerInventoryUtil.giveItemStack(player, item); + } + player.sendMessage(Lang.get("auchestshop.action.message-5", amount, ItemStackUtil.getItemName(itemStack))); + } else if (shopType == ShopType.BUYING) { + ItemStack itemStack = shop.getItem(); + int freeSize = ItemStackUtil.countSpace(shopInventory, itemStack); + if (freeSize < amount) { + player.sendMessage(Lang.get("auchestshop.action.error-10", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + int allAmount = ItemStackUtil.countItems(player.getInventory(), itemStack); + if (allAmount < amount) { + player.sendMessage(Lang.get("auchestshop.action.error-12", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + double allPrice = shop.getPrice() * amount; + EconomyResponse economyResponse = AuChestShop.getEconomy().depositPlayer(player, allPrice); + if (!economyResponse.transactionSuccess()) { + player.sendMessage(Lang.get("auchestshop.action.error-7", amount, ItemStackUtil.getItemName(itemStack))); + return; + } + PlayerInventoryUtil.takeItemStack(player, (itemStack1 -> ItemStackUtil.matches(itemStack1, itemStack)), amount); + List itemStacks = ItemStackUtil.mergeItems(itemStack, amount); + for (ItemStack item : itemStacks) { + shopInventory.addItem(item); + } + player.sendMessage(Lang.get("auchestshop.action.message-4", amount, ItemStackUtil.getItemName(itemStack))); + } + } + +} diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml index 4761aff..7077538 100644 --- a/src/main/resources/lang.yml +++ b/src/main/resources/lang.yml @@ -1,17 +1,26 @@ auchestshop: create-shop: - up-has-block: "§c创建失败,商店上方存在非法方块" - success: "§a成功创建商店" - error-1: "§c商店创建已取消" - remove-shop: "§a成功移除商店" + up-has-block: "&c创建失败,商店上方存在非法方块" + success: "&a成功创建商店" + error-1: "&c商店创建已取消" + remove-shop: "&a成功移除商店" action: - cancel: "§a操作已取消" - message-1: "§a请在聊天中输入交易1个§e$0§a所需的价格。" - message-2: "§a聊天栏中输入想出售§e$0§a的物品数量,您现在可以卖出§e$1§a件物品。输入§ball§a来出售全部物品" - message-3: "§a聊天栏中输入想购买§e$0§a的物品数量,您可以购买§e$1§a件物品。输入§ball§a来购买全部物品" - error-1: "§c请输入有效的数字" - error-2: "§c请输入大于0的整数" - error-3: "§c您的价格中的小数点后位数超过上限" - error-4: "§c该值超过了最大值" - error-5: "§c请输入一个有效的价格" - success-create: "§a成功设置商店物品" \ No newline at end of file + cancel: "&a操作已取消" + message-1: "&a请在聊天中输入交易1个&e$0&a所需的价格。" + message-2: "&a聊天栏中输入想出售&e$0&a的物品数量,您现在可以卖出&e$1&a件物品。输入&ball&a来出售全部物品" + message-3: "&a聊天栏中输入想购买&e$0&a的物品数量,您可以购买&e$1&a件物品。输入&ball&a来购买全部物品" + message-4: "&a成功出售&e$0&a个&e$1" + message-5: "&a成功购买&e$0&a个&e$1" + error-1: "&c请输入有效的数字" + error-2: "&c请输入大于0的整数" + error-3: "&c您的价格中的小数点后位数超过上限" + error-4: "&c该值超过了最大值" + error-5: "&c请输入一个有效的价格" + error-6: "&c请输入大于0的数" + error-7: "&c您没有足够的钱购买&e$0&a个&e$1" + error-8: "&c该商店的店主没有足够的钱收购&e$0&a个&e$1" + error-9: "&c您没有足够的空间购买&e$0&a个&e$1" + error-10: "&c该商店没有足够的空间收购&e$0&a个&e$1" + error-11: "&c该商店没有足够的库存出售&e$0&a个&e$1" + error-12: "&c你没有足够的物品出售&e$0&a个&e$1" + success-create: "&a成功设置商店物品" \ No newline at end of file