Protection signs and

new Listeners for the signs
This commit is contained in:
snowleo 2011-06-26 15:31:13 +02:00
parent 512a1b9183
commit 3b9a07e560
9 changed files with 688 additions and 16 deletions

View File

@ -6,19 +6,24 @@ import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.ItemDb; import com.earth2me.essentials.ItemDb;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.Util; import com.earth2me.essentials.Util;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.craftbukkit.block.CraftSign; import org.bukkit.craftbukkit.block.CraftSign;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class EssentialsSign public class EssentialsSign
{ {
private static final Set<Material> EMPTY_SET = new HashSet<Material>();
protected transient final String signName; protected transient final String signName;
private static final String FORMAT_SUCCESS = "§1[%s]"; private static final String FORMAT_SUCCESS = "§1[%s]";
private static final String FORMAT_TEMPLATE = "[%s]";
private static final String FORMAT_FAIL = "§4[%s]"; private static final String FORMAT_FAIL = "§4[%s]";
public EssentialsSign(final String signName) public EssentialsSign(final String signName)
@ -41,7 +46,7 @@ public class EssentialsSign
final boolean ret = onSignCreate(sign, user, getUsername(user), ess); final boolean ret = onSignCreate(sign, user, getUsername(user), ess);
if (ret) if (ret)
{ {
sign.setLine(0, String.format(FORMAT_SUCCESS, this.signName)); sign.setLine(0, getSuccessName());
} }
return ret; return ret;
} }
@ -56,15 +61,25 @@ public class EssentialsSign
return false; return false;
} }
public String getSuccessName()
{
return String.format(FORMAT_SUCCESS, this.signName);
}
public String getTemplateName()
{
return String.format(FORMAT_TEMPLATE, this.signName);
}
private String getUsername(final User user) private String getUsername(final User user)
{ {
return user.getName().substring(0, user.getName().length() > 14 ? 14 : user.getName().length()); return user.getName().substring(0, user.getName().length() > 14 ? 14 : user.getName().length());
} }
public final boolean onSignInteract(final PlayerInteractEvent event, final IEssentials ess) public final boolean onSignInteract(final Block block, final Player player, final IEssentials ess)
{ {
final ISign sign = new BlockSign(event.getClickedBlock()); final ISign sign = new BlockSign(block);
final User user = ess.getUser(event.getPlayer()); final User user = ess.getUser(player);
try try
{ {
return (user.isAuthorized("essentials.signs." + signName.toLowerCase() + ".use") return (user.isAuthorized("essentials.signs." + signName.toLowerCase() + ".use")
@ -83,10 +98,10 @@ public class EssentialsSign
} }
} }
public final boolean onSignBreak(final BlockBreakEvent event, final IEssentials ess) public final boolean onSignBreak(final Block block, final Player player, final IEssentials ess)
{ {
final ISign sign = new BlockSign(event.getBlock()); final ISign sign = new BlockSign(block);
final User user = ess.getUser(event.getPlayer()); final User user = ess.getUser(player);
try try
{ {
return (user.isAuthorized("essentials.signs." + signName.toLowerCase() + ".break") return (user.isAuthorized("essentials.signs." + signName.toLowerCase() + ".break")
@ -115,6 +130,114 @@ public class EssentialsSign
return true; return true;
} }
public final boolean onBlockPlace(final Block block, final Player player, final IEssentials ess)
{
User user = ess.getUser(player);
try
{
return onBlockPlace(block, user, getUsername(user), ess);
}
catch (ChargeException ex)
{
ess.showError(user, ex, signName);
}
catch (SignException ex)
{
ess.showError(user, ex, signName);
}
return false;
}
public final boolean onBlockInteract(final Block block, final Player player, final IEssentials ess)
{
User user = ess.getUser(player);
try
{
return onBlockInteract(block, user, getUsername(user), ess);
}
catch (ChargeException ex)
{
ess.showError(user, ex, signName);
}
catch (SignException ex)
{
ess.showError(user, ex, signName);
}
return false;
}
public final boolean onBlockBreak(final Block block, final Player player, final IEssentials ess)
{
User user = ess.getUser(player);
try
{
return onBlockBreak(block, user, getUsername(user), ess);
}
catch (SignException ex)
{
ess.showError(user, ex, signName);
}
return false;
}
public boolean onBlockExplode(final Block block, final IEssentials ess)
{
return true;
}
public boolean onBlockBurn(final Block block, final IEssentials ess)
{
return true;
}
public static boolean checkIfBlockBreaksSigns(final Block block)
{
if (block.getFace(BlockFace.UP).getType() == Material.SIGN_POST)
{
return false;
}
final BlockFace[] directions = new BlockFace[]
{
BlockFace.NORTH,
BlockFace.EAST,
BlockFace.SOUTH,
BlockFace.WEST
};
for (BlockFace blockFace : directions)
{
final Block signblock = block.getFace(blockFace);
if (signblock.getType() == Material.WALL_SIGN)
{
final org.bukkit.material.Sign sign = (org.bukkit.material.Sign)signblock.getState().getData();
if (sign.getFacing() == blockFace)
{
return false;
}
}
}
return true;
}
protected boolean onBlockPlace(final Block block, final User player, final String username, final IEssentials ess) throws SignException, ChargeException
{
return true;
}
protected boolean onBlockInteract(final Block block, final User player, final String username, final IEssentials ess) throws SignException, ChargeException
{
return true;
}
protected boolean onBlockBreak(final Block block, final User 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 protected final void validateTrade(final ISign sign, final int index, final IEssentials ess) throws SignException
{ {
final String line = sign.getLine(index).trim(); final String line = sign.getLine(index).trim();
@ -130,8 +253,6 @@ public class EssentialsSign
} }
} }
protected final void validateTrade(final ISign sign, final int amountIndex, final int itemIndex, protected final void validateTrade(final ISign sign, final int amountIndex, final int itemIndex,
final User player, final IEssentials ess) throws SignException final User player, final IEssentials ess) throws SignException
{ {
@ -266,10 +387,12 @@ public class EssentialsSign
static class EventSign implements ISign static class EventSign implements ISign
{ {
private final transient SignChangeEvent event; private final transient SignChangeEvent event;
private final transient Block block;
public EventSign(final SignChangeEvent event) public EventSign(final SignChangeEvent event)
{ {
this.event = event; this.event = event;
this.block = event.getBlock();
} }
public final String getLine(final int index) public final String getLine(final int index)
@ -281,15 +404,22 @@ public class EssentialsSign
{ {
event.setLine(index, text); event.setLine(index, text);
} }
public Block getBlock()
{
return block;
}
} }
static class BlockSign implements ISign static class BlockSign implements ISign
{ {
private final transient Sign sign; private final transient Sign sign;
private final transient Block block;
public BlockSign(final Block block) public BlockSign(final Block block)
{ {
this.block = block;
this.sign = new CraftSign(block); this.sign = new CraftSign(block);
} }
@ -302,6 +432,11 @@ public class EssentialsSign
{ {
sign.setLine(index, text); sign.setLine(index, text);
} }
public final Block getBlock()
{
return block;
}
} }
@ -310,5 +445,7 @@ public class EssentialsSign
String getLine(final int index); String getLine(final int index);
void setLine(final int index, final String text); void setLine(final int index, final String text);
public Block getBlock();
} }
} }

View File

@ -0,0 +1,133 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.IEssentials;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.craftbukkit.block.CraftSign;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.SignChangeEvent;
public class SignBlockListener extends BlockListener
{
private final transient IEssentials ess;
public SignBlockListener(IEssentials ess)
{
this.ess = ess;
}
@Override
public void onBlockBreak(final BlockBreakEvent event)
{
if (event.isCancelled() || ess.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 == Material.SIGN_POST.getId() || mat == Material.WALL_SIGN.getId())
{
final Sign csign = new CraftSign(block);
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (csign.getLine(0).equalsIgnoreCase(sign.getSuccessName())
&& !sign.onSignBreak(block, player, ess))
{
return true;
}
}
}
else
{
// prevent any signs be broken by destroying the block they are attached to
if (EssentialsSign.checkIfBlockBreaksSigns(block))
{
return true;
}
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (sign.getBlocks().contains(block.getType())
&& !sign.onBlockBreak(block, player, ess))
{
return true;
}
}
}
return false;
}
@Override
public void onSignChange(final SignChangeEvent event)
{
if (event.isCancelled() || ess.getSettings().areSignsDisabled())
{
return;
}
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (event.getLine(0).equalsIgnoreCase(sign.getTemplateName()))
{
event.setCancelled(!sign.onSignCreate(event, ess));
return;
}
}
}
@Override
public void onBlockBurn(final BlockBurnEvent event)
{
if (event.isCancelled() || ess.getSettings().areSignsDisabled())
{
return;
}
Block block = event.getBlock();
if ((block.getType() == Material.WALL_SIGN
|| block.getType() == Material.SIGN_POST
|| EssentialsSign.checkIfBlockBreaksSigns(block)))
{
event.setCancelled(true);
return;
}
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (sign.getBlocks().contains(block.getType()))
{
event.setCancelled(!sign.onBlockBurn(block, ess));
return;
}
}
}
@Override
public void onBlockIgnite(final BlockIgniteEvent event)
{
if (event.isCancelled() || ess.getSettings().areSignsDisabled())
{
return;
}
if (protectSignsAndBlocks(event.getBlock(), event.getPlayer()))
{
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,44 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.IEssentials;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityListener;
public class SignEntityListener extends EntityListener
{
private final transient IEssentials ess;
public SignEntityListener(IEssentials ess)
{
this.ess = ess;
}
@Override
public void onEntityExplode(EntityExplodeEvent event)
{
for (Block block : event.blockList())
{
if ((block.getType() == Material.WALL_SIGN
|| block.getType() == Material.SIGN_POST
|| EssentialsSign.checkIfBlockBreaksSigns(block)))
{
event.setCancelled(true);
return;
}
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (sign.getBlocks().contains(block.getType()))
{
event.setCancelled(!sign.onBlockExplode(block, ess));
return;
}
}
}
}
}

View File

@ -1,8 +1,6 @@
package com.earth2me.essentials.signs; package com.earth2me.essentials.signs;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.IEssentials; import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.ItemDb;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import net.minecraft.server.InventoryPlayer; import net.minecraft.server.InventoryPlayer;
import org.bukkit.craftbukkit.inventory.CraftInventoryPlayer; import org.bukkit.craftbukkit.inventory.CraftInventoryPlayer;

View File

@ -0,0 +1,60 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.IEssentials;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.craftbukkit.block.CraftSign;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerListener;
public class SignPlayerListener extends PlayerListener
{
private final transient IEssentials ess;
public SignPlayerListener(IEssentials ess)
{
this.ess = ess;
}
@Override
public void onPlayerInteract(PlayerInteractEvent event)
{
if (event.isCancelled() || ess.getSettings().areSignsDisabled())
{
return;
}
final Block block = event.getClickedBlock();
final int mat = block.getTypeId();
if (mat == Material.SIGN_POST.getId() || mat == Material.WALL_SIGN.getId())
{
final Sign csign = new CraftSign(block);
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (csign.getLine(0).equalsIgnoreCase(sign.getSuccessName())
&& !sign.onSignInteract(block, event.getPlayer(), ess))
{
event.setCancelled(true);
return;
}
}
}
else
{
for (Signs signs : Signs.values())
{
final EssentialsSign sign = signs.getSign();
if (sign.getBlocks().contains(block.getType())
&& !sign.onBlockInteract(block, event.getPlayer(), ess))
{
event.setCancelled(true);
return;
}
}
}
}
}

View File

@ -0,0 +1,273 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.Util;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
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.craftbukkit.block.CraftSign;
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 User player, final String username, final IEssentials ess) throws SignException, ChargeException
{
sign.setLine(3, "§4" + username);
if (hasAdjacentBlock(sign.getBlock()) && isBlockProtected(sign.getBlock(), player, username) != SignProtectionState.NOT_ALLOWED)
{
sign.setLine(3, "§1" + username);
}
return true;
}
@Override
protected boolean onSignBreak(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException
{
final SignProtectionState state = checkProtectionSign(sign, player, username);
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 User player, final String username, final IEssentials ess)
{
final Map<Location, SignProtectionState> signs = getConnectedSigns(block, player, username);
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 User user, final String username)
{
final Map<Location, SignProtectionState> signs = new HashMap<Location, SignProtectionState>();
getConnectedSigns(block, signs, user, username, 2);
return signs;
}
private void getConnectedSigns(final Block block, final Map<Location, SignProtectionState> signs, final User user, final String username, final int depth)
{
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);
signs.put(loc, check);
if (protectedBlocks.contains(b.getType()) && depth > 0)
{
getConnectedSigns(b, signs, user, username, depth - 1);
}
}
}
public enum SignProtectionState
{
NOT_ALLOWED, ALLOWED, NOSIGN, OWNER
}
private SignProtectionState checkProtectionSign(final Block block, final User user, final String username)
{
if (block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN)
{
final BlockSign sign = new BlockSign(block);
if (sign.getLine(0).equalsIgnoreCase(this.getSuccessName()))
{
return checkProtectionSign(sign, user, username);
}
}
return SignProtectionState.NOSIGN;
}
private SignProtectionState checkProtectionSign(final ISign sign, final User user, final String username)
{
if (user == null || username == null)
{
return SignProtectionState.NOT_ALLOWED;
}
if (user.isAuthorized("essentials.signs.protection.override"))
{
return SignProtectionState.OWNER;
}
for (int i = 1; i <= 2; i++)
{
final String line = sign.getLine(i);
if (line.startsWith("(") && line.endsWith(")") && user.inGroup(line.substring(1, line.length() - 1)))
{
return SignProtectionState.ALLOWED;
}
else if (line.equalsIgnoreCase(username))
{
return SignProtectionState.ALLOWED;
}
}
if (sign.getLine(3).equalsIgnoreCase(username))
{
return SignProtectionState.OWNER;
}
return SignProtectionState.NOT_ALLOWED;
}
private Block[] getAdjacentBlocks(final Block block)
{
return new Block[]
{
block.getFace(BlockFace.NORTH),
block.getFace(BlockFace.SOUTH),
block.getFace(BlockFace.EAST),
block.getFace(BlockFace.WEST),
block.getFace(BlockFace.DOWN),
block.getFace(BlockFace.UP)
};
}
public SignProtectionState isBlockProtected(final Block block, final User user, final String username)
{
final Map<Location, SignProtectionState> signs = getConnectedSigns(block, user, username);
SignProtectionState retstate = SignProtectionState.NOSIGN;
for (SignProtectionState state : signs.values())
{
if (state == SignProtectionState.OWNER || state == SignProtectionState.ALLOWED)
{
return state;
}
if (state == SignProtectionState.NOT_ALLOWED)
{
retstate = 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 = new CraftSign(b);
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 = new CraftSign(a);
if (sign.getLine(0).equalsIgnoreCase("§1[Protection]"))
{
return true;
}
}
}
}
}
return false;
}
@Override
public Set<Material> getBlocks()
{
return protectedBlocks;
}
@Override
protected boolean onBlockBreak(final Block block, final User player, final String username, final IEssentials ess) throws SignException
{
final SignProtectionState state = isBlockProtected(block, player, username);
if (state == SignProtectionState.OWNER || state == SignProtectionState.NOSIGN)
{
checkIfSignsAreBroken(block, player, username, ess);
return true;
}
if ((state == SignProtectionState.ALLOWED || state == SignProtectionState.NOT_ALLOWED)
&& player.isAuthorized("essentials.signs.protection.override"))
{
checkIfSignsAreBroken(block, player, username, ess);
return true;
}
player.sendMessage(Util.format("noDestroyPermission", block.getType().toString().toLowerCase()));
return false;
}
@Override
public boolean onBlockExplode(final Block block, final IEssentials ess)
{
final SignProtectionState state = isBlockProtected(block, null, null);
return state == SignProtectionState.NOSIGN;
}
@Override
public boolean onBlockBurn(final Block block, final IEssentials ess)
{
final SignProtectionState state = isBlockProtected(block, null, null);
return state == SignProtectionState.NOSIGN;
}
}

View File

@ -12,7 +12,7 @@ public class SignSell extends EssentialsSign
{ {
super("Sell"); super("Sell");
} }
@Override @Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException
{ {
@ -20,7 +20,7 @@ public class SignSell extends EssentialsSign
validateTrade(sign, 3, ess); validateTrade(sign, 3, ess);
return true; return true;
} }
@Override @Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException
{ {

View File

@ -65,7 +65,7 @@ public class SignTrade extends EssentialsSign
return false; return false;
} }
} }
protected final void validateTrade(final ISign sign, final int index, final boolean amountNeeded, final IEssentials ess) throws SignException 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(); final String line = sign.getLine(index).trim();

View File

@ -0,0 +1,27 @@
package com.earth2me.essentials.signs;
public enum Signs
{
BUY(new SignBuy()),
DISPOSAL(new SignDisposal()),
FREE(new SignFree()),
HEAL(new SignHeal()),
MAIL(new SignMail()),
PROTECTION(new SignProtection()),
SELL(new SignSell()),
TIME(new SignTime()),
TRADE(new SignTrade()),
WARP(new SignWarp());
private final EssentialsSign sign;
private Signs(final EssentialsSign sign)
{
this.sign = sign;
}
public EssentialsSign getSign()
{
return sign;
}
}