Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 53 additions & 8 deletions Essentials/src/com/earth2me/essentials/Worth.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -62,6 +62,51 @@ public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) {
return result;
}

/**
* 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this whole function (as well as getSellPrice) can be folded into getPrice() where getPrice() has an additional argument for which 'keyspace' it is looking up the price in i.e. the 'buy' keyspace vs the 'worth' keyspace.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. I just refactored this.

BigDecimal result = getPrice(ess, itemStack, "buy");

if (result.signum() < 0) {
return getWorthPrice(ess, itemStack);
}
return result;
}

/**
* 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 = getPrice(ess, itemStack, "sell");

if (result.signum() < 0) {
return getWorthPrice(ess, itemStack);
}
return result;
}

/**
* Get the amount of items to be sold from a player's inventory.
*
Expand Down
98 changes: 98 additions & 0 deletions Essentials/src/com/earth2me/essentials/commands/Commandbuy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
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 < 1) {
throw new NotEnoughArgumentsException();
}

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.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a localization lookup.

}

ItemStack is = ess.getItemDb().get(args[0]);
is.setAmount(amountToGive);
BigDecimal worthSingleItem = ess.getWorth().getBuyPrice(ess, is);
BigDecimal worth = worthSingleItem.multiply(BigDecimal.valueOf(amountToGive));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause a NPE if getBuyPrice doesn't find a worth - worthSingleItem will be null. The check on 45-47 should happen after 42.


if (worth == null) {
throw new Exception(tl("itemCannotBeSold"));
}

if (worth.compareTo(user.getMoney()) == -1) {
boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();
BigDecimal leftoverValue = BigDecimal.ZERO;
Map<Integer, ItemStack> leftovers;

if (user.isAuthorized("essentials.oversizedstacks")) {
leftovers = InventoryWorkaround.addOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), is);
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like some indentation / formatting issues in this file - it makes it harder to read.

leftovers = InventoryWorkaround.addItems(user.getBase().getInventory(), is);
}

if (isDropItemsIfFull) {
for (ItemStack item : leftovers.values()) {
World w = user.getWorld();
w.dropItemNaturally(user.getLocation(), item);
}
} else if(!leftovers.values().isEmpty()) {
for (ItemStack item : leftovers.values()) {
leftoverValue = leftoverValue.add(worthSingleItem.multiply(BigDecimal.valueOf(item.getAmount())));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is more expensive (cpu time) / more verbose than counting how many total leftovers there are then doing a single BigDecimal multiply operation (no need for subsequent BigDecimal add operations)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix this is a separate commit.

}

user.sendMessage("Not enough inventory space. Refunding $<amount>.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a format string to it can be localized to different languages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also did we really refund them if we never took it to begin with?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I couldn't think of a better way to phrase it. Maybe just a message of something like "You didn't have enough inventory space. You purchased X items instead of Y."

Any input here is appreciated.

}

user.takeMoney(worth.subtract(leftoverValue));
user.getBase().updateInventory();
} else {
throw new Exception("You do not have enough money.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs a localization lookup

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time contributing to this repo, so please forgive my ignorance here. I understand how i18n works from the other files. Am I required to provide a translation for each language as a part of this PR? Do you have a recommended translator or translation tool I should use to do the translations?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remember who told me this, but I add my messages to just messages.properties. You can ignore the other files.

}
}

@Override
protected List<String> 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should /worth list both the buying and selling prices?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should probably be a way to configure whether or not it shows up, in the case that servers don't want to use both buy and sell at the same time, for example.


if (worth == null) {
throw new Exception(tl("itemCannotBeSold"));
Expand Down
1 change: 1 addition & 0 deletions Essentials/src/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ player-commands:
- balance.others
- balancetop
- build
- buy
- chat.color
- chat.format
- chat.shout
Expand Down
3 changes: 3 additions & 0 deletions Essentials/src/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ commands:
description: Set a player on fire.
usage: /<command> <player> <seconds>
aliases: [eburn]
buy:
description: Buy the specified item.
usage: /<command> <<itemname>|<id>> [-][amount]
clearinventory:
description: Clear all items in your inventory.
usage: /<command> [player|*] [item[:<data>]|*|**] [amount]
Expand Down
7 changes: 7 additions & 0 deletions Essentials/src/worth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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