[Feature] Withdraw from trade signs without dropping items as overflow. [EXPERIMENTAL]
This commit is contained in:
parent
ed5743147b
commit
5f6cca83ce
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
final ItemStack stack = itemStack.clone();
|
||||
stack.setAmount(maxStackSize);
|
||||
itemStacks[i] = loc.getWorld().dropItem(loc, stack);
|
||||
ess.getLogger().log(Level.INFO, "abort paying " + user.getName() + " itemstack " + getItemStack().toString() + " due to lack of inventory space ");
|
||||
}
|
||||
if (leftover > 0)
|
||||
|
||||
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())
|
||||
{
|
||||
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() + " 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 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 (ess.getSettings().isDebug())
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -304,6 +344,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();
|
||||
|
@ -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!");
|
||||
|
|
Loading…
Reference in New Issue