summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKHobbits <rob@khobbits.co.uk>2013-05-06 06:40:22 +0100
committerKHobbits <rob@khobbits.co.uk>2013-05-06 23:09:31 +0100
commit5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef (patch)
tree28a48d08c40c4e5538fda6c1a51ca6c4aad70d9e
parented5743147b9874cc5a735f373f0621fdb17e1b6f (diff)
downloadEssentials-5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef.tar
Essentials-5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef.tar.gz
Essentials-5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef.tar.lz
Essentials-5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef.tar.xz
Essentials-5f6cca83ceb002b8a6886d2a893e2c6ad8d463ef.zip
[Feature] Withdraw from trade signs without dropping items as overflow. [EXPERIMENTAL]
-rw-r--r--Essentials/src/com/earth2me/essentials/Kit.java3
-rw-r--r--Essentials/src/com/earth2me/essentials/Trade.java85
-rw-r--r--Essentials/src/com/earth2me/essentials/commands/Commandessentials.java1
-rw-r--r--Essentials/src/com/earth2me/essentials/craftbukkit/InventoryWorkaround.java14
-rw-r--r--Essentials/src/com/earth2me/essentials/signs/SignBuy.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/signs/SignProtection.java6
-rw-r--r--Essentials/src/com/earth2me/essentials/signs/SignSell.java3
-rw-r--r--Essentials/src/com/earth2me/essentials/signs/SignTrade.java118
8 files changed, 172 insertions, 60 deletions
diff --git a/Essentials/src/com/earth2me/essentials/Kit.java b/Essentials/src/com/earth2me/essentials/Kit.java
index 16cb35fc9..2807a06ad 100644
--- a/Essentials/src/com/earth2me/essentials/Kit.java
+++ b/Essentials/src/com/earth2me/essentials/Kit.java
@@ -2,6 +2,7 @@ package com.earth2me.essentials;
import static com.earth2me.essentials.I18n._;
import static com.earth2me.essentials.I18n.capitalCase;
+import com.earth2me.essentials.Trade.OverflowType;
import com.earth2me.essentials.commands.NoChargeException;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.textreader.IText;
@@ -137,7 +138,7 @@ public class Kit
{
BigDecimal value = new BigDecimal(kitItem.substring(ess.getSettings().getCurrencySymbol().length()).trim());
Trade t = new Trade(value, ess);
- t.pay(user);
+ t.pay(user, OverflowType.DROP);
continue;
}
diff --git a/Essentials/src/com/earth2me/essentials/Trade.java b/Essentials/src/com/earth2me/essentials/Trade.java
index a770bfc29..8830df9a1 100644
--- a/Essentials/src/com/earth2me/essentials/Trade.java
+++ b/Essentials/src/com/earth2me/essentials/Trade.java
@@ -35,6 +35,14 @@ public class Trade
ITEM
}
+
+ public enum OverflowType
+ {
+ ABORT,
+ DROP,
+ RETURN
+ }
+
public Trade(final String command, final IEssentials ess)
{
this(command, null, null, null, null, ess);
@@ -112,14 +120,13 @@ public class Trade
}
}
- public void pay(final IUser user)
+ public boolean pay(final IUser user)
{
- pay(user, true);
+ return pay(user, OverflowType.ABORT) == null;
}
- public boolean pay(final IUser user, final boolean dropItems)
+ public Map<Integer, ItemStack> pay(final IUser user, final OverflowType type)
{
- boolean success = true;
if (getMoney() != null && getMoney().signum() > 0)
{
if (ess.getSettings().isDebug())
@@ -130,33 +137,65 @@ public class Trade
}
if (getItemStack() != null)
{
- if (dropItems)
+ // This stores the would be overflow
+ Map<Integer, ItemStack> overFlow = InventoryWorkaround.addAllItems(user.getInventory(), getItemStack());
+
+ if (overFlow != null)
{
- final Map<Integer, ItemStack> leftOver = InventoryWorkaround.addItems(user.getInventory(), getItemStack());
- final Location loc = user.getLocation();
- for (ItemStack itemStack : leftOver.values())
+ switch (type)
{
- final int maxStackSize = itemStack.getType().getMaxStackSize();
- final int stacks = itemStack.getAmount() / maxStackSize;
- final int leftover = itemStack.getAmount() % maxStackSize;
- final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
- for (int i = 0; i < stacks; i++)
+ case ABORT:
+ if (ess.getSettings().isDebug())
+ {
+ ess.getLogger().log(Level.INFO, "abort paying " + user.getName() + " itemstack " + getItemStack().toString() + " due to lack of inventory space ");
+ }
+
+ return overFlow;
+
+ case RETURN:
+ // Pay the user the items, and return overflow
+ final Map<Integer, ItemStack> returnStack = InventoryWorkaround.addItems(user.getInventory(), getItemStack());
+ user.updateInventory();
+
+ if (ess.getSettings().isDebug())
+ {
+ ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " with overflow " + returnStack.get(0).toString());
+ }
+
+ return returnStack;
+
+ case DROP:
+ // Pay the users the items directly, and drop the rest, will always return no overflow.
+ final Map<Integer, ItemStack> leftOver = InventoryWorkaround.addItems(user.getInventory(), getItemStack());
+ final Location loc = user.getLocation();
+ for (ItemStack loStack : leftOver.values())
{
- final ItemStack stack = itemStack.clone();
- stack.setAmount(maxStackSize);
- itemStacks[i] = loc.getWorld().dropItem(loc, stack);
+ final int maxStackSize = loStack.getType().getMaxStackSize();
+ final int stacks = loStack.getAmount() / maxStackSize;
+ final int leftover = loStack.getAmount() % maxStackSize;
+ final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
+ for (int i = 0; i < stacks; i++)
+ {
+ final ItemStack stack = loStack.clone();
+ stack.setAmount(maxStackSize);
+ itemStacks[i] = loc.getWorld().dropItem(loc, stack);
+ }
+ if (leftover > 0)
+ {
+ final ItemStack stack = loStack.clone();
+ stack.setAmount(leftover);
+ itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
+ }
}
- if (leftover > 0)
+ if (ess.getSettings().isDebug())
{
- final ItemStack stack = itemStack.clone();
- stack.setAmount(leftover);
- itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
+ ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " and dropping overflow " + leftOver.get(0).toString());
}
}
}
- else
+ else if (ess.getSettings().isDebug())
{
- success = InventoryWorkaround.addAllItems(user.getInventory(), getItemStack());
+ ess.getLogger().log(Level.INFO, "paying " + user.getName() + " itemstack " + getItemStack().toString());
}
user.updateInventory();
}
@@ -164,7 +203,7 @@ public class Trade
{
SetExpFix.setTotalExperience(user, SetExpFix.getTotalExperience(user) + getExperience());
}
- return success;
+ return null;
}
public void charge(final IUser user) throws ChargeException
diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java b/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java
index 1fd0720ee..671a5a2b0 100644
--- a/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java
+++ b/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java
@@ -222,6 +222,7 @@ public class Commandessentials extends EssentialsCommand
{
sender.sendMessage("This sub-command will delete users who havent logged in in the last <days> days.");
sender.sendMessage("Optional parameters define the minium amount required to prevent deletion.");
+ sender.sendMessage("Unless you define larger default values, this command wil ignore people who have more than 0 money/homes/bans.");
throw new Exception("/<command> cleanup <days> [money] [homes] [ban count]");
}
sender.sendMessage(_("cleaning"));
diff --git a/Essentials/src/com/earth2me/essentials/craftbukkit/InventoryWorkaround.java b/Essentials/src/com/earth2me/essentials/craftbukkit/InventoryWorkaround.java
index 2e05f5c43..d5da047fe 100644
--- a/Essentials/src/com/earth2me/essentials/craftbukkit/InventoryWorkaround.java
+++ b/Essentials/src/com/earth2me/essentials/craftbukkit/InventoryWorkaround.java
@@ -34,23 +34,29 @@ public final class InventoryWorkaround
return -1;
}
- public static boolean addAllItems(final Inventory inventory, final ItemStack... items)
+ // Returns what it couldnt store
+ // This will will abort if it couldn't store all items
+ public static Map<Integer, ItemStack> addAllItems(final Inventory inventory, final ItemStack... items)
{
final Inventory fakeInventory = Bukkit.getServer().createInventory(null, inventory.getType());
fakeInventory.setContents(inventory.getContents());
- if (addItems(fakeInventory, items).isEmpty())
+ Map<Integer, ItemStack> overFlow = addItems(fakeInventory, items);
+ if (overFlow.isEmpty())
{
addItems(inventory, items);
- return true;
+ return null;
}
- return false;
+ return addItems(fakeInventory, items);
}
+ // Returns what it couldnt store
public static Map<Integer, ItemStack> addItems(final Inventory inventory, final ItemStack... items)
{
return addOversizedItems(inventory, 0, items);
}
+ // Returns what it couldnt store
+ // Set oversizedStack to below normal stack size to disable oversized stacks
public static Map<Integer, ItemStack> addOversizedItems(final Inventory inventory, final int oversizedStacks, final ItemStack... items)
{
final Map<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>();
diff --git a/Essentials/src/com/earth2me/essentials/signs/SignBuy.java b/Essentials/src/com/earth2me/essentials/signs/SignBuy.java
index d675a598c..7f4b824ca 100644
--- a/Essentials/src/com/earth2me/essentials/signs/SignBuy.java
+++ b/Essentials/src/com/earth2me/essentials/signs/SignBuy.java
@@ -27,7 +27,7 @@ public class SignBuy extends EssentialsSign
final Trade items = getTrade(sign, 1, 2, player, ess);
final Trade charge = getTrade(sign, 3, ess);
charge.isAffordableFor(player);
- if (!items.pay(player, false))
+ if (!items.pay(player))
{
throw new ChargeException("Inventory full"); //TODO: TL
}
diff --git a/Essentials/src/com/earth2me/essentials/signs/SignProtection.java b/Essentials/src/com/earth2me/essentials/signs/SignProtection.java
index b5a679324..c336ec8c8 100644
--- a/Essentials/src/com/earth2me/essentials/signs/SignProtection.java
+++ b/Essentials/src/com/earth2me/essentials/signs/SignProtection.java
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import static com.earth2me.essentials.I18n._;
import com.earth2me.essentials.*;
+import com.earth2me.essentials.Trade.OverflowType;
import java.util.*;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -10,6 +11,7 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.inventory.ItemStack;
+
@Deprecated // This sign will be removed soon
public class SignProtection extends EssentialsSign
{
@@ -81,7 +83,7 @@ public class SignProtection extends EssentialsSign
{
block.setType(Material.AIR);
final Trade trade = new Trade(new ItemStack(Material.SIGN, 1), ess);
- trade.pay(player);
+ trade.pay(player, OverflowType.DROP);
}
}
}
@@ -241,7 +243,7 @@ public class SignProtection extends EssentialsSign
{
return protectedBlocks;
}
-
+
@Override
public boolean areHeavyEventRequired()
{
diff --git a/Essentials/src/com/earth2me/essentials/signs/SignSell.java b/Essentials/src/com/earth2me/essentials/signs/SignSell.java
index 442a503c2..ea2022f7f 100644
--- a/Essentials/src/com/earth2me/essentials/signs/SignSell.java
+++ b/Essentials/src/com/earth2me/essentials/signs/SignSell.java
@@ -3,6 +3,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.Trade;
+import com.earth2me.essentials.Trade.OverflowType;
import com.earth2me.essentials.User;
@@ -27,7 +28,7 @@ public class SignSell extends EssentialsSign
final Trade charge = getTrade(sign, 1, 2, player, ess);
final Trade money = getTrade(sign, 3, ess);
charge.isAffordableFor(player);
- money.pay(player);
+ money.pay(player, OverflowType.DROP);
charge.charge(player);
Trade.log("Sign", "Sell", "Interact", username, charge, username, money, sign.getBlock().getLocation(), ess);
return true;
diff --git a/Essentials/src/com/earth2me/essentials/signs/SignTrade.java b/Essentials/src/com/earth2me/essentials/signs/SignTrade.java
index eb6cc60ee..eb611e7ea 100644
--- a/Essentials/src/com/earth2me/essentials/signs/SignTrade.java
+++ b/Essentials/src/com/earth2me/essentials/signs/SignTrade.java
@@ -3,7 +3,9 @@ package com.earth2me.essentials.signs;
import static com.earth2me.essentials.I18n._;
import com.earth2me.essentials.Trade.TradeType;
import com.earth2me.essentials.*;
+import com.earth2me.essentials.Trade.OverflowType;
import java.math.BigDecimal;
+import java.util.Map;
import org.bukkit.inventory.ItemStack;
//TODO: TL exceptions
@@ -14,13 +16,21 @@ public class SignTrade extends EssentialsSign
super("Trade");
}
+
+ public enum AmountType
+ {
+ TOTAL,
+ ROUNDED,
+ COST
+ }
+
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException
{
validateTrade(sign, 1, false, ess);
validateTrade(sign, 2, true, ess);
- final Trade trade = getTrade(sign, 2, true, true, ess);
- final Trade charge = getTrade(sign, 1, true, false, ess);
+ final Trade trade = getTrade(sign, 2, AmountType.ROUNDED, true, ess);
+ final Trade charge = getTrade(sign, 1, AmountType.ROUNDED, false, ess);
if (trade.getType() == charge.getType() && (trade.getType() != TradeType.ITEM || trade.getItemStack().getType().equals(charge.getItemStack().getType())))
{
throw new SignException("You cannot trade for the same item type.");
@@ -41,9 +51,20 @@ public class SignTrade extends EssentialsSign
Trade stored = null;
try
{
- stored = getTrade(sign, 1, true, true, ess);
+ stored = getTrade(sign, 1, AmountType.TOTAL, true, ess);
subtractAmount(sign, 1, stored, ess);
- stored.pay(player);
+
+ Map<Integer, ItemStack> withdraw = stored.pay(player, OverflowType.RETURN);
+
+ if (withdraw == null)
+ {
+ Trade.log("Sign", "Trade", "Withdraw", username, store, username, null, sign.getBlock().getLocation(), ess);
+ }
+ else
+ {
+ setAmount(sign, 1, BigDecimal.valueOf(withdraw.get(0).getAmount()), ess);
+ Trade.log("Sign", "Trade", "Withdraw", username, stored, username, new Trade(withdraw.get(0), ess), sign.getBlock().getLocation(), ess);
+ }
}
catch (SignException e)
{
@@ -52,16 +73,16 @@ public class SignTrade extends EssentialsSign
throw new SignException(_("tradeSignEmptyOwner"), e);
}
}
- Trade.log("Sign", "Trade", "OwnerInteract", username, store, username, stored, sign.getBlock().getLocation(), ess);
+ Trade.log("Sign", "Trade", "Deposit", username, store, username, null, sign.getBlock().getLocation(), ess);
}
else
{
- final Trade charge = getTrade(sign, 1, false, false, ess);
- final Trade trade = getTrade(sign, 2, false, true, ess);
+ final Trade charge = getTrade(sign, 1, AmountType.COST, false, ess);
+ final Trade trade = getTrade(sign, 2, AmountType.COST, true, ess);
charge.isAffordableFor(player);
addAmount(sign, 1, charge, ess);
subtractAmount(sign, 2, trade, ess);
- if (!trade.pay(player, false))
+ if (!trade.pay(player))
{
subtractAmount(sign, 1, charge, ess);
addAmount(sign, 2, trade, ess);
@@ -76,7 +97,7 @@ public class SignTrade extends EssentialsSign
private Trade rechargeSign(final ISign sign, final IEssentials ess, final User player) throws SignException, ChargeException
{
- final Trade trade = getTrade(sign, 2, false, false, ess);
+ final Trade trade = getTrade(sign, 2, AmountType.COST, false, ess);
if (trade.getItemStack() != null && player.getItemInHand() != null
&& trade.getItemStack().getTypeId() == player.getItemInHand().getTypeId()
&& trade.getItemStack().getDurability() == player.getItemInHand().getDurability()
@@ -105,11 +126,24 @@ public class SignTrade extends EssentialsSign
{
try
{
- final Trade stored1 = getTrade(sign, 1, true, false, ess);
- final Trade stored2 = getTrade(sign, 2, true, false, ess);
- stored1.pay(player);
- stored2.pay(player);
- Trade.log("Sign", "Trade", "Break", username, stored2, username, stored1, sign.getBlock().getLocation(), ess);
+ final Trade stored1 = getTrade(sign, 1, AmountType.TOTAL, false, ess);
+ final Trade stored2 = getTrade(sign, 2, AmountType.TOTAL, false, ess);
+ Map<Integer, ItemStack> withdraw1 = stored1.pay(player, OverflowType.RETURN);
+ Map<Integer, ItemStack> withdraw2 = stored2.pay(player, OverflowType.RETURN);
+
+ if (withdraw1 == null && withdraw2 == null)
+ {
+ Trade.log("Sign", "Trade", "Break", username, stored2, username, stored1, sign.getBlock().getLocation(), ess);
+ return true;
+ }
+
+ setAmount(sign, 1, BigDecimal.valueOf(withdraw1 == null ? 0L : withdraw1.get(0).getAmount()), ess);
+ Trade.log("Sign", "Trade", "Withdraw", username, stored1, username, withdraw1 == null ? null : new Trade(withdraw1.get(0), ess), sign.getBlock().getLocation(), ess);
+
+ setAmount(sign, 2, BigDecimal.valueOf(withdraw2 == null ? 0L : withdraw2.get(0).getAmount()), ess);
+ Trade.log("Sign", "Trade", "Withdraw", username, stored2, username, withdraw2 == null ? null : new Trade(withdraw2.get(0), ess), sign.getBlock().getLocation(), ess);
+
+ sign.updateSign();
}
catch (SignException e)
{
@@ -119,7 +153,7 @@ public class SignTrade extends EssentialsSign
}
throw e;
}
- return true;
+ return false;
}
else
{
@@ -208,7 +242,7 @@ public class SignTrade extends EssentialsSign
throw new SignException(_("invalidSignLine", index + 1));
}
- protected final Trade getTrade(final ISign sign, final int index, final boolean fullAmount, final boolean notEmpty, final IEssentials ess) throws SignException
+ protected final Trade getTrade(final ISign sign, final int index, final AmountType amountType, final boolean notEmpty, final IEssentials ess) throws SignException
{
final String line = sign.getLine(index).trim();
if (line.isEmpty())
@@ -225,7 +259,7 @@ public class SignTrade extends EssentialsSign
final BigDecimal amount = notEmpty ? getBigDecimalPositive(split[1]) : getBigDecimal(split[1]);
if (money != null && amount != null)
{
- return new Trade(fullAmount ? amount : money, ess);
+ return new Trade(amountType == AmountType.COST ? money : amount, ess);
}
}
catch (SignException e)
@@ -240,24 +274,30 @@ public class SignTrade extends EssentialsSign
{
final int stackamount = getIntegerPositive(split[0]);
int amount = getInteger(split[2]);
- amount -= amount % stackamount;
+ if (amountType == AmountType.ROUNDED)
+ {
+ amount -= amount % stackamount;
+ }
if (notEmpty && (amount < 1 || stackamount < 1))
{
throw new SignException(_("tradeSignEmpty"));
}
- return new Trade(fullAmount ? amount : stackamount, ess);
+ return new Trade((amountType == AmountType.COST ? stackamount : amount), ess);
}
else
{
final int stackamount = getIntegerPositive(split[0]);
final ItemStack item = getItemStack(split[1], stackamount, ess);
int amount = getInteger(split[2]);
- amount -= amount % stackamount;
+ if (amountType == AmountType.ROUNDED)
+ {
+ amount -= amount % stackamount;
+ }
if (notEmpty && (amount < 1 || stackamount < 1 || item.getTypeId() == 0))
{
throw new SignException(_("tradeSignEmpty"));
}
- item.setAmount(fullAmount ? amount : stackamount);
+ item.setAmount(amountType == AmountType.COST ? stackamount : amount);
return new Trade(item, ess);
}
}
@@ -305,6 +345,31 @@ public class SignTrade extends EssentialsSign
//TODO: Translate these exceptions.
private void changeAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess) throws SignException
{
+ final String line = sign.getLine(index).trim();
+ if (line.isEmpty())
+ {
+ throw new SignException("Empty line");
+ }
+ final String[] split = line.split("[ :]+");
+
+ if (split.length == 2)
+ {
+ final BigDecimal amount = getBigDecimal(split[1]).add(value);
+ setAmount(sign, index, amount, ess);
+ return;
+ }
+ if (split.length == 3)
+ {
+ final BigDecimal amount = getBigDecimal(split[2]).add(value);
+ setAmount(sign, index, amount, ess);
+ return;
+ }
+ throw new SignException(_("invalidSignLine", index + 1));
+ }
+
+ //TODO: Translate these exceptions.
+ private void setAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess) throws SignException
+ {
final String line = sign.getLine(index).trim();
if (line.isEmpty())
@@ -319,7 +384,7 @@ public class SignTrade extends EssentialsSign
final BigDecimal amount = getBigDecimal(split[1]);
if (money != null && amount != null)
{
- final String newline = Util.shortCurrency(money, ess) + ":" + Util.shortCurrency(amount.add(value), ess).substring(1);
+ final String newline = Util.shortCurrency(money, ess) + ":" + Util.shortCurrency(value, ess).substring(1);
if (newline.length() > 15)
{
throw new SignException("This sign is full: Line too long!");
@@ -334,8 +399,7 @@ public class SignTrade extends EssentialsSign
if (split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp"))
{
final int stackamount = getIntegerPositive(split[0]);
- final int amount = getInteger(split[2]);
- final String newline = stackamount + " " + split[1] + ":" + (amount + value.intValueExact());
+ final String newline = stackamount + " " + split[1] + ":" + (value.intValueExact());
if (newline.length() > 15)
{
throw new SignException("This sign is full: Line too long!");
@@ -346,10 +410,8 @@ public class SignTrade extends EssentialsSign
else
{
final int stackamount = getIntegerPositive(split[0]);
- //TODO: Unused local variable
- final ItemStack item = getItemStack(split[1], stackamount, ess);
- final int amount = getInteger(split[2]);
- final String newline = stackamount + " " + split[1] + ":" + (amount + value.intValueExact());
+ getItemStack(split[1], stackamount, ess);
+ final String newline = stackamount + " " + split[1] + ":" + (value.intValueExact());
if (newline.length() > 15)
{
throw new SignException("This sign is full: Line too long!");