package net.ess3.signs; import java.util.HashSet; import java.util.Locale; import java.util.Set; import static net.ess3.I18n._; import net.ess3.api.ChargeException; import net.ess3.api.IEssentials; import net.ess3.api.IUser; import net.ess3.economy.Trade; import net.ess3.signs.signs.SignException; import net.ess3.utils.FormatUtil; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; import org.bukkit.entity.Player; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.inventory.ItemStack; public class EssentialsSign { private static final Set EMPTY_SET = new HashSet(); protected final String signName; public EssentialsSign(final String signName) { this.signName = signName; } public final boolean onSignCreate(final SignChangeEvent event, final IEssentials ess) { final ISign sign = new EventSign(event); final IUser user = ess.getUserMap().getUser(event.getPlayer()); if (!SignsPermissions.CREATE.isAuthorized(user, signName)) { // Return true, so other plugins can use the same sign title, just hope // they won't change it to §1[Signname] return true; } sign.setLine(0, _("[{0}]", this.signName)); try { final boolean ret = onSignCreate(sign, user, getUsername(user), ess); if (ret) { sign.setLine(0, getSuccessName()); } return ret; } catch (ChargeException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } // Return true, so the player sees the wrong sign. return true; } public String getSuccessName() { return _("[{0}]", this.signName); } public String getTemplateName() { return _("[{0}]", this.signName); } private String getUsername(final IUser user) { return user.getName().substring(0, user.getName().length() > 13 ? 13 : user.getName().length()); } public final boolean onSignInteract(final Block block, final Player player, final IEssentials ess, final ISignsPlugin isp) { final ISign sign = new BlockSign(block); final IUser user = ess.getUserMap().getUser(player); if (user.checkSignThrottle(isp.getSettings().getData().getSignUsePerSecond())) { return false; } try { return SignsPermissions.USE.isAuthorized(user, signName) && onSignInteract(sign, user, getUsername(user), ess); } catch (ChargeException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); return false; } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); return false; } } public final boolean onSignBreak(final Block block, final Player player, final IEssentials ess) { final ISign sign = new BlockSign(block); final IUser user = ess.getUserMap().getUser(player); try { return SignsPermissions.BREAK.isAuthorized(user, signName) && onSignBreak(sign, user, getUsername(user), ess); } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); return false; } } protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException { return true; } protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException { return true; } protected boolean onSignBreak(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException { return true; } public final boolean onBlockPlace(final Block block, final Player player, final IEssentials ess) { final IUser user = ess.getUserMap().getUser(player); try { return onBlockPlace(block, user, getUsername(user), ess); } catch (ChargeException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } return false; } public final boolean onBlockInteract(final Block block, final Player player, final IEssentials ess) { final IUser user = ess.getUserMap().getUser(player); try { return onBlockInteract(block, user, getUsername(user), ess); } catch (ChargeException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } return false; } public final boolean onBlockBreak(final Block block, final Player player, final IEssentials ess) { final IUser user = ess.getUserMap().getUser(player); try { return onBlockBreak(block, user, getUsername(user), ess); } catch (SignException ex) { ess.getCommandHandler().showCommandError(user, signName, ex); } return false; } public boolean onBlockBreak(final Block block, final IEssentials ess) { return true; } public boolean onBlockExplode(final Block block, final IEssentials ess) { return true; } public boolean onBlockBurn(final Block block, final IEssentials ess) { return true; } public boolean onBlockIgnite(final Block block, final IEssentials ess) { return true; } public boolean onBlockPush(final Block block, final IEssentials ess) { return true; } public static boolean checkIfBlockBreaksSigns(final Block block) { final Block sign = block.getRelative(BlockFace.UP); if (sign.getType() == Material.SIGN_POST && isValidSign(new BlockSign(sign))) { return true; } final BlockFace[] directions = new BlockFace[]{ BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; for (BlockFace blockFace : directions) { final Block signblock = block.getRelative(blockFace); if (signblock.getType() == Material.WALL_SIGN) { final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign)signblock.getState().getData(); if (signMat != null && signMat.getFacing() == blockFace && isValidSign(new BlockSign(signblock))) { return true; } } } return false; } public static boolean isValidSign(final ISign sign) { return sign.getLine(0).matches("§1\\[.*\\]"); } protected boolean onBlockPlace(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException { return true; } protected boolean onBlockInteract(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException { return true; } protected boolean onBlockBreak(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException { return true; } public Set getBlocks() { return EMPTY_SET; } protected final void validateTrade(final ISign sign, final int index, final IEssentials ess) throws SignException { final String line = sign.getLine(index).trim(); if (line.isEmpty()) { return; } final Trade trade = getTrade(sign, index, 0, ess); final Double money = trade.getMoney(); if (money != null) { sign.setLine(index, FormatUtil.shortCurrency(money, ess)); } } protected final void validateTrade(final ISign sign, final int amountIndex, final int itemIndex, final IUser player, final IEssentials ess) throws SignException { if (sign.getLine(itemIndex).equalsIgnoreCase("exp") || sign.getLine(itemIndex).equalsIgnoreCase("xp")) { int amount = getIntegerPositive(sign.getLine(amountIndex)); sign.setLine(amountIndex, Integer.toString(amount)); sign.setLine(itemIndex, "exp"); return; } final Trade trade = getTrade(sign, amountIndex, itemIndex, player, ess); final ItemStack item = trade.getItemStack(); sign.setLine(amountIndex, Integer.toString(item.getAmount())); sign.setLine(itemIndex, sign.getLine(itemIndex).trim()); } protected final Trade getTrade(final ISign sign, final int amountIndex, final int itemIndex, final IUser player, final IEssentials ess) throws SignException { if (sign.getLine(itemIndex).equalsIgnoreCase("exp") || sign.getLine(itemIndex).equalsIgnoreCase("xp")) { final int amount = getIntegerPositive(sign.getLine(amountIndex)); return new Trade(amount, ess); } final ItemStack item = getItemStack(sign.getLine(itemIndex), 1, ess); final int amount = Math.min( getIntegerPositive(sign.getLine(amountIndex)), item.getType().getMaxStackSize() * player.getPlayer().getInventory().getSize()); if (item.getTypeId() == 0 || amount < 1) { throw new SignException(_("Quantities must be greater than 0.")); } item.setAmount(amount); return new Trade(item, ess); } protected final void validateInteger(final ISign sign, final int index) throws SignException { final String line = sign.getLine(index).trim(); if (line.isEmpty()) { throw new SignException("Empty line " + index); } final int quantity = getIntegerPositive(line); sign.setLine(index, Integer.toString(quantity)); } protected final int getIntegerPositive(final String line) throws SignException { final int quantity = getInteger(line); if (quantity < 1) { throw new SignException(_("Quantities must be greater than 0.")); } return quantity; } protected final int getInteger(final String line) throws SignException { try { final int quantity = Integer.parseInt(line); return quantity; } catch (NumberFormatException ex) { throw new SignException("Invalid sign", ex); } } protected final ItemStack getItemStack(final String itemName, final int quantity, final IEssentials ess) throws SignException { try { final ItemStack item = ess.getItemDb().get(itemName); item.setAmount(quantity); return item; } catch (Exception ex) { throw new SignException(ex.getMessage(), ex); } } protected final Double getMoney(final String line) throws SignException { final boolean isMoney = line.matches("^[^0-9-\\.][\\.0-9]+$"); return isMoney ? getDoublePositive(line.substring(1)) : null; } protected final Double getDoublePositive(final String line) throws SignException { final double quantity = getDouble(line); if (Math.round(quantity * 100.0) < 1.0) { throw new SignException(_("Quantities must be greater than 0.")); } return quantity; } protected final Double getDouble(final String line) throws SignException { try { return Double.parseDouble(line); } catch (NumberFormatException ex) { throw new SignException(ex.getMessage(), ex); } } protected final Trade getTrade(final ISign sign, final int index, final IEssentials ess) throws SignException { return getTrade(sign, index, 1, ess); } protected final Trade getTrade(final ISign sign, final int index, final int decrement, final IEssentials ess) throws SignException { final String line = sign.getLine(index).trim(); if (line.isEmpty()) { return new Trade(signName.toLowerCase(Locale.ENGLISH) + "sign", ess); } final Double money = getMoney(line); if (money == null) { final String[] split = line.split("[ :]+", 2); if (split.length != 2) { throw new SignException(_("Invalid charge.")); } final int quantity = getIntegerPositive(split[0]); final String item = split[1].toLowerCase(Locale.ENGLISH); if (item.equalsIgnoreCase("times")) { sign.setLine(index, (quantity - decrement) + " times"); return new Trade(signName.toLowerCase(Locale.ENGLISH) + "sign", ess); } else if (item.equalsIgnoreCase("exp") || item.equalsIgnoreCase("xp")) { sign.setLine(index, quantity + " exp"); return new Trade(quantity, ess); } else { final ItemStack stack = getItemStack(item, quantity, ess); sign.setLine(index, quantity + " " + item); return new Trade(stack, ess); } } else { return new Trade(money, ess); } } static class EventSign implements ISign { private final SignChangeEvent event; private final Block block; public EventSign(final SignChangeEvent event) { this.event = event; this.block = event.getBlock(); } @Override public final String getLine(final int index) { return event.getLine(index); } @Override public final void setLine(final int index, final String text) { event.setLine(index, text); } @Override public Block getBlock() { return block; } @Override public void updateSign() { } } public static class BlockSign implements ISign { private final Sign sign; private final Block block; public BlockSign(final Block block) { this.block = block; this.sign = (Sign)block.getState(); } @Override public final String getLine(final int index) { return sign.getLine(index); } @Override public final void setLine(final int index, final String text) { sign.setLine(index, text); } @Override public final Block getBlock() { return block; } @Override public final void updateSign() { sign.update(); } } public interface ISign { String getLine(final int index); void setLine(final int index, final String text); public Block getBlock(); void updateSign(); } }