summaryrefslogtreecommitdiffstats
path: root/EssentialsSigns/src/net/ess3/signs
diff options
context:
space:
mode:
Diffstat (limited to 'EssentialsSigns/src/net/ess3/signs')
-rw-r--r--EssentialsSigns/src/net/ess3/signs/EssentialsSign.java516
-rw-r--r--EssentialsSigns/src/net/ess3/signs/EssentialsSignsPlugin.java54
-rw-r--r--EssentialsSigns/src/net/ess3/signs/ISignsPlugin.java9
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignBalance.java22
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignBlockListener.java264
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignBuy.java38
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignDisposal.java23
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignEnchant.java119
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignEntityListener.java80
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignException.java15
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignFree.java47
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignGameMode.java37
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignHeal.java36
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignKit.java75
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignMail.java41
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignPlayerListener.java65
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignProtection.java350
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignSell.java35
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignSpawnmob.java48
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignTime.java57
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignTrade.java361
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignWarp.java70
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignWeather.java55
-rw-r--r--EssentialsSigns/src/net/ess3/signs/Signs.java33
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignsConfig.java21
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignsConfigHolder.java85
-rw-r--r--EssentialsSigns/src/net/ess3/signs/SignsPermissions.java51
27 files changed, 2607 insertions, 0 deletions
diff --git a/EssentialsSigns/src/net/ess3/signs/EssentialsSign.java b/EssentialsSigns/src/net/ess3/signs/EssentialsSign.java
new file mode 100644
index 000000000..272f14252
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/EssentialsSign.java
@@ -0,0 +1,516 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import static net.ess3.I18n._;
+import net.ess3.economy.Trade;
+import net.ess3.utils.Util;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+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<Material> EMPTY_SET = new HashSet<Material>();
+ protected transient 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.getUser(event.getPlayer());
+ if (!SignsPermissions.getCreatePermission(signName).isAuthorized(user))
+ {
+ // 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, _("signFormatFail", 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 _("signFormatSuccess", this.signName);
+ }
+
+ public String getTemplateName()
+ {
+ return _("signFormatTemplate", 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 ISign sign = new BlockSign(block);
+ final IUser user = ess.getUser(player);
+ try
+ {
+ return SignsPermissions.getUsePermission(signName).isAuthorized(user)
+ && 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.getUser(player);
+ try
+ {
+ return SignsPermissions.getBreakPermission(signName).isAuthorized(user)
+ && 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.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.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.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<Material> 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, Util.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.getInventory().getSize());
+ if (item.getTypeId() == 0 || amount < 1)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ 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(_("moreThanZero"));
+ }
+ 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(_("moreThanZero"));
+ }
+ 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(_("invalidCharge"));
+ }
+ 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 transient SignChangeEvent event;
+ private final transient 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()
+ {
+ }
+ }
+
+
+ static class BlockSign implements ISign
+ {
+ private final transient Sign sign;
+ private final transient 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();
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/EssentialsSignsPlugin.java b/EssentialsSigns/src/net/ess3/signs/EssentialsSignsPlugin.java
new file mode 100644
index 000000000..d2f615d52
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/EssentialsSignsPlugin.java
@@ -0,0 +1,54 @@
+package net.ess3.signs;
+
+import static net.ess3.I18n._;
+import net.ess3.api.IEssentials;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+
+public class EssentialsSignsPlugin extends JavaPlugin implements ISignsPlugin
+{
+ private static final transient Logger LOGGER = Bukkit.getLogger();
+ private transient SignsConfigHolder config;
+
+ @Override
+ public void onEnable()
+ {
+ final PluginManager pluginManager = getServer().getPluginManager();
+ final IEssentials ess = (IEssentials)pluginManager.getPlugin("Essentials-3");
+ if (!this.getDescription().getVersion().equals(ess.getDescription().getVersion()))
+ {
+ LOGGER.log(Level.WARNING, _("versionMismatchAll"));
+ }
+ if (!ess.isEnabled())
+ {
+ this.setEnabled(false);
+ return;
+ }
+
+ final SignBlockListener signBlockListener = new SignBlockListener(ess, this);
+ pluginManager.registerEvents(signBlockListener, this);
+
+ final SignPlayerListener signPlayerListener = new SignPlayerListener(ess, this);
+ pluginManager.registerEvents(signPlayerListener, this);
+
+ final SignEntityListener signEntityListener = new SignEntityListener(ess, this);
+ pluginManager.registerEvents(signEntityListener, this);
+
+ config = new SignsConfigHolder(ess, this);
+ }
+
+ @Override
+ public void onDisable()
+ {
+ }
+
+ @Override
+ public SignsConfigHolder getSettings()
+ {
+ return config;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/ISignsPlugin.java b/EssentialsSigns/src/net/ess3/signs/ISignsPlugin.java
new file mode 100644
index 000000000..9a6d14a61
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/ISignsPlugin.java
@@ -0,0 +1,9 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentialsModule;
+
+
+public interface ISignsPlugin extends IEssentialsModule
+{
+ SignsConfigHolder getSettings();
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignBalance.java b/EssentialsSigns/src/net/ess3/signs/SignBalance.java
new file mode 100644
index 000000000..35a1648ae
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignBalance.java
@@ -0,0 +1,22 @@
+package net.ess3.signs;
+
+import static net.ess3.I18n._;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.utils.Util;
+
+
+public class SignBalance extends EssentialsSign
+{
+ public SignBalance()
+ {
+ super("Balance");
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ player.sendMessage(_("balance", Util.displayCurrency(player.getMoney(), ess)));
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignBlockListener.java b/EssentialsSigns/src/net/ess3/signs/SignBlockListener.java
new file mode 100644
index 000000000..31cdfc970
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignBlockListener.java
@@ -0,0 +1,264 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentials;
+import net.ess3.api.ISettings;
+import net.ess3.api.IUser;
+import net.ess3.utils.Util;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.Sign;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.*;
+
+
+public class SignBlockListener implements Listener
+{
+ private final transient IEssentials ess;
+ private final transient ISignsPlugin plugin;
+ private final static Logger LOGGER = Logger.getLogger("Minecraft");
+ private final static int WALL_SIGN = Material.WALL_SIGN.getId();
+ private final static int SIGN_POST = Material.SIGN_POST.getId();
+
+ public SignBlockListener(final IEssentials ess, final ISignsPlugin plugin)
+ {
+ this.ess = ess;
+ this.plugin = plugin;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBlockBreak(final BlockBreakEvent event)
+ {
+ ISettings settings = ess.getSettings();
+ settings.acquireReadLock();
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ if (protectSignsAndBlocks(event.getBlock(), event.getPlayer()))
+ {
+ event.setCancelled(true);
+ }
+ }
+
+ public boolean protectSignsAndBlocks(final Block block, final Player player)
+ {
+ final int mat = block.getTypeId();
+ if (mat == SIGN_POST || mat == WALL_SIGN)
+ {
+ final Sign csign = (Sign)block.getState();
+
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (csign.getLine(0).equalsIgnoreCase(sign.getSuccessName())
+ && !sign.onSignBreak(block, player, ess))
+ {
+ return true;
+ }
+ }
+ }
+ // prevent any signs be broken by destroying the block they are attached to
+ if (EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ LOGGER.log(Level.INFO, "Prevented that a block was broken next to a sign.");
+ return true;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockBreak(block, player, ess))
+ {
+ LOGGER.log(Level.INFO, "A block was protected by a sign.");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onSignChange(final SignChangeEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+ IUser user = ess.getUser(event.getPlayer());
+
+ for (int i = 0; i < 4; i++)
+ {
+ event.setLine(i, Util.formatString(user, "essentials.signs", event.getLine(i)));
+ }
+
+ for (Signs signs : Signs.values())
+ {
+ final EssentialsSign sign = signs.getSign();
+ if (event.getLine(0).equalsIgnoreCase(sign.getSuccessName()))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ if (event.getLine(0).equalsIgnoreCase(sign.getTemplateName())
+ && !sign.onSignCreate(event, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onBlockPlace(final BlockPlaceEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ final Block against = event.getBlockAgainst();
+ if ((against.getTypeId() == WALL_SIGN
+ || against.getTypeId() == SIGN_POST)
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(against)))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ final Block block = event.getBlock();
+ if (block.getTypeId() == WALL_SIGN
+ || block.getTypeId() == SIGN_POST)
+ {
+ return;
+ }
+ for (Signs signs : Signs.values())
+ {
+ final EssentialsSign sign = signs.getSign();
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockPlace(block, event.getPlayer(), ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onBlockBurn(final BlockBurnEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ final Block block = event.getBlock();
+ if (((block.getTypeId() == WALL_SIGN
+ || block.getTypeId() == SIGN_POST)
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockBurn(block, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onBlockIgnite(final BlockIgniteEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ final Block block = event.getBlock();
+ if (((block.getTypeId() == WALL_SIGN
+ || block.getTypeId() == SIGN_POST)
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockIgnite(block, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onBlockPistonExtend(final BlockPistonExtendEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ for (Block block : event.getBlocks())
+ {
+ if (((block.getTypeId() == WALL_SIGN
+ || block.getTypeId() == SIGN_POST)
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockPush(block, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onBlockPistonRetract(final BlockPistonRetractEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ if (event.isSticky())
+ {
+ final Block block = event.getBlock();
+ if (((block.getTypeId() == WALL_SIGN
+ || block.getTypeId() == SIGN_POST)
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockPush(block, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignBuy.java b/EssentialsSigns/src/net/ess3/signs/SignBuy.java
new file mode 100644
index 000000000..ff08cdbc1
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignBuy.java
@@ -0,0 +1,38 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.economy.Trade;
+
+
+public class SignBuy extends EssentialsSign
+{
+ public SignBuy()
+ {
+ super("Buy");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 1, 2, player, ess);
+ validateTrade(sign, 3, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade items = getTrade(sign, 1, 2, player, ess);
+ final Trade charge = getTrade(sign, 3, ess);
+ charge.isAffordableFor(player);
+ if (!items.pay(player, false))
+ {
+ throw new ChargeException("Inventory full");
+ }
+ charge.charge(player);
+ Trade.log("Sign", "Buy", "Interact", username, charge, username, items, sign.getBlock().getLocation(), ess);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignDisposal.java b/EssentialsSigns/src/net/ess3/signs/SignDisposal.java
new file mode 100644
index 000000000..01775e18c
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignDisposal.java
@@ -0,0 +1,23 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+
+
+public class SignDisposal extends EssentialsSign
+{
+ public SignDisposal()
+ {
+ super("Disposal");
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess)
+ {
+ player.sendMessage("Bukkit broke this sign :(");
+ //TODO: wait for a fix in bukkit
+ //Problem: Items can be duplicated
+ //player.getBase().openInventory(ess.getServer().createInventory(player, 36));
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignEnchant.java b/EssentialsSigns/src/net/ess3/signs/SignEnchant.java
new file mode 100644
index 000000000..6004d9f38
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignEnchant.java
@@ -0,0 +1,119 @@
+package net.ess3.signs;
+
+import static net.ess3.I18n._;
+import net.ess3.api.ChargeException;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.bukkit.Enchantments;
+import net.ess3.economy.Trade;
+import java.util.Locale;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.ItemStack;
+
+
+public class SignEnchant extends EssentialsSign
+{
+ public SignEnchant()
+ {
+ super("Enchant");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final ItemStack stack = sign.getLine(1).equals("*") || sign.getLine(1).equalsIgnoreCase("any") ? null : getItemStack(sign.getLine(1), 1, ess);
+ final String[] enchantLevel = sign.getLine(2).split(":");
+ if (enchantLevel.length != 2)
+ {
+ throw new SignException(_("invalidSignLine", 3));
+ }
+ final Enchantment enchantment = Enchantments.getByName(enchantLevel[0]);
+ if (enchantment == null)
+ {
+ throw new SignException(_("enchantmentNotFound"));
+ }
+ int level;
+ try
+ {
+ level = Integer.parseInt(enchantLevel[1]);
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ if (level < 1 || level > enchantment.getMaxLevel())
+ {
+ level = enchantment.getMaxLevel();
+ sign.setLine(2, enchantLevel[0] + ":" + level);
+ }
+ try
+ {
+ if (stack != null)
+ {
+ stack.addEnchantment(enchantment, level);
+ }
+ }
+ catch (Throwable ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ getTrade(sign, 3, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(ISign sign, IUser player, String username, IEssentials ess) throws SignException, ChargeException
+ {
+ final ItemStack search = sign.getLine(1).equals("*") || sign.getLine(1).equalsIgnoreCase("any") ? null : getItemStack(sign.getLine(1), 1, ess);
+ int slot = -1;
+ final Trade charge = getTrade(sign, 3, ess);
+ charge.isAffordableFor(player);
+ final String[] enchantLevel = sign.getLine(2).split(":");
+ if (enchantLevel.length != 2)
+ {
+ throw new SignException(_("invalidSignLine", 3));
+ }
+ final Enchantment enchantment = Enchantments.getByName(enchantLevel[0]);
+ if (enchantment == null)
+ {
+ throw new SignException(_("enchantmentNotFound"));
+ }
+ int level;
+ try
+ {
+ level = Integer.parseInt(enchantLevel[1]);
+ }
+ catch (NumberFormatException ex)
+ {
+ level = enchantment.getMaxLevel();
+ }
+
+ final ItemStack playerHand = player.getItemInHand();
+ if (playerHand == null
+ || playerHand.getAmount() != 1
+ || (playerHand.containsEnchantment(enchantment)
+ && playerHand.getEnchantmentLevel(enchantment) == level))
+ {
+ throw new SignException(_("missingItems", 1, sign.getLine(1)));
+ }
+ if (search != null && playerHand.getType() != search.getType())
+ {
+ throw new SignException(_("missingItems", 1, search.getType().toString().toLowerCase(Locale.ENGLISH).replace('_', ' ')));
+ }
+
+ final ItemStack toEnchant = playerHand;
+ try
+ {
+ toEnchant.addEnchantment(enchantment, level);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+
+ charge.charge(player);
+ Trade.log("Sign", "Enchant", "Interact", username, charge, username, charge, sign.getBlock().getLocation(), ess);
+ player.updateInventory();
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignEntityListener.java b/EssentialsSigns/src/net/ess3/signs/SignEntityListener.java
new file mode 100644
index 000000000..1c316478d
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignEntityListener.java
@@ -0,0 +1,80 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentials;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityChangeBlockEvent;
+import org.bukkit.event.entity.EntityExplodeEvent;
+
+
+public class SignEntityListener implements Listener
+{
+ private final transient IEssentials ess;
+ private final transient ISignsPlugin plugin;
+
+ public SignEntityListener(final IEssentials ess, final ISignsPlugin plugin)
+ {
+ this.ess = ess;
+ this.plugin = plugin;
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onEntityExplode(final EntityExplodeEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ for (Block block : event.blockList())
+ {
+ if (((block.getTypeId() == Material.WALL_SIGN.getId()
+ || block.getTypeId() == Material.SIGN_POST.getId())
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType()))
+ {
+ event.setCancelled(!sign.onBlockExplode(block, ess));
+ return;
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onEntityChangeBlock(final EntityChangeBlockEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled())
+ {
+ return;
+ }
+
+ final Block block = event.getBlock();
+ if (((block.getTypeId() == Material.WALL_SIGN.getId()
+ || block.getTypeId() == Material.SIGN_POST.getId())
+ && EssentialsSign.isValidSign(new EssentialsSign.BlockSign(block)))
+ || EssentialsSign.checkIfBlockBreaksSigns(block))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockBreak(block, ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignException.java b/EssentialsSigns/src/net/ess3/signs/SignException.java
new file mode 100644
index 000000000..7ca73e4e5
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignException.java
@@ -0,0 +1,15 @@
+package net.ess3.signs;
+
+
+public class SignException extends Exception
+{
+ public SignException(final String message)
+ {
+ super(message);
+ }
+
+ public SignException(final String message, final Throwable throwable)
+ {
+ super(message, throwable);
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignFree.java b/EssentialsSigns/src/net/ess3/signs/SignFree.java
new file mode 100644
index 000000000..2cf049346
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignFree.java
@@ -0,0 +1,47 @@
+package net.ess3.signs;
+
+import static net.ess3.I18n._;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.craftbukkit.InventoryWorkaround;
+import net.ess3.economy.Trade;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+
+public class SignFree extends EssentialsSign
+{
+ public SignFree()
+ {
+ super("Free");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ getItemStack(sign.getLine(1), 1, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ final ItemStack item = getItemStack(sign.getLine(1), 1, ess);
+ if (item.getType() == Material.AIR)
+ {
+ throw new SignException(_("cantSpawnItem", "Air"));
+ }
+
+ item.setAmount(item.getType().getMaxStackSize());
+ InventoryWorkaround.addItem(player.getInventory(), true, item);
+ player.sendMessage("Item added to your inventory.");
+ player.updateInventory();
+ //TODO: wait for a fix in bukkit
+ //Problem: Items can be duplicated
+ //Inventory i = ess.getServer().createInventory(player, InventoryType.CHEST);
+ //i.addItem(item);
+ //player.openInventory(i);
+ Trade.log("Sign", "Free", "Interact", username, null, username, new Trade(item, ess), sign.getBlock().getLocation(), ess);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignGameMode.java b/EssentialsSigns/src/net/ess3/signs/SignGameMode.java
new file mode 100644
index 000000000..a8ef5a881
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignGameMode.java
@@ -0,0 +1,37 @@
+package net.ess3.signs;
+
+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 java.util.Locale;
+import org.bukkit.GameMode;
+
+
+public class SignGameMode extends EssentialsSign
+{
+ public SignGameMode()
+ {
+ super("GameMode");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 1, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 1, ess);
+ charge.isAffordableFor(player);
+
+ player.setGameMode(player.getGameMode() == GameMode.SURVIVAL ? GameMode.CREATIVE : GameMode.SURVIVAL);
+ player.sendMessage(_("gameMode", _(player.getGameMode().toString().toLowerCase(Locale.ENGLISH)), player.getDisplayName()));
+ charge.charge(player);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignHeal.java b/EssentialsSigns/src/net/ess3/signs/SignHeal.java
new file mode 100644
index 000000000..787e7b166
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignHeal.java
@@ -0,0 +1,36 @@
+package net.ess3.signs;
+
+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;
+
+
+public class SignHeal extends EssentialsSign
+{
+ public SignHeal()
+ {
+ super("Heal");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 1, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 1, ess);
+ charge.isAffordableFor(player);
+ player.setHealth(20);
+ player.setFoodLevel(20);
+ player.setFireTicks(0);
+ player.sendMessage(_("youAreHealed"));
+ charge.charge(player);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignKit.java b/EssentialsSigns/src/net/ess3/signs/SignKit.java
new file mode 100644
index 000000000..9c478ccad
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignKit.java
@@ -0,0 +1,75 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import net.ess3.economy.Trade;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.permissions.KitPermissions;
+import net.ess3.settings.Kit;
+import java.util.Locale;
+
+
+public class SignKit extends EssentialsSign
+{
+ public SignKit()
+ {
+ super("Kit");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 3, ess);
+
+ final String kitName = sign.getLine(1).toLowerCase(Locale.ENGLISH);
+
+ if (kitName.isEmpty())
+ {
+ sign.setLine(1, "§dKit name!");
+ return false;
+ }
+ else
+ {
+ try
+ {
+ ess.getKits().getKit(kitName);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ final String group = sign.getLine(2);
+ if ("Everyone".equalsIgnoreCase(group) || "Everybody".equalsIgnoreCase(group))
+ {
+ sign.setLine(2, "§2Everyone");
+ }
+ return true;
+ }
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final String kitName = sign.getLine(1).toLowerCase(Locale.ENGLISH);
+ final String group = sign.getLine(2);
+ if ((!group.isEmpty() && ("§2Everyone".equals(group) || ess.getRanks().inGroup(player, group)))
+ || (group.isEmpty() && KitPermissions.getPermission(kitName).isAuthorized(player)))
+ {
+ final Trade charge = getTrade(sign, 3, ess);
+ charge.isAffordableFor(player);
+ try
+ {;
+ final Kit kit = ess.getKits().getKit(kitName);
+ ess.getKits().checkTime(player, kit);
+ ess.getKits().sendKit(player, kit);
+ charge.charge(player);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignMail.java b/EssentialsSigns/src/net/ess3/signs/SignMail.java
new file mode 100644
index 000000000..6acf14bb1
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignMail.java
@@ -0,0 +1,41 @@
+package net.ess3.signs;
+
+import static net.ess3.I18n._;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import java.util.List;
+
+
+public class SignMail extends EssentialsSign
+{
+ public SignMail()
+ {
+ super("Mail");
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ final List<String> mail;
+ player.acquireReadLock();
+ try
+ {
+ mail = player.getData().getMails();
+ }
+ finally
+ {
+ player.unlock();
+ }
+ if (mail == null || mail.isEmpty())
+ {
+ player.sendMessage(_("noNewMail"));
+ return false;
+ }
+ for (String s : mail)
+ {
+ player.sendMessage(s);
+ }
+ player.sendMessage(_("markMailAsRead"));
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignPlayerListener.java b/EssentialsSigns/src/net/ess3/signs/SignPlayerListener.java
new file mode 100644
index 000000000..eabf5423b
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignPlayerListener.java
@@ -0,0 +1,65 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentials;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.Sign;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+
+
+public class SignPlayerListener implements Listener
+{
+ private final transient IEssentials ess;
+ private final transient ISignsPlugin plugin;
+
+ public SignPlayerListener(final IEssentials ess, final ISignsPlugin plugin)
+ {
+ this.ess = ess;
+ this.plugin = plugin;
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onPlayerInteract(final PlayerInteractEvent event)
+ {
+ if (plugin.getSettings().areSignsDisabled() || event.getAction() != Action.RIGHT_CLICK_BLOCK)
+ {
+ return;
+ }
+ final Block block = event.getClickedBlock();
+ if (block == null)
+ {
+ return;
+ }
+
+ final int mat = block.getTypeId();
+ if (mat == Material.SIGN_POST.getId() || mat == Material.WALL_SIGN.getId())
+ {
+ final Sign csign = (Sign)block.getState();
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (csign.getLine(0).equalsIgnoreCase(sign.getSuccessName()))
+ {
+ sign.onSignInteract(block, event.getPlayer(), ess);
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (EssentialsSign sign : plugin.getSettings().getEnabledSigns())
+ {
+ if (sign.getBlocks().contains(block.getType())
+ && !sign.onBlockInteract(block, event.getPlayer(), ess))
+ {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignProtection.java b/EssentialsSigns/src/net/ess3/signs/SignProtection.java
new file mode 100644
index 000000000..e87002fd4
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignProtection.java
@@ -0,0 +1,350 @@
+package net.ess3.signs;
+
+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.utils.Util;
+import java.util.*;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.Sign;
+import org.bukkit.inventory.ItemStack;
+
+
+public class SignProtection extends EssentialsSign
+{
+ private final transient Set<Material> protectedBlocks = EnumSet.noneOf(Material.class);
+
+ public SignProtection()
+ {
+ super("Protection");
+ protectedBlocks.add(Material.CHEST);
+ protectedBlocks.add(Material.BURNING_FURNACE);
+ protectedBlocks.add(Material.FURNACE);
+ protectedBlocks.add(Material.DISPENSER);
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ sign.setLine(3, "§4" + username);
+ if (hasAdjacentBlock(sign.getBlock()))
+ {
+ final SignProtectionState state = isBlockProtected(sign.getBlock(), player, username, true, ess);
+ if (state == SignProtectionState.NOSIGN || state == SignProtectionState.OWNER
+ || SignsPermissions.PROTECTION_OVERRIDE.isAuthorized(player))
+ {
+ sign.setLine(3, "§1" + username);
+ return true;
+ }
+ }
+ player.sendMessage(_("signProtectInvalidLocation"));
+ return false;
+ }
+
+ @Override
+ protected boolean onSignBreak(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ final SignProtectionState state = checkProtectionSign(sign, player, username, ess);
+ return state == SignProtectionState.OWNER;
+ }
+
+ public boolean hasAdjacentBlock(final Block block, final Block... ignoredBlocks)
+ {
+ final Block[] faces = getAdjacentBlocks(block);
+ for (Block b : faces)
+ {
+ for (Block ignoredBlock : ignoredBlocks)
+ {
+ if (b.getLocation().equals(ignoredBlock.getLocation()))
+ {
+ continue;
+ }
+ }
+ if (protectedBlocks.contains(b.getType()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void checkIfSignsAreBroken(final Block block, final IUser player, final String username, final IEssentials ess)
+ {
+ final Map<Location, SignProtectionState> signs = getConnectedSigns(block, player, username, false, ess);
+ for (Map.Entry<Location, SignProtectionState> entry : signs.entrySet())
+ {
+ if (entry.getValue() != SignProtectionState.NOSIGN)
+ {
+ final Block sign = entry.getKey().getBlock();
+ if (!hasAdjacentBlock(sign, block))
+ {
+ block.setType(Material.AIR);
+ final Trade trade = new Trade(new ItemStack(Material.SIGN, 1), ess);
+ trade.pay(player);
+ }
+ }
+ }
+ }
+
+ private Map<Location, SignProtectionState> getConnectedSigns(final Block block, final IUser user, final String username, boolean secure, final IEssentials ess)
+ {
+ final Map<Location, SignProtectionState> signs = new HashMap<Location, SignProtectionState>();
+ getConnectedSigns(block, signs, user, username, secure ? 4 : 2, ess);
+ return signs;
+ }
+
+ private void getConnectedSigns(final Block block, final Map<Location, SignProtectionState> signs, final IUser user, final String username, final int depth, final IEssentials ess)
+ {
+ final Block[] faces = getAdjacentBlocks(block);
+ for (Block b : faces)
+ {
+ final Location loc = b.getLocation();
+ if (signs.containsKey(loc))
+ {
+ continue;
+ }
+ final SignProtectionState check = checkProtectionSign(b, user, username, ess);
+ signs.put(loc, check);
+
+ if (protectedBlocks.contains(b.getType()) && depth > 0)
+ {
+ getConnectedSigns(b, signs, user, username, depth - 1, ess);
+ }
+ }
+ }
+
+
+ public enum SignProtectionState
+ {
+ NOT_ALLOWED, ALLOWED, NOSIGN, OWNER
+ }
+
+ private SignProtectionState checkProtectionSign(final Block block, final IUser user, final String username, final IEssentials ess)
+ {
+ if (block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN)
+ {
+ final BlockSign sign = new BlockSign(block);
+ if (sign.getLine(0).equals(this.getSuccessName()))
+ {
+ return checkProtectionSign(sign, user, username, ess);
+ }
+ }
+ return SignProtectionState.NOSIGN;
+ }
+
+ private SignProtectionState checkProtectionSign(final ISign sign, final IUser user, final String username, final IEssentials ess)
+ {
+ if (user == null || username == null)
+ {
+ return SignProtectionState.NOT_ALLOWED;
+ }
+ if (SignsPermissions.PROTECTION_OVERRIDE.isAuthorized(user))
+ {
+ return SignProtectionState.OWNER;
+ }
+ if (Util.stripFormat(sign.getLine(3)).equalsIgnoreCase(username))
+ {
+ return SignProtectionState.OWNER;
+ }
+ for (int i = 1; i <= 2; i++)
+ {
+ final String line = sign.getLine(i);
+ if (line.startsWith("(") && line.endsWith(")") && ess.getRanks().inGroup(user, line.substring(1, line.length() - 1)))
+ {
+ return SignProtectionState.ALLOWED;
+ }
+ else if (line.equalsIgnoreCase(username))
+ {
+ return SignProtectionState.ALLOWED;
+ }
+ }
+ return SignProtectionState.NOT_ALLOWED;
+ }
+
+ private Block[] getAdjacentBlocks(final Block block)
+ {
+ return new Block[]
+ {
+ block.getRelative(BlockFace.NORTH),
+ block.getRelative(BlockFace.SOUTH),
+ block.getRelative(BlockFace.EAST),
+ block.getRelative(BlockFace.WEST),
+ block.getRelative(BlockFace.DOWN),
+ block.getRelative(BlockFace.UP)
+ };
+ }
+
+ public SignProtectionState isBlockProtected(final Block block, final IUser user, final String username, boolean secure, final IEssentials ess)
+ {
+ final Map<Location, SignProtectionState> signs = getConnectedSigns(block, user, username, secure, ess);
+ SignProtectionState retstate = SignProtectionState.NOSIGN;
+ for (SignProtectionState state : signs.values())
+ {
+ if (state == SignProtectionState.ALLOWED)
+ {
+ retstate = state;
+ }
+ else if (state == SignProtectionState.NOT_ALLOWED && retstate != SignProtectionState.ALLOWED)
+ {
+ retstate = state;
+ }
+ }
+ if (!secure || retstate == SignProtectionState.NOSIGN)
+ {
+ for (SignProtectionState state : signs.values())
+ {
+ if (state == SignProtectionState.OWNER)
+ {
+ return state;
+ }
+ }
+ }
+ return retstate;
+ }
+
+ public boolean isBlockProtected(final Block block)
+ {
+ final Block[] faces = getAdjacentBlocks(block);
+ for (Block b : faces)
+ {
+ if (b.getType() == Material.SIGN_POST || b.getType() == Material.WALL_SIGN)
+ {
+ final Sign sign = (Sign)b.getState();
+ if (sign.getLine(0).equalsIgnoreCase("§1[Protection]"))
+ {
+ return true;
+ }
+ }
+ if (protectedBlocks.contains(b.getType()))
+ {
+ final Block[] faceChest = getAdjacentBlocks(b);
+
+ for (Block a : faceChest)
+ {
+ if (a.getType() == Material.SIGN_POST || a.getType() == Material.WALL_SIGN)
+ {
+ final Sign sign = (Sign)a.getState();
+ if (sign.getLine(0).equalsIgnoreCase("§1[Protection]"))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Set<Material> getBlocks()
+ {
+ return protectedBlocks;
+ }
+
+ @Override
+ protected boolean onBlockPlace(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ for (Block adjBlock : getAdjacentBlocks(block))
+ {
+ final SignProtectionState state = isBlockProtected(adjBlock, player, username, true, ess);
+
+ if ((state == SignProtectionState.ALLOWED || state == SignProtectionState.NOT_ALLOWED)
+ && !SignsPermissions.PROTECTION_OVERRIDE.isAuthorized(player))
+ {
+ player.sendMessage(_("noPlacePermission", block.getType().toString().toLowerCase(Locale.ENGLISH)));
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ @Override
+ protected boolean onBlockInteract(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ final SignProtectionState state = isBlockProtected(block, player, username, false, ess);
+
+ if (state == SignProtectionState.OWNER || state == SignProtectionState.NOSIGN || state == SignProtectionState.ALLOWED)
+ {
+ return true;
+ }
+
+ if (state == SignProtectionState.NOT_ALLOWED
+ && SignsPermissions.PROTECTION_OVERRIDE.isAuthorized(player))
+ {
+ return true;
+ }
+
+
+ player.sendMessage(_("noAccessPermission", block.getType().toString().toLowerCase(Locale.ENGLISH)));
+ return false;
+ }
+
+ @Override
+ protected boolean onBlockBreak(final Block block, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ final SignProtectionState state = isBlockProtected(block, player, username, false, ess);
+
+ if (state == SignProtectionState.OWNER || state == SignProtectionState.NOSIGN)
+ {
+ checkIfSignsAreBroken(block, player, username, ess);
+ return true;
+ }
+
+ if ((state == SignProtectionState.ALLOWED || state == SignProtectionState.NOT_ALLOWED)
+ && SignsPermissions.PROTECTION_OVERRIDE.isAuthorized(player))
+ {
+ checkIfSignsAreBroken(block, player, username, ess);
+ return true;
+ }
+
+
+ player.sendMessage(_("noDestroyPermission", block.getType().toString().toLowerCase(Locale.ENGLISH)));
+ return false;
+ }
+
+ @Override
+ public boolean onBlockBreak(final Block block, final IEssentials ess)
+ {
+ final SignProtectionState state = isBlockProtected(block, null, null, false, ess);
+
+ return state == SignProtectionState.NOSIGN;
+ }
+
+ @Override
+ public boolean onBlockExplode(final Block block, final IEssentials ess)
+ {
+ final SignProtectionState state = isBlockProtected(block, null, null, false, ess);
+
+ return state == SignProtectionState.NOSIGN;
+ }
+
+ @Override
+ public boolean onBlockBurn(final Block block, final IEssentials ess)
+ {
+ final SignProtectionState state = isBlockProtected(block, null, null, false, ess);
+
+ return state == SignProtectionState.NOSIGN;
+ }
+
+ @Override
+ public boolean onBlockIgnite(final Block block, final IEssentials ess)
+ {
+ final SignProtectionState state = isBlockProtected(block, null, null, false, ess);
+
+ return state == SignProtectionState.NOSIGN;
+ }
+
+ @Override
+ public boolean onBlockPush(final Block block, final IEssentials ess)
+ {
+ final SignProtectionState state = isBlockProtected(block, null, null, false, ess);
+
+ return state == SignProtectionState.NOSIGN;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignSell.java b/EssentialsSigns/src/net/ess3/signs/SignSell.java
new file mode 100644
index 000000000..9a48e4948
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignSell.java
@@ -0,0 +1,35 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.economy.Trade;
+
+
+public class SignSell extends EssentialsSign
+{
+ public SignSell()
+ {
+ super("Sell");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 1, 2, player, ess);
+ validateTrade(sign, 3, ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 1, 2, player, ess);
+ final Trade money = getTrade(sign, 3, ess);
+ charge.isAffordableFor(player);
+ money.pay(player);
+ charge.charge(player);
+ Trade.log("Sign", "Sell", "Interact", username, charge, username, money, sign.getBlock().getLocation(), ess);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignSpawnmob.java b/EssentialsSigns/src/net/ess3/signs/SignSpawnmob.java
new file mode 100644
index 000000000..47961a96e
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignSpawnmob.java
@@ -0,0 +1,48 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.commands.Commandspawnmob;
+import net.ess3.economy.Trade;
+
+
+public class SignSpawnmob extends EssentialsSign
+{
+ public SignSpawnmob()
+ {
+ super("Spawnmob");
+ }
+
+ @Override
+ protected boolean onSignCreate(ISign sign, IUser player, String username, IEssentials ess) throws SignException, ChargeException
+ {
+ validateInteger(sign, 1);
+ validateTrade(sign, 3, ess);
+ return true;
+ }
+
+ //TODO: This should call a method not a command
+ @Override
+ protected boolean onSignInteract(ISign sign, IUser player, String username, IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 3, ess);
+ charge.isAffordableFor(player);
+ Commandspawnmob command = new Commandspawnmob();
+ command.init(ess, "spawnmob");
+ String[] args = new String[]
+ {
+ sign.getLine(2), sign.getLine(1)
+ };
+ try
+ {
+ command.run(player, "spawnmob", args);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ charge.charge(player);
+ return true;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignTime.java b/EssentialsSigns/src/net/ess3/signs/SignTime.java
new file mode 100644
index 000000000..8ef98a4d5
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignTime.java
@@ -0,0 +1,57 @@
+package net.ess3.signs;
+
+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;
+
+
+public class SignTime extends EssentialsSign
+{
+ public SignTime()
+ {
+ super("Time");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 2, ess);
+ final String timeString = sign.getLine(1);
+ if ("Day".equalsIgnoreCase(timeString))
+ {
+ sign.setLine(1, "§2Day");
+ return true;
+ }
+ if ("Night".equalsIgnoreCase(timeString))
+ {
+ sign.setLine(1, "§2Night");
+ return true;
+ }
+ throw new SignException(_("onlyDayNight"));
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 2, ess);
+ charge.isAffordableFor(player);
+ final String timeString = sign.getLine(1);
+ long time = player.getWorld().getTime();
+ time -= time % 24000;
+ if ("§2Day".equalsIgnoreCase(timeString))
+ {
+ player.getWorld().setTime(time + 24000);
+ charge.charge(player);
+ return true;
+ }
+ if ("§2Night".equalsIgnoreCase(timeString))
+ {
+ player.getWorld().setTime(time + 37700);
+ charge.charge(player);
+ return true;
+ }
+ throw new SignException(_("onlyDayNight"));
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignTrade.java b/EssentialsSigns/src/net/ess3/signs/SignTrade.java
new file mode 100644
index 000000000..c3e78e226
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignTrade.java
@@ -0,0 +1,361 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import static net.ess3.I18n._;
+import net.ess3.economy.Trade;
+import net.ess3.utils.Util;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import org.bukkit.inventory.ItemStack;
+
+//TODO: Sell Enchantment on Trade signs?
+public class SignTrade extends EssentialsSign
+{
+
+ public SignTrade()
+ {
+ super("Trade");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ validateTrade(sign, 1, false, ess);
+ validateTrade(sign, 2, true, ess);
+ final Trade charge = getTrade(sign, 2, true, true, ess);
+ charge.isAffordableFor(player);
+ sign.setLine(3, "§8" + username);
+ charge.charge(player);
+ Trade.log("Sign", "Trade", "Create", username, charge, username, null, sign.getBlock().getLocation(), ess);
+ return true;
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ if (sign.getLine(3).substring(2).equalsIgnoreCase(username))
+ {
+ final Trade store = rechargeSign(sign, ess, player);
+ Trade stored = null;
+ try
+ {
+ stored = getTrade(sign, 1, true, true, ess);
+ subtractAmount(sign, 1, stored, ess);
+ stored.pay(player);
+ }
+ catch (SignException e)
+ {
+ if (store == null)
+ {
+ throw new SignException(_("tradeSignEmptyOwner"), e);
+ }
+ }
+ Trade.log("Sign", "Trade", "OwnerInteract", username, store, username, stored, sign.getBlock().getLocation(), ess);
+ }
+ else
+ {
+ final Trade charge = getTrade(sign, 1, false, false, ess);
+ final Trade trade = getTrade(sign, 2, false, true, ess);
+ charge.isAffordableFor(player);
+ addAmount(sign, 1, charge, ess);
+ subtractAmount(sign, 2, trade, ess);
+ if (!trade.pay(player, false))
+ {
+ subtractAmount(sign, 1, charge, ess);
+ addAmount(sign, 2, trade, ess);
+ throw new ChargeException("Full inventory");
+ }
+ charge.charge(player);
+ Trade.log("Sign", "Trade", "Interact", sign.getLine(3), charge, username, trade, sign.getBlock().getLocation(), ess);
+ }
+ sign.updateSign();
+ return true;
+ }
+
+ private Trade rechargeSign(final ISign sign, final IEssentials ess, final IUser player) throws SignException, ChargeException
+ {
+ final Trade trade = getTrade(sign, 2, false, false, ess);
+ if (trade.getItemStack() != null && player.getItemInHand() != null
+ && trade.getItemStack().getTypeId() == player.getItemInHand().getTypeId()
+ && trade.getItemStack().getDurability() == player.getItemInHand().getDurability()
+ && trade.getItemStack().getEnchantments().equals(player.getItemInHand().getEnchantments()))
+ {
+ int amount = player.getItemInHand().getAmount();
+ amount -= amount % trade.getItemStack().getAmount();
+ if (amount > 0)
+ {
+ final ItemStack stack = player.getItemInHand().clone();
+ stack.setAmount(amount);
+ final Trade store = new Trade(stack, ess);
+ addAmount(sign, 2, store, ess);
+ store.charge(player);
+ return store;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean onSignBreak(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ if ((sign.getLine(3).length() > 3 && sign.getLine(3).substring(2).equalsIgnoreCase(username))
+ || SignsPermissions.TRADE_OVERRIDE.isAuthorized(player))
+ {
+ 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);
+ }
+ catch (SignException e)
+ {
+ if (SignsPermissions.TRADE_OVERRIDE.isAuthorized(player))
+ {
+ return true;
+ }
+ throw e;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ protected final void validateTrade(final ISign sign, final int index, final boolean amountNeeded, 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 == 1 && !amountNeeded)
+ {
+ final Double money = getMoney(split[0]);
+ if (money != null)
+ {
+ if (Util.shortCurrency(money, ess).length() * 2 > 15)
+ {
+ throw new SignException("Line can be too long!");
+ }
+ sign.setLine(index, Util.shortCurrency(money, ess) + ":0");
+ return;
+ }
+ }
+
+ if (split.length == 2 && amountNeeded)
+ {
+ final Double money = getMoney(split[0]);
+ Double amount = getDoublePositive(split[1]);
+ if (money != null && amount != null)
+ {
+ amount -= amount % money;
+ if (amount < 0.01 || money < 0.01)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ sign.setLine(index, Util.shortCurrency(money, ess) + ":" + Util.shortCurrency(amount, ess).substring(1));
+ return;
+ }
+ }
+
+ if (split.length == 2 && !amountNeeded)
+ {
+ final int amount = getIntegerPositive(split[0]);
+
+ if (amount < 1)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ if (!(split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp"))
+ && getItemStack(split[1], amount, ess).getTypeId() == 0)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ String newline = amount + " " + split[1] + ":0";
+ if ((newline + amount).length() > 15)
+ {
+ throw new SignException("Line can be too long!");
+ }
+ sign.setLine(index, newline);
+ return;
+ }
+
+ if (split.length == 3 && amountNeeded)
+ {
+ final int stackamount = getIntegerPositive(split[0]);
+ int amount = getIntegerPositive(split[2]);
+ amount -= amount % stackamount;
+ if (amount < 1 || stackamount < 1)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ if (!(split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp"))
+ && getItemStack(split[1], stackamount, ess).getTypeId() == 0)
+ {
+ throw new SignException(_("moreThanZero"));
+ }
+ sign.setLine(index, stackamount + " " + split[1] + ":" + amount);
+ return;
+ }
+ 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
+ {
+ final String line = sign.getLine(index).trim();
+ if (line.isEmpty())
+ {
+ throw new SignException("Empty line");
+ }
+ final String[] split = line.split("[ :]+");
+
+ if (split.length == 2)
+ {
+ try
+ {
+ final Double money = getMoney(split[0]);
+ final Double amount = notEmpty ? getDoublePositive(split[1]) : getDouble(split[1]);
+ if (money != null && amount != null)
+ {
+ return new Trade(fullAmount ? amount : money, ess);
+ }
+ }
+ catch (SignException e)
+ {
+ throw new SignException(_("tradeSignEmpty"), e);
+ }
+ }
+
+ if (split.length == 3)
+ {
+ if (split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp"))
+ {
+ final int stackamount = getIntegerPositive(split[0]);
+ int amount = getInteger(split[2]);
+ amount -= amount % stackamount;
+ if (notEmpty && (amount < 1 || stackamount < 1))
+ {
+ throw new SignException(_("tradeSignEmpty"));
+ }
+ return new Trade(fullAmount ? amount : stackamount, 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 (notEmpty && (amount < 1 || stackamount < 1 || item.getTypeId() == 0))
+ {
+ throw new SignException(_("tradeSignEmpty"));
+ }
+ item.setAmount(fullAmount ? amount : stackamount);
+ return new Trade(item, ess);
+ }
+ }
+ throw new SignException(_("invalidSignLine", index + 1));
+ }
+
+ protected final void subtractAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException
+ {
+ final Double money = trade.getMoney();
+ if (money != null)
+ {
+ changeAmount(sign, index, -money, ess);
+ }
+ final ItemStack item = trade.getItemStack();
+ if (item != null)
+ {
+ changeAmount(sign, index, -item.getAmount(), ess);
+ }
+ final Integer exp = trade.getExperience();
+ if (exp != null)
+ {
+ changeAmount(sign, index, -exp.intValue(), ess);
+ }
+ }
+
+ protected final void addAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException
+ {
+ final Double money = trade.getMoney();
+ if (money != null)
+ {
+ changeAmount(sign, index, money, ess);
+ }
+ final ItemStack item = trade.getItemStack();
+ if (item != null)
+ {
+ changeAmount(sign, index, item.getAmount(), ess);
+ }
+ final Integer exp = trade.getExperience();
+ if (exp != null)
+ {
+ changeAmount(sign, index, exp.intValue(), ess);
+ }
+ }
+
+ //TODO: Translate these exceptions.
+ private void changeAmount(final ISign sign, final int index, final double 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 Double money = getMoney(split[0]);
+ final Double amount = getDouble(split[1]);
+ if (money != null && amount != null)
+ {
+ final String newline = Util.shortCurrency(money, ess) + ":" + Util.shortCurrency(amount + value, ess).substring(1);
+ if (newline.length() > 15)
+ {
+ throw new SignException("This sign is full: Line too long!");
+ }
+ sign.setLine(index, newline);
+ return;
+ }
+ }
+
+ if (split.length == 3)
+ {
+ 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 + Math.round(value));
+ if (newline.length() > 15)
+ {
+ throw new SignException("This sign is full: Line too long!");
+ }
+ sign.setLine(index, newline);
+ return;
+ }
+ 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 + Math.round(value));
+ if (newline.length() > 15)
+ {
+ throw new SignException("This sign is full: Line too long!");
+ }
+ sign.setLine(index, newline);
+ return;
+ }
+ }
+ throw new SignException(_("invalidSignLine", index + 1));
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignWarp.java b/EssentialsSigns/src/net/ess3/signs/SignWarp.java
new file mode 100644
index 000000000..b6dc95d0f
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignWarp.java
@@ -0,0 +1,70 @@
+package net.ess3.signs;
+
+import net.ess3.api.ChargeException;
+import net.ess3.api.IEssentials;
+import net.ess3.api.IUser;
+import net.ess3.economy.Trade;
+import net.ess3.permissions.WarpPermissions;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+
+
+public class SignWarp extends EssentialsSign
+{
+ public SignWarp()
+ {
+ super("Warp");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 3, ess);
+ final String warpName = sign.getLine(1);
+
+ if (warpName.isEmpty())
+ {
+ sign.setLine(1, "§dWarp name!");
+ return false;
+ }
+ else
+ {
+ try
+ {
+ ess.getWarps().getWarp(warpName);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ final String group = sign.getLine(2);
+ if ("Everyone".equalsIgnoreCase(group) || "Everybody".equalsIgnoreCase(group))
+ {
+ sign.setLine(2, "§2Everyone");
+ }
+ return true;
+ }
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final String warpName = sign.getLine(1);
+ final String group = sign.getLine(2);
+
+ if ((!group.isEmpty() && ("§2Everyone".equals(group) || ess.getRanks().inGroup(player, group)))
+ || (group.isEmpty() && WarpPermissions.getPermission(warpName).isAuthorized(player)))
+ {
+ final Trade charge = getTrade(sign, 3, ess);
+ try
+ {
+ player.getTeleport().warp(warpName, charge, TeleportCause.PLUGIN);
+ }
+ catch (Exception ex)
+ {
+ throw new SignException(ex.getMessage(), ex);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignWeather.java b/EssentialsSigns/src/net/ess3/signs/SignWeather.java
new file mode 100644
index 000000000..94217aeec
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignWeather.java
@@ -0,0 +1,55 @@
+package net.ess3.signs;
+
+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;
+
+
+public class SignWeather extends EssentialsSign
+{
+ public SignWeather()
+ {
+ super("Weather");
+ }
+
+ @Override
+ protected boolean onSignCreate(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException
+ {
+ validateTrade(sign, 2, ess);
+ final String timeString = sign.getLine(1);
+ if ("Sun".equalsIgnoreCase(timeString))
+ {
+ sign.setLine(1, "§2Sun");
+ return true;
+ }
+ if ("Storm".equalsIgnoreCase(timeString))
+ {
+ sign.setLine(1, "§2Storm");
+ return true;
+ }
+ throw new SignException(_("onlySunStorm"));
+ }
+
+ @Override
+ protected boolean onSignInteract(final ISign sign, final IUser player, final String username, final IEssentials ess) throws SignException, ChargeException
+ {
+ final Trade charge = getTrade(sign, 2, ess);
+ charge.isAffordableFor(player);
+ final String weatherString = sign.getLine(1);
+ if ("§2Sun".equalsIgnoreCase(weatherString))
+ {
+ player.getWorld().setStorm(false);
+ charge.charge(player);
+ return true;
+ }
+ if ("§2Storm".equalsIgnoreCase(weatherString))
+ {
+ player.getWorld().setStorm(true);
+ charge.charge(player);
+ return true;
+ }
+ throw new SignException(_("onlySunStorm"));
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/Signs.java b/EssentialsSigns/src/net/ess3/signs/Signs.java
new file mode 100644
index 000000000..af4111dac
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/Signs.java
@@ -0,0 +1,33 @@
+package net.ess3.signs;
+
+
+public enum Signs
+{
+ BALANCE(new SignBalance()),
+ BUY(new SignBuy()),
+ DISPOSAL(new SignDisposal()),
+ ENCHANT(new SignEnchant()),
+ FREE(new SignFree()),
+ GAMEMODE(new SignGameMode()),
+ HEAL(new SignHeal()),
+ KIT(new SignKit()),
+ MAIL(new SignMail()),
+ PROTECTION(new SignProtection()),
+ SELL(new SignSell()),
+ SPAWNMOB(new SignSpawnmob()),
+ TIME(new SignTime()),
+ TRADE(new SignTrade()),
+ WARP(new SignWarp()),
+ WEATHER(new SignWeather());
+ private final EssentialsSign sign;
+
+ private Signs(final EssentialsSign sign)
+ {
+ this.sign = sign;
+ }
+
+ public EssentialsSign getSign()
+ {
+ return sign;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignsConfig.java b/EssentialsSigns/src/net/ess3/signs/SignsConfig.java
new file mode 100644
index 000000000..70b606962
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignsConfig.java
@@ -0,0 +1,21 @@
+package net.ess3.signs;
+
+import net.ess3.storage.StorageObject;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class SignsConfig implements StorageObject
+{
+ private Map<String, Boolean> signs = new HashMap<String, Boolean>();
+
+ public Map<String, Boolean> getSigns()
+ {
+ return signs;
+ }
+
+ public void setSigns(final Map<String, Boolean> signs)
+ {
+ this.signs = signs;
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignsConfigHolder.java b/EssentialsSigns/src/net/ess3/signs/SignsConfigHolder.java
new file mode 100644
index 000000000..395d0194a
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignsConfigHolder.java
@@ -0,0 +1,85 @@
+package net.ess3.signs;
+
+import net.ess3.api.IEssentials;
+import net.ess3.storage.AsyncStorageObjectHolder;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import org.bukkit.plugin.Plugin;
+
+
+public class SignsConfigHolder extends AsyncStorageObjectHolder<SignsConfig>
+{
+ private final transient Plugin plugin;
+ private Set<EssentialsSign> enabledSigns = new HashSet<EssentialsSign>();
+ private boolean signsEnabled = false;
+
+ public SignsConfigHolder(final IEssentials ess, final Plugin plugin)
+ {
+ super(ess, SignsConfig.class);
+ this.plugin = plugin;
+ onReload();
+ acquireReadLock();
+ try
+ {
+ final Map<String, Boolean> signs = getData().getSigns();
+ for (Map.Entry<String, Boolean> entry : signs.entrySet())
+ {
+ if (entry.getKey().trim().toUpperCase(Locale.ENGLISH).equals("COLOR") || entry.getKey().trim().toUpperCase(Locale.ENGLISH).equals("COLOUR"))
+ {
+ signsEnabled = true;
+ continue;
+ }
+ final Signs sign = Signs.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
+ if (sign != null && entry.getValue())
+ {
+ enabledSigns.add(sign.getSign());
+ }
+ }
+ }
+ finally
+ {
+ unlock();
+ }
+ acquireWriteLock();
+ try
+ {
+ final Map<String, Boolean> signs = new HashMap<String, Boolean>();
+ for (Signs sign : Signs.values())
+ {
+ signs.put(sign.toString(), enabledSigns.contains(sign.getSign()));
+ }
+ getData().setSigns(signs);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ public File getStorageFile() throws IOException
+ {
+ return new File(plugin.getDataFolder(), "config.yml");
+ }
+
+ public Set<EssentialsSign> getEnabledSigns()
+ {
+ return enabledSigns;
+ }
+
+ public boolean areSignsDisabled()
+ {
+ return !signsEnabled;
+ }
+
+ @Override
+ public void finishRead()
+ {
+ }
+
+ @Override
+ public void finishWrite()
+ {
+ }
+}
diff --git a/EssentialsSigns/src/net/ess3/signs/SignsPermissions.java b/EssentialsSigns/src/net/ess3/signs/SignsPermissions.java
new file mode 100644
index 000000000..21c736b7d
--- /dev/null
+++ b/EssentialsSigns/src/net/ess3/signs/SignsPermissions.java
@@ -0,0 +1,51 @@
+package net.ess3.signs;
+
+import net.ess3.api.IPermission;
+import net.ess3.permissions.BasePermission;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+
+public class SignsPermissions
+{
+ public static final IPermission COLOR = new BasePermission("essentials.signs.", "color");
+ public static final IPermission PROTECTION_OVERRIDE = new BasePermission("essentials.signs.protection.", "override");
+ public static final IPermission TRADE_OVERRIDE = new BasePermission("essentials.signs.trade.", "override");
+ private static Map<String, IPermission> createpermissions = new HashMap<String, IPermission>();
+
+ public static IPermission getCreatePermission(final String signName)
+ {
+ IPermission perm = createpermissions.get(signName);
+ if (perm == null)
+ {
+ perm = new BasePermission("essentials.signs.create.", signName.toLowerCase(Locale.ENGLISH));
+ createpermissions.put(signName, perm);
+ }
+ return perm;
+ }
+ private static Map<String, IPermission> usepermissions = new HashMap<String, IPermission>();
+
+ public static IPermission getUsePermission(final String signName)
+ {
+ IPermission perm = usepermissions.get(signName);
+ if (perm == null)
+ {
+ perm = new BasePermission("essentials.signs.use.", signName.toLowerCase(Locale.ENGLISH));
+ usepermissions.put(signName, perm);
+ }
+ return perm;
+ }
+ private static Map<String, IPermission> breakpermissions = new HashMap<String, IPermission>();
+
+ public static IPermission getBreakPermission(final String signName)
+ {
+ IPermission perm = breakpermissions.get(signName);
+ if (perm == null)
+ {
+ perm = new BasePermission("essentials.signs.break.", signName.toLowerCase(Locale.ENGLISH));
+ breakpermissions.put(signName, perm);
+ }
+ return perm;
+ }
+}