From d1732552b03384719b31c634b39bb341f02af767 Mon Sep 17 00:00:00 2001 From: Acrobot Date: Sat, 7 Jul 2012 19:24:06 +0200 Subject: [PATCH] - Made the plugin more event-driven - Added PreTransactionEvent which can be cancelled - Fixed not placing B/S before prices - Updated Heroes --- com/Acrobot/Breeze/Utils/BlockUtil.java | 11 ++++ com/Acrobot/Breeze/Utils/MaterialUtil.java | 16 +++--- com/Acrobot/Breeze/Utils/PriceUtil.java | 13 +++++ .../ChestShop/Events/PreTransactionEvent.java | 54 +++++++++++++++++++ .../ChestShop/Listeners/Block/BlockBreak.java | 19 +++---- .../ChestShop/Listeners/Block/SignChange.java | 17 +++--- .../Listeners/Player/PlayerInteract.java | 11 ++++ com/Acrobot/ChestShop/Plugins/Heroes.java | 2 +- .../ChestShop/Signs/restrictedSign.java | 49 ++++++++++++++++- com/Acrobot/ChestShop/Utils/uBlock.java | 18 ------- plugin.yml | 2 +- 11 files changed, 164 insertions(+), 48 deletions(-) create mode 100644 com/Acrobot/ChestShop/Events/PreTransactionEvent.java diff --git a/com/Acrobot/Breeze/Utils/BlockUtil.java b/com/Acrobot/Breeze/Utils/BlockUtil.java index fbb9cf3..89f7131 100644 --- a/com/Acrobot/Breeze/Utils/BlockUtil.java +++ b/com/Acrobot/Breeze/Utils/BlockUtil.java @@ -2,6 +2,7 @@ package com.Acrobot.Breeze.Utils; import org.bukkit.block.Block; import org.bukkit.block.Sign; +import org.bukkit.material.Attachable; /** * @author Acrobot @@ -16,4 +17,14 @@ public class BlockUtil { public static boolean isSign(Block block) { return block.getState() instanceof Sign; } + + /** + * Gets the block to which the sign is attached + * + * @param sign Sign which is attached + * @return Block to which the sign is attached + */ + public static Block getAttachedFace(Sign sign) { + return sign.getBlock().getRelative(((Attachable) sign.getData()).getAttachedFace()); + } } diff --git a/com/Acrobot/Breeze/Utils/MaterialUtil.java b/com/Acrobot/Breeze/Utils/MaterialUtil.java index 37b4129..47e8ddf 100644 --- a/com/Acrobot/Breeze/Utils/MaterialUtil.java +++ b/com/Acrobot/Breeze/Utils/MaterialUtil.java @@ -243,14 +243,14 @@ public class MaterialUtil { Map map = new HashMap(); - StringBuilder integer = new StringBuilder(String.valueOf(Integer.parseInt(base32, 32))); + StringBuilder number = new StringBuilder(Long.toString(Long.parseLong(base32, 32))); - while (integer.length() % 3 != 0) { - integer.insert(0, '0'); + while (number.length() % 3 != 0) { + number.insert(0, '0'); } - for (int i = 0; i < integer.length() / 3; i++) { - String item = integer.substring(i * 3, i * 3 + 3); + for (int i = 0; i < number.length() / 3; i++) { + String item = number.substring(i * 3, i * 3 + 3); org.bukkit.enchantments.Enchantment enchantment = org.bukkit.enchantments.Enchantment.getById(Integer.parseInt(item.substring(0, 2))); @@ -279,13 +279,13 @@ public class MaterialUtil { * @return Encoded enchantments */ public static String encodeEnchantment(Map enchantments) { - int integer = 0; + long number = 0; for (Map.Entry entry : enchantments.entrySet()) { - integer = integer * 1000 + (entry.getKey().getId()) * 10 + entry.getValue(); + number = number * 1000 + (entry.getKey().getId()) * 10 + entry.getValue(); } - return integer != 0 ? Integer.toString(integer, 32) : null; + return number != 0 ? Long.toString(number, 32) : null; } /** diff --git a/com/Acrobot/Breeze/Utils/PriceUtil.java b/com/Acrobot/Breeze/Utils/PriceUtil.java index bd34e97..4802e2f 100644 --- a/com/Acrobot/Breeze/Utils/PriceUtil.java +++ b/com/Acrobot/Breeze/Utils/PriceUtil.java @@ -61,4 +61,17 @@ public class PriceUtil { public static double getSellPrice(String text) { return get(text, 's'); } + + /** + * Checks if the string is a valid price + * @param text Text to check + * @return Is the string a valid price + */ + public static boolean textIsPrice(String text) { + if (NumberUtil.isFloat(text)) { + return true; + } + + return text.trim().equalsIgnoreCase("free"); + } } diff --git a/com/Acrobot/ChestShop/Events/PreTransactionEvent.java b/com/Acrobot/ChestShop/Events/PreTransactionEvent.java new file mode 100644 index 0000000..7f69730 --- /dev/null +++ b/com/Acrobot/ChestShop/Events/PreTransactionEvent.java @@ -0,0 +1,54 @@ +package com.Acrobot.ChestShop.Events; + +import com.Acrobot.ChestShop.Shop.Shop; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @author Acrobot + */ +public class PreTransactionEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private final Shop shop; + private final Player player; + private final TransactionEvent.Type transactionType; + + private boolean isCancelled = false; + + public PreTransactionEvent(Shop shop, Player player, TransactionEvent.Type type) { + this.shop = shop; + this.player = player; + this.transactionType = type; + } + + public Shop getShop() { + return shop; + } + + public Player getPlayer() { + return player; + } + + public TransactionEvent.Type getTransactionType() { + return transactionType; + } + + public boolean isCancelled() { + return isCancelled; + } + + public void setCancelled(boolean b) { + this.isCancelled = b; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/com/Acrobot/ChestShop/Listeners/Block/BlockBreak.java b/com/Acrobot/ChestShop/Listeners/Block/BlockBreak.java index 829e2a8..e6007ad 100644 --- a/com/Acrobot/ChestShop/Listeners/Block/BlockBreak.java +++ b/com/Acrobot/ChestShop/Listeners/Block/BlockBreak.java @@ -3,10 +3,8 @@ package com.Acrobot.ChestShop.Listeners.Block; import com.Acrobot.Breeze.Utils.BlockUtil; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; -import com.Acrobot.ChestShop.Config.Property; import com.Acrobot.ChestShop.Economy.Economy; import com.Acrobot.ChestShop.Permission; -import com.Acrobot.ChestShop.Signs.RestrictedSign; import com.Acrobot.ChestShop.Utils.uBlock; import com.Acrobot.ChestShop.Utils.uName; import org.bukkit.Material; @@ -26,23 +24,25 @@ import org.bukkit.material.PistonBaseMaterial; import java.util.ArrayList; import java.util.List; +import static com.Acrobot.ChestShop.Config.Property.SHOP_REFUND_PRICE; + /** * @author Acrobot */ public class BlockBreak implements Listener { public static boolean cancellingBlockBreak(Block block, Player player) { - if (block == null) return false; + if (block == null) { + return false; + } if (BlockUtil.isSign(block)) block.getState().update(); //Show the text immediately - if (restrictedSign(block)) return !RestrictedSign.canDestroy(player, uBlock.findRestrictedSign(block)); - Sign sign = uBlock.findValidShopSign(block, (player != null ? uName.stripName(player.getName()) : null)); if (!isCorrectSign(sign, block)) return false; //It's not a correct shop sign, so don't cancel it if (playerIsNotOwner(player, sign)) return !isAdmin(player); //If the player isn't the owner or an admin - cancel! if (weShouldReturnMoney() && !Permission.has(player, Permission.NOFEE)) { - float refundPrice = Config.getFloat(Property.SHOP_REFUND_PRICE); + float refundPrice = Config.getFloat(SHOP_REFUND_PRICE); Economy.add(uName.getName(sign.getLine(0)), refundPrice); //Add some money player.sendMessage(Config.getLocal(Language.SHOP_REFUNDED).replace("%amount", Economy.formatBalance(refundPrice))); } @@ -55,12 +55,7 @@ public class BlockBreak implements Listener { } private static boolean weShouldReturnMoney() { - //We should return money when it's turned on in config, obviously - return Config.getFloat(Property.SHOP_REFUND_PRICE) != 0; - } - - private static boolean restrictedSign(Block block) { - return uBlock.findRestrictedSign(block) != null; + return Config.getFloat(SHOP_REFUND_PRICE) != 0; } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) diff --git a/com/Acrobot/ChestShop/Listeners/Block/SignChange.java b/com/Acrobot/ChestShop/Listeners/Block/SignChange.java index e1f7a3e..7b1030f 100644 --- a/com/Acrobot/ChestShop/Listeners/Block/SignChange.java +++ b/com/Acrobot/ChestShop/Listeners/Block/SignChange.java @@ -1,7 +1,6 @@ package com.Acrobot.ChestShop.Listeners.Block; import com.Acrobot.Breeze.Utils.MaterialUtil; -import com.Acrobot.Breeze.Utils.NumberUtil; import com.Acrobot.Breeze.Utils.PriceUtil; import com.Acrobot.Breeze.Utils.StringUtil; import com.Acrobot.ChestShop.ChestShop; @@ -27,6 +26,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.inventory.ItemStack; +import static com.Acrobot.Breeze.Utils.PriceUtil.NO_PRICE; import static com.Acrobot.ChestShop.Config.Language.*; import static com.Acrobot.ChestShop.Config.Property.SHOP_CREATION_PRICE; import static com.Acrobot.ChestShop.Signs.ChestShopSign.*; @@ -123,7 +123,7 @@ public class SignChange implements Listener { private static boolean canCreateShop(Player player, Material mat, double buyPrice, double sellPrice) { if (Config.getBoolean(Property.BLOCK_SHOPS_WITH_SELL_PRICE_HIGHER_THAN_BUY_PRICE)) { - if (buyPrice != -1 && sellPrice != -1 && sellPrice > buyPrice) { + if (buyPrice != NO_PRICE && sellPrice != NO_PRICE && sellPrice > buyPrice) { return false; } } @@ -135,18 +135,21 @@ public class SignChange implements Listener { return true; } - if (buy && !Permission.has(player, Permission.SHOP_CREATION_BUY)) return false; - return !(sell && !Permission.has(player, Permission.SHOP_CREATION_SELL)); + if (buy && !Permission.has(player, Permission.SHOP_CREATION_BUY)){ + return false; + } else { + return !(sell && !Permission.has(player, Permission.SHOP_CREATION_SELL)); + } } private static String formatPriceLine(String thirdLine) { - String line = thirdLine.toUpperCase(); + String line = thirdLine; String[] split = line.split(":"); - if (NumberUtil.isFloat(split[0])) { + if (PriceUtil.textIsPrice(split[0])) { line = "B " + line; } - if (split.length == 2 && NumberUtil.isFloat(split[1])) { + if (split.length == 2 && PriceUtil.textIsPrice(split[1])) { line += " S"; } diff --git a/com/Acrobot/ChestShop/Listeners/Player/PlayerInteract.java b/com/Acrobot/ChestShop/Listeners/Player/PlayerInteract.java index 4782f03..659b22b 100644 --- a/com/Acrobot/ChestShop/Listeners/Player/PlayerInteract.java +++ b/com/Acrobot/ChestShop/Listeners/Player/PlayerInteract.java @@ -3,6 +3,7 @@ package com.Acrobot.ChestShop.Listeners.Player; import com.Acrobot.Breeze.Utils.BlockUtil; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; +import com.Acrobot.ChestShop.Events.PreTransactionEvent; import com.Acrobot.ChestShop.Permission; import com.Acrobot.ChestShop.Plugins.ChestShop; import com.Acrobot.ChestShop.Security; @@ -10,6 +11,7 @@ import com.Acrobot.ChestShop.Shop.Shop; import com.Acrobot.ChestShop.Signs.ChestShopSign; import com.Acrobot.ChestShop.Signs.RestrictedSign; import com.Acrobot.ChestShop.Utils.uBlock; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Material; @@ -30,6 +32,8 @@ import java.util.UUID; import static com.Acrobot.ChestShop.Config.Language.ACCESS_DENIED; import static com.Acrobot.ChestShop.Config.Property.*; +import static com.Acrobot.ChestShop.Events.TransactionEvent.Type.BUY; +import static com.Acrobot.ChestShop.Events.TransactionEvent.Type.SELL; import static org.bukkit.event.block.Action.LEFT_CLICK_BLOCK; import static org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK; @@ -106,6 +110,13 @@ public class PlayerInteract implements Listener { return; } + PreTransactionEvent pEvent = new PreTransactionEvent(shop, player, action == buy ? BUY : SELL); + Bukkit.getPluginManager().callEvent(pEvent); + + if (pEvent.isCancelled()) { + return; + } + if (action == buy) { shop.sellToPlayer(player); } else { diff --git a/com/Acrobot/ChestShop/Plugins/Heroes.java b/com/Acrobot/ChestShop/Plugins/Heroes.java index 75d2dd6..099396c 100644 --- a/com/Acrobot/ChestShop/Plugins/Heroes.java +++ b/com/Acrobot/ChestShop/Plugins/Heroes.java @@ -32,7 +32,7 @@ public class Heroes implements Listener { if (hero.hasParty()) { hero.getParty().gainExp(heroExp, HeroClass.ExperienceType.EXTERNAL, event.getPlayer().getLocation()); } else { - hero.gainExp(heroExp, HeroClass.ExperienceType.EXTERNAL); + hero.gainExp(heroExp, HeroClass.ExperienceType.EXTERNAL, event.getPlayer().getLocation()); } } diff --git a/com/Acrobot/ChestShop/Signs/restrictedSign.java b/com/Acrobot/ChestShop/Signs/restrictedSign.java index 78aec54..447b154 100644 --- a/com/Acrobot/ChestShop/Signs/restrictedSign.java +++ b/com/Acrobot/ChestShop/Signs/restrictedSign.java @@ -4,6 +4,7 @@ import com.Acrobot.Breeze.Utils.BlockUtil; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; import com.Acrobot.ChestShop.Permission; +import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; @@ -11,12 +12,29 @@ 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.BlockBreakEvent; import org.bukkit.event.block.SignChangeEvent; /** * @author Acrobot */ public class RestrictedSign implements Listener { + private static final BlockFace[] SIGN_CONNECTION_FACES = {BlockFace.SELF, BlockFace.UP, BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH}; + + @EventHandler(ignoreCancelled = true) + public static void onBlockDestroy(BlockBreakEvent event) { + Block destroyed = event.getBlock(); + Sign attachedRestrictedSign = getRestrictedSign(destroyed.getLocation()); + + if (attachedRestrictedSign == null) { + return; + } + + if (!canDestroy(event.getPlayer(), attachedRestrictedSign)) { + event.setCancelled(true); + } + } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public static void onSignChange(SignChangeEvent event) { String[] lines = event.getLines(); @@ -42,6 +60,35 @@ public class RestrictedSign implements Listener { } } } + + public static Sign getRestrictedSign(Location location) { + Block currentBlock = location.getBlock(); + + if (BlockUtil.isSign(currentBlock)) { + return (Sign) currentBlock.getState(); + } + + for (BlockFace face : SIGN_CONNECTION_FACES) { + Block relative = currentBlock.getRelative(face); + + if (!BlockUtil.isSign(relative)) { + continue; + } + + Sign sign = (Sign) relative.getState(); + + if (!BlockUtil.getAttachedFace(sign).equals(currentBlock)) { + continue; + } + + if (isRestricted(sign)) { + return sign; + } + } + + return null; //No sign found + } + public static boolean isRestrictedShop(Sign sign) { Block blockUp = sign.getBlock().getRelative(BlockFace.UP); return BlockUtil.isSign(blockUp) && isRestricted(((Sign) blockUp.getState()).getLines()); @@ -52,7 +99,7 @@ public class RestrictedSign implements Listener { } public static boolean isRestricted(Sign sign) { - return sign.getLine(0).equalsIgnoreCase("[restricted]"); + return isRestricted(sign.getLines()); } public static boolean canAccess(Sign sign, Player player) { diff --git a/com/Acrobot/ChestShop/Utils/uBlock.java b/com/Acrobot/ChestShop/Utils/uBlock.java index af4fc0c..d578e20 100644 --- a/com/Acrobot/ChestShop/Utils/uBlock.java +++ b/com/Acrobot/ChestShop/Utils/uBlock.java @@ -2,7 +2,6 @@ package com.Acrobot.ChestShop.Utils; import com.Acrobot.Breeze.Utils.BlockUtil; import com.Acrobot.ChestShop.Signs.ChestShopSign; -import com.Acrobot.ChestShop.Signs.RestrictedSign; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -73,23 +72,6 @@ public class uBlock { return null; } - public static Sign findRestrictedSign(Block block) { - for (BlockFace bf : SHOP_FACES) { - Block faceBlock = block.getRelative(bf); - - if (!BlockUtil.isSign(faceBlock)) { - continue; - } - - Sign sign = (Sign) faceBlock.getState(); - - if (RestrictedSign.isRestricted(sign) && signIsAttachedToBlock(sign, block)) { - return sign; - } - } - return null; - } - public static Chest findNeighbor(Block block) { for (BlockFace blockFace : CHEST_EXTENSION_FACES) { Block neighborBlock = block.getRelative(blockFace); diff --git a/plugin.yml b/plugin.yml index ec795e5..2533150 100644 --- a/plugin.yml +++ b/plugin.yml @@ -2,7 +2,7 @@ name: ChestShop main: com.Acrobot.ChestShop.ChestShop -version: 3.45 TEST BUILD +version: 3.46 #for CButD dev-url: http://dev.bukkit.org/server-mods/chestshop/