From 0ae7ccbeb070c7eef0098dbf617c0c725d4900e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85dne=20Wasb=C3=B8?= Date: Sun, 6 Sep 2026 12:36:01 +0200 Subject: [PATCH 1/2] Started work on deriving a buy command implementation from the sell command --- .../essentials/commands/Commandbuy.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java new file mode 100644 index 00000000000..fa7c19e154b --- /dev/null +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java @@ -0,0 +1,147 @@ +package com.earth2me.essentials.commands; + +import com.earth2me.essentials.Trade; +import com.earth2me.essentials.User; +import com.earth2me.essentials.craftbukkit.Inventories; +import com.earth2me.essentials.adventure.AdventureUtil; +import com.earth2me.essentials.utils.NumberUtil; +import com.google.common.collect.Lists; +import net.ess3.api.TranslatableException; +import net.ess3.api.events.UserBalanceUpdateEvent; +import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.inventory.ItemStack; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.logging.Level; + +import static com.earth2me.essentials.I18n.tlLiteral; + +// The file commandsell.java has been used as a "template" +// Most of the code in this file is therefor a one-to-one copy from that file +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 { + BigDecimal totalWorth = BigDecimal.ZERO; + if (args.length < 1) { + throw new NotEnoughArgumentsException(); + } + + // Let's check if the user is authorized to buy stuff more of the stuff in hand. + // Consider removing the first if. + if (args[0].equalsIgnoreCase("hand") && !user.isAuthorized("essentials.buy.hand")) { + throw new TranslatableException("buyHandPermission"); + } else if ((args[0].equalsIgnoreCase("inventory") || args[0].equalsIgnoreCase("invent") || args[0].equalsIgnoreCase("all")) && !user.isAuthorized("essentials.buy.bulk")) { + throw new TranslatableException("buyBulkPermission"); + } + + final List is = ess.getItemDb().getMatching(user, args); + int count = 0; + + final boolean isBulk = is.size() > 1; + + final List notSold = new ArrayList<>(); + for (ItemStack stack : is) { + if (!ess.getSettings().isAllowBuyNamedItems()) { + if (stack.getItemMeta() != null && stack.getItemMeta().hasDisplayName()) { + if (isBulk) { + notSold.add(stack); + continue; + } + throw new TranslatableException("cannotBuyNamedItem"); + } + } + try { + if (stack.getAmount() > 0) { + totalWorth = totalWorth.add(buyItem(user, stack, args, isBulk)); + stack = stack.clone(); + count++; + for (final ItemStack zeroStack : is) { + if (zeroStack.isSimilar(stack)) { + zeroStack.setAmount(0); + } + } + } + } catch (final Exception e) { + if (!isBulk) { + throw e; + } + } + } + if (!notBought.isEmpty()) { + final List names = new ArrayList<>(); + for (final ItemStack stack : notBought { + if (stack.getItemMeta() != null) { //This was already validated but IDE still freaks out + names.add(stack.getItemMeta().getDisplayName()); + } + } + ess.showError(user.getSource(), new TranslatableException("cannotBuyTheseNamedItems", String.join(ChatColor.RESET + ", ", names)), commandLabel); + } + if (count != 1) { + final AdventureUtil.ParsedPlaceholder totalWorthStr = AdventureUtil.parsed(NumberUtil.displayCurrency(totalWorth, ess)); + if (args[0].equalsIgnoreCase("blocks")) { + user.sendTl("totalWorthBlocks", totalWorthStr, totalWorthStr); + } else { + user.sendTl("totalWorthAll", totalWorthStr, totalWorthStr); + } + } + } + + private BigDecimal sellItem(final User user, final ItemStack is, final String[] args, final boolean isBulkSell) throws Exception { + final int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkSell); + final BigDecimal originalWorth = ess.getWorth().getPrice(ess, is); + final BigDecimal worth = originalWorth == null ? null : originalWorth.multiply(ess.getSettings().getMultiplier(user)); + + if (worth == null) { + throw new TranslatableException("itemCannotBeBought"); + } + + if (amount <= 0) { + if (!isBulkSell) { + user.sendTl("itemBought", AdventureUtil.parsed(NumberUtil.displayCurrency(BigDecimal.ZERO, ess)), BigDecimal.ZERO, is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(worth, ess)); + } + return BigDecimal.ZERO; + } + + final BigDecimal result = worth.multiply(BigDecimal.valueOf(amount)); + + //TODO: Prices for Enchantments + final ItemStack ris = is.clone(); + ris.setAmount(amount); + // This statement is for checking if more items that is in inventory is trying to be sold. Should never happen. + // Needs to be rewritten into a check about if more gold is consumed. + if (!Inventories.containsAtLeast(user.getBase(), ris, amount)) { + // This should never happen. + throw new IllegalStateException("Trying to remove more items than are available."); + } + Inventories.removeItemAmount(user.getBase(), ris, ris.getAmount()); + user.getBase().updateInventory(); + Trade.log("Command", "Buy", "Item", user.getName(), new Trade(ris, ess), user.getName(), new Trade(result, ess), user.getLocation(), user.getMoney(), ess); + // Needs to be changed to a method for taking money + user.giveMoney(result, null, UserBalanceUpdateEvent.Cause.COMMAND_BUY); + final String typeName = is.getType().toString().toLowerCase(Locale.ENGLISH); + final AdventureUtil.ParsedPlaceholder worthDisplay = AdventureUtil.parsed(NumberUtil.displayCurrency(worth, ess)); + user.sendTl("itemBought", AdventureUtil.parsed(NumberUtil.displayCurrency(result, ess)), amount, typeName, worthDisplay); + ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("itemBoughtConsole", user.getName(), typeName, ess.getAdventureFacet().miniToLegacy(NumberUtil.displayCurrency(result, ess)), amount, ess.getAdventureFacet().miniToLegacy(worthDisplay.toString()), user.getDisplayName()))); + return result; + } + + @Override + protected List getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) { + if (args.length == 1) { + return getMatchingItems(args[0]); + } else if (args.length == 2) { + return Lists.newArrayList("1", "64"); + } else { + return Collections.emptyList(); + } + } +} From 401845f0d853b15d083a822300451a0937913f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85dne=20Wasb=C3=B8?= Date: Sun, 6 Sep 2026 12:57:16 +0200 Subject: [PATCH 2/2] Further work on comments --- .../earth2me/essentials/commands/Commandbuy.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java index fa7c19e154b..90a4bc3541c 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandbuy.java @@ -28,14 +28,16 @@ public Commandbuy() { super("buy"); } + // Starting point for when the command is run @Override public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { BigDecimal totalWorth = BigDecimal.ZERO; + // Throw an error if the user has not specified enough arguments. if (args.length < 1) { throw new NotEnoughArgumentsException(); } - // Let's check if the user is authorized to buy stuff more of the stuff in hand. + // Let's check if the user is authorized to buy more of the stuff in hand // Consider removing the first if. if (args[0].equalsIgnoreCase("hand") && !user.isAuthorized("essentials.buy.hand")) { throw new TranslatableException("buyHandPermission"); @@ -48,12 +50,12 @@ public void run(final Server server, final User user, final String commandLabel, final boolean isBulk = is.size() > 1; - final List notSold = new ArrayList<>(); + final List notBought = new ArrayList<>(); for (ItemStack stack : is) { if (!ess.getSettings().isAllowBuyNamedItems()) { if (stack.getItemMeta() != null && stack.getItemMeta().hasDisplayName()) { if (isBulk) { - notSold.add(stack); + notBought.add(stack); continue; } throw new TranslatableException("cannotBuyNamedItem"); @@ -95,8 +97,8 @@ public void run(final Server server, final User user, final String commandLabel, } } - private BigDecimal sellItem(final User user, final ItemStack is, final String[] args, final boolean isBulkSell) throws Exception { - final int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkSell); + private BigDecimal buyItem(final User user, final ItemStack is, final String[] args, final boolean isBulkBuy) throws Exception { + final int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkBuy); final BigDecimal originalWorth = ess.getWorth().getPrice(ess, is); final BigDecimal worth = originalWorth == null ? null : originalWorth.multiply(ess.getSettings().getMultiplier(user)); @@ -126,7 +128,7 @@ private BigDecimal sellItem(final User user, final ItemStack is, final String[] user.getBase().updateInventory(); Trade.log("Command", "Buy", "Item", user.getName(), new Trade(ris, ess), user.getName(), new Trade(result, ess), user.getLocation(), user.getMoney(), ess); // Needs to be changed to a method for taking money - user.giveMoney(result, null, UserBalanceUpdateEvent.Cause.COMMAND_BUY); + user.takeMoney(result, null, UserBalanceUpdateEvent.Cause.COMMAND_BUY); final String typeName = is.getType().toString().toLowerCase(Locale.ENGLISH); final AdventureUtil.ParsedPlaceholder worthDisplay = AdventureUtil.parsed(NumberUtil.displayCurrency(worth, ess)); user.sendTl("itemBought", AdventureUtil.parsed(NumberUtil.displayCurrency(result, ess)), amount, typeName, worthDisplay);