From 4b51f61073133a26543901ebf60a785c3d74b8f8 Mon Sep 17 00:00:00 2001 From: Levi McGlone Date: Wed, 25 Sep 2019 13:38:18 -0400 Subject: [PATCH 1/5] add basics for buy command --- .../essentials/commands/Commandbuy.java | 86 +++++++++++++++++++ Essentials/src/config.yml | 1 + Essentials/src/plugin.yml | 3 + 3 files changed, 90 insertions(+) create mode 100644 Essentials/src/com/earth2me/essentials/commands/Commandbuy.java diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java new file mode 100644 index 00000000000..3dc9f0ab713 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java @@ -0,0 +1,86 @@ +package com.earth2me.essentials.commands; + +import com.earth2me.essentials.Trade; +import com.earth2me.essentials.User; +import com.earth2me.essentials.craftbukkit.InventoryWorkaround; +import com.earth2me.essentials.utils.NumberUtil; +import com.google.common.collect.Lists; + +import org.apache.commons.lang.math.NumberUtils; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.inventory.ItemStack; + +import static com.earth2me.essentials.I18n.tl; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; + +public class Commandbuy extends EssentialsCommand { + public Commandbuy() { + super("buy"); + } + + @Override + public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { + if (args.length < 2 || !NumberUtil.isInt(args[1])) { + throw new NotEnoughArgumentsException(); + } + + int amountToGive = NumberUtils.toInt(args[1]); + + if (amountToGive <= 0) { + throw new Exception("You cannot buy 0 items."); + } + + ItemStack is = ess.getItemDb().get(args[0]); + is.setAmount(amountToGive); + BigDecimal worthSingleItem = ess.getWorth().getPrice(ess, is); + BigDecimal worth = worthSingleItem.multiply(BigDecimal.valueOf(amountToGive)); + + if (worth.compareTo(user.getMoney()) == -1) { + boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull(); + BigDecimal leftoverValue = BigDecimal.ZERO; + Map leftovers; + + if (user.isAuthorized("essentials.oversizedstacks")) { + leftovers = InventoryWorkaround.addOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), is); + } else { + leftovers = InventoryWorkaround.addItems(user.getBase().getInventory(), is); + } + + if (isDropItemsIfFull) { + for (ItemStack item : leftovers.values()) { + World w = user.getWorld(); + w.dropItemNaturally(user.getLocation(), item); + } + } else { + for (ItemStack item : leftovers.values()) { + leftoverValue.add(worthSingleItem.multiply(BigDecimal.valueOf(item.getAmount()))); + + user.sendMessage("Not enough inventory space. Refunding $."); + } + } + + user.takeMoney(worth.subtract(leftoverValue)); + user.getBase().updateInventory(); + } else { + throw new Exception("You do not have enough money."); + } + } + + @Override + protected List getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) { + if (args.length == 1) { + return getItems(); + } else if (args.length == 2) { + return Lists.newArrayList("1", "64"); + } else { + return Collections.emptyList(); + } + } +} diff --git a/Essentials/src/config.yml b/Essentials/src/config.yml index 094e93b7383..4ddfd72bfb0 100644 --- a/Essentials/src/config.yml +++ b/Essentials/src/config.yml @@ -215,6 +215,7 @@ player-commands: - balance.others - balancetop - build + - buy - chat.color - chat.format - chat.shout diff --git a/Essentials/src/plugin.yml b/Essentials/src/plugin.yml index 26add785aef..496ec478dba 100644 --- a/Essentials/src/plugin.yml +++ b/Essentials/src/plugin.yml @@ -65,6 +65,9 @@ commands: description: Set a player on fire. usage: / aliases: [eburn] + buy: + description: Buy the specified item. + usage: / <|> [-][amount] clearinventory: description: Clear all items in your inventory. usage: / [player|*] [item[:]|*|**] [amount] From 74949009cdf6ea0558a3bd0d2fe60bd909df717b Mon Sep 17 00:00:00 2001 From: Levi McGlone Date: Mon, 30 Sep 2019 12:29:29 -0400 Subject: [PATCH 2/5] fix bug with full inventory and check null worth --- .../com/earth2me/essentials/commands/Commandbuy.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java index 3dc9f0ab713..2b5ad8e1859 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java @@ -42,6 +42,10 @@ public void run(final Server server, final User user, final String commandLabel, BigDecimal worthSingleItem = ess.getWorth().getPrice(ess, is); BigDecimal worth = worthSingleItem.multiply(BigDecimal.valueOf(amountToGive)); + if (worth == null) { + throw new Exception(tl("itemCannotBeSold")); + } + if (worth.compareTo(user.getMoney()) == -1) { boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull(); BigDecimal leftoverValue = BigDecimal.ZERO; @@ -60,10 +64,10 @@ public void run(final Server server, final User user, final String commandLabel, } } else { for (ItemStack item : leftovers.values()) { - leftoverValue.add(worthSingleItem.multiply(BigDecimal.valueOf(item.getAmount()))); - - user.sendMessage("Not enough inventory space. Refunding $."); + leftoverValue = leftoverValue.add(worthSingleItem.multiply(BigDecimal.valueOf(item.getAmount()))); } + + user.sendMessage("Not enough inventory space. Refunding $."); } user.takeMoney(worth.subtract(leftoverValue)); From 3d15488aebe050b1727ad2ea8304f09614134c77 Mon Sep 17 00:00:00 2001 From: Levi McGlone Date: Mon, 30 Sep 2019 13:02:11 -0400 Subject: [PATCH 3/5] support reading alternate buy and sell config values --- .../src/com/earth2me/essentials/Worth.java | 80 +++++++++++++++++++ .../essentials/commands/Commandbuy.java | 4 +- .../essentials/commands/Commandsell.java | 2 +- Essentials/src/worth.yml | 7 ++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/Worth.java b/Essentials/src/com/earth2me/essentials/Worth.java index 804797dd393..8835095a77a 100644 --- a/Essentials/src/com/earth2me/essentials/Worth.java +++ b/Essentials/src/com/earth2me/essentials/Worth.java @@ -62,6 +62,86 @@ public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) { return result; } + /** + * Get the value of an item stack from the config for buying. + * + * @param ess The Essentials instance. + * @param itemStack The item stack to look up in the config. + * @return The price from the config. + */ + public BigDecimal getBuyPrice(IEssentials ess, ItemStack itemStack) { + BigDecimal result; + + String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""); + + // Check for matches with data value from stack + // Note that we always default to BigDecimal.ONE.negate(), equivalent to -1 + result = config.getBigDecimal("buy." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate()); + + // Check for matches with data value 0 + if (result.signum() < 0) { + final ConfigurationSection itemNameMatch = config.getConfigurationSection("buy." + itemname); + if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) { + result = config.getBigDecimal("buy." + itemname + ".0", BigDecimal.ONE.negate()); + } + } + + // Check for matches with data value wildcard + if (result.signum() < 0) { + result = config.getBigDecimal("buy." + itemname + ".*", BigDecimal.ONE.negate()); + } + + // Check for matches with item name alone + if (result.signum() < 0) { + result = config.getBigDecimal("buy." + itemname, BigDecimal.ONE.negate()); + } + + if (result.signum() < 0) { + return getPrice(ess, itemStack); + } + return result; + } + + /** + * Get the value of an item stack from the config for selling. + * + * @param ess The Essentials instance. + * @param itemStack The item stack to look up in the config. + * @return The price from the config. + */ + public BigDecimal getSellPrice(IEssentials ess, ItemStack itemStack) { + BigDecimal result; + + String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""); + + // Check for matches with data value from stack + // Note that we always default to BigDecimal.ONE.negate(), equivalent to -1 + result = config.getBigDecimal("sell." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate()); + + // Check for matches with data value 0 + if (result.signum() < 0) { + final ConfigurationSection itemNameMatch = config.getConfigurationSection("sell." + itemname); + if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) { + result = config.getBigDecimal("sell." + itemname + ".0", BigDecimal.ONE.negate()); + } + } + + // Check for matches with data value wildcard + if (result.signum() < 0) { + result = config.getBigDecimal("sell." + itemname + ".*", BigDecimal.ONE.negate()); + } + + // Check for matches with item name alone + if (result.signum() < 0) { + result = config.getBigDecimal("sell." + itemname, BigDecimal.ONE.negate()); + } + + if (result.signum() < 0) { + return getPrice(ess, itemStack); + } + return result; + } + /** * Get the amount of items to be sold from a player's inventory. * diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java index 2b5ad8e1859..ec2d707ac6e 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java @@ -39,7 +39,7 @@ public void run(final Server server, final User user, final String commandLabel, ItemStack is = ess.getItemDb().get(args[0]); is.setAmount(amountToGive); - BigDecimal worthSingleItem = ess.getWorth().getPrice(ess, is); + BigDecimal worthSingleItem = ess.getWorth().getBuyPrice(ess, is); BigDecimal worth = worthSingleItem.multiply(BigDecimal.valueOf(amountToGive)); if (worth == null) { @@ -62,7 +62,7 @@ public void run(final Server server, final User user, final String commandLabel, World w = user.getWorld(); w.dropItemNaturally(user.getLocation(), item); } - } else { + } else if(!leftovers.values().isEmpty()) { for (ItemStack item : leftovers.values()) { leftoverValue = leftoverValue.add(worthSingleItem.multiply(BigDecimal.valueOf(item.getAmount()))); } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandsell.java b/Essentials/src/com/earth2me/essentials/commands/Commandsell.java index e6c41a98b4f..2f70dfea43a 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandsell.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandsell.java @@ -69,7 +69,7 @@ public void run(final Server server, final User user, final String commandLabel, private BigDecimal sellItem(User user, ItemStack is, String[] args, boolean isBulkSell) throws Exception { int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkSell); - BigDecimal worth = ess.getWorth().getPrice(ess, is); + BigDecimal worth = ess.getWorth().getSellPrice(ess, is); if (worth == null) { throw new Exception(tl("itemCannotBeSold")); diff --git a/Essentials/src/worth.yml b/Essentials/src/worth.yml index 7d273e45dac..02a14823839 100644 --- a/Essentials/src/worth.yml +++ b/Essentials/src/worth.yml @@ -184,3 +184,10 @@ worth: ironboots: 22.0 step: 1.5 sugar: 10.0 + +# Override prices from the section above for buying and selling specifically. +buy: + diamond: 2000 + +sell: + diamond: 20 From bd8a6f516204d142f65db1595b82fe2aa5f95607 Mon Sep 17 00:00:00 2001 From: Levi McGlone Date: Thu, 3 Oct 2019 11:16:53 -0400 Subject: [PATCH 4/5] refactor Worth.java changes --- .../src/com/earth2me/essentials/Worth.java | 89 ++++++------------- .../essentials/commands/Commandworth.java | 2 +- 2 files changed, 28 insertions(+), 63 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/Worth.java b/Essentials/src/com/earth2me/essentials/Worth.java index 8835095a77a..bddef39a35f 100644 --- a/Essentials/src/com/earth2me/essentials/Worth.java +++ b/Essentials/src/com/earth2me/essentials/Worth.java @@ -27,33 +27,33 @@ public Worth(File dataFolder) { * * @param ess The Essentials instance. * @param itemStack The item stack to look up in the config. + * @param key The key to look under in the config * @return The price from the config. */ - public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) { - BigDecimal result; - + public BigDecimal getPrice(IEssentials ess, ItemStack itemStack, String key) { + BigDecimal negativeOne = BigDecimal.ONE.negate(); String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""); // Check for matches with data value from stack // Note that we always default to BigDecimal.ONE.negate(), equivalent to -1 - result = config.getBigDecimal("worth." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate()); + BigDecimal result = config.getBigDecimal(key + "." + itemname + "." + itemStack.getDurability(), negativeOne); // Check for matches with data value 0 if (result.signum() < 0) { - final ConfigurationSection itemNameMatch = config.getConfigurationSection("worth." + itemname); + final ConfigurationSection itemNameMatch = config.getConfigurationSection(key + "." + itemname); if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) { - result = config.getBigDecimal("worth." + itemname + ".0", BigDecimal.ONE.negate()); + result = config.getBigDecimal(key + "." + itemname + ".0", negativeOne); } } // Check for matches with data value wildcard if (result.signum() < 0) { - result = config.getBigDecimal("worth." + itemname + ".*", BigDecimal.ONE.negate()); + result = config.getBigDecimal(key + "." + itemname + ".*", negativeOne); } // Check for matches with item name alone if (result.signum() < 0) { - result = config.getBigDecimal("worth." + itemname, BigDecimal.ONE.negate()); + result = config.getBigDecimal(key + "." + itemname, negativeOne); } if (result.signum() < 0) { @@ -63,81 +63,46 @@ public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) { } /** - * Get the value of an item stack from the config for buying. + * Get the value of an item stack from the worth array in worth.yml. + * + * @param ess The Essentials instance. + * @param itemStack The item stack to look up in the config. + * @return The price from the config. + */ + public BigDecimal getWorthPrice(IEssentials ess, ItemStack itemStack) { + return getPrice(ess, itemStack, "worth"); + } + + /** + * Get the value of an item stack from the buy array in worth.yml. + * Falls back to worth section if the item is not found in the buy section. * * @param ess The Essentials instance. * @param itemStack The item stack to look up in the config. * @return The price from the config. */ public BigDecimal getBuyPrice(IEssentials ess, ItemStack itemStack) { - BigDecimal result; - - String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""); - - // Check for matches with data value from stack - // Note that we always default to BigDecimal.ONE.negate(), equivalent to -1 - result = config.getBigDecimal("buy." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate()); - - // Check for matches with data value 0 - if (result.signum() < 0) { - final ConfigurationSection itemNameMatch = config.getConfigurationSection("buy." + itemname); - if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) { - result = config.getBigDecimal("buy." + itemname + ".0", BigDecimal.ONE.negate()); - } - } + BigDecimal result = getPrice(ess, itemStack, "buy"); - // Check for matches with data value wildcard if (result.signum() < 0) { - result = config.getBigDecimal("buy." + itemname + ".*", BigDecimal.ONE.negate()); - } - - // Check for matches with item name alone - if (result.signum() < 0) { - result = config.getBigDecimal("buy." + itemname, BigDecimal.ONE.negate()); - } - - if (result.signum() < 0) { - return getPrice(ess, itemStack); + return getWorthPrice(ess, itemStack); } return result; } /** - * Get the value of an item stack from the config for selling. + * Get the value of an item stack from the sell array in worth.yml. + * Falls back to worth section if the item is not found in the buy section. * * @param ess The Essentials instance. * @param itemStack The item stack to look up in the config. * @return The price from the config. */ public BigDecimal getSellPrice(IEssentials ess, ItemStack itemStack) { - BigDecimal result; - - String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""); - - // Check for matches with data value from stack - // Note that we always default to BigDecimal.ONE.negate(), equivalent to -1 - result = config.getBigDecimal("sell." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate()); - - // Check for matches with data value 0 - if (result.signum() < 0) { - final ConfigurationSection itemNameMatch = config.getConfigurationSection("sell." + itemname); - if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) { - result = config.getBigDecimal("sell." + itemname + ".0", BigDecimal.ONE.negate()); - } - } - - // Check for matches with data value wildcard - if (result.signum() < 0) { - result = config.getBigDecimal("sell." + itemname + ".*", BigDecimal.ONE.negate()); - } - - // Check for matches with item name alone - if (result.signum() < 0) { - result = config.getBigDecimal("sell." + itemname, BigDecimal.ONE.negate()); - } + BigDecimal result = getPrice(ess, itemStack, "sell"); if (result.signum() < 0) { - return getPrice(ess, itemStack); + return getWorthPrice(ess, itemStack); } return result; } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandworth.java b/Essentials/src/com/earth2me/essentials/commands/Commandworth.java index 31b55be5544..492d4136f17 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandworth.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandworth.java @@ -84,7 +84,7 @@ private BigDecimal itemWorth(CommandSource sender, User user, ItemStack is, Stri amount = ess.getWorth().getAmount(ess, user, is, args, true); } - BigDecimal worth = ess.getWorth().getPrice(ess, is); + BigDecimal worth = ess.getWorth().getSellPrice(ess, is); if (worth == null) { throw new Exception(tl("itemCannotBeSold")); From 0409afe3af45878d8095e88c54c67feda84c8b93 Mon Sep 17 00:00:00 2001 From: Levi McGlone Date: Thu, 3 Oct 2019 11:31:13 -0400 Subject: [PATCH 5/5] handle fallback for invalid integers --- .../com/earth2me/essentials/commands/Commandbuy.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java index ec2d707ac6e..d65b18dbda6 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandbuy.java @@ -27,11 +27,19 @@ public Commandbuy() { @Override public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { - if (args.length < 2 || !NumberUtil.isInt(args[1])) { + if (args.length < 1) { throw new NotEnoughArgumentsException(); } - int amountToGive = NumberUtils.toInt(args[1]); + int amountToGive; + + if (args[1] != null && NumberUtil.isInt(args[1])) { + amountToGive = NumberUtils.toInt(args[1]); + } else if (args[1] == null) { + amountToGive = 1; + } else { + throw new Exception("The second argument must be an integer."); + } if (amountToGive <= 0) { throw new Exception("You cannot buy 0 items.");