Improvements

This commit is contained in:
Acrobot 2012-09-12 12:35:48 +02:00
parent 7ef93e7bc1
commit d421581e89
19 changed files with 213 additions and 97 deletions

View File

@ -9,11 +9,13 @@ import com.Acrobot.ChestShop.DB.Queue;
import com.Acrobot.ChestShop.DB.Transaction;
import com.Acrobot.ChestShop.Listeners.Block.BlockBreak;
import com.Acrobot.ChestShop.Listeners.Block.BlockPlace;
import com.Acrobot.ChestShop.Listeners.Block.Break.ChestBreak;
import com.Acrobot.ChestShop.Listeners.Block.EntityExplode;
import com.Acrobot.ChestShop.Listeners.Block.SignChange;
import com.Acrobot.ChestShop.Listeners.ItemInfoListener;
import com.Acrobot.ChestShop.Listeners.Player.PlayerConnect;
import com.Acrobot.ChestShop.Listeners.Player.PlayerInteract;
import com.Acrobot.ChestShop.Listeners.Player.PlayerInventory;
import com.Acrobot.ChestShop.Listeners.Player.ShortNameSaver;
import com.Acrobot.ChestShop.Listeners.PostTransaction.EconomicModule;
import com.Acrobot.ChestShop.Listeners.PostTransaction.ItemManager;
@ -140,11 +142,13 @@ public class ChestShop extends JavaPlugin {
registerEvent(new com.Acrobot.ChestShop.Plugins.ChestShop()); //Chest protection
registerEvent(new BlockBreak());
registerEvent(new ChestBreak());
registerEvent(new BlockPlace());
registerEvent(new SignChange());
registerEvent(new EntityExplode());
registerEvent(new PlayerConnect());
registerEvent(new PlayerInteract());
registerEvent(new PlayerInventory());
registerEvent(new ItemInfoListener());

View File

@ -41,6 +41,8 @@ public enum Language {
SHOP_CREATED("Shop successfully created!"),
SHOP_REFUNDED("You have been refunded %amount."),
RESTRICTED_SIGN_CREATED("Sign succesfully created!"),
NO_PERMISSION("You don't have permissions to do that!"),
INCORRECT_ITEM_ID("You have specified invalid item id!"),
NOT_ENOUGH_PROTECTIONS("You have reached the protection limit!"),
@ -55,10 +57,6 @@ public enum Language {
text = def;
}
public String toString() {
return text;
}
public Value getValue() {
return new Value(text);
}

View File

@ -13,6 +13,7 @@ public enum Property {
SHOP_INTERACTION_INTERVAL(100, "(In 1/1000th of a second) How often can a player use the shop sign?"),
IGNORE_CREATIVE_MODE(true, "Do you want to allow using shops to people in creative mode?"),
REVERSE_BUTTONS(false, "If true, people will buy with left-click and sell with right-click."),
SHIFT_SELLS_EVERYTHING(false, "If true, people will be able to sell/buy everything available of the same type."),
ALLOW_SIGN_CHEST_OPEN(true, "Can shop's chest be opened by owner with right-clicking a shop's sign?"),
ALLOW_LEFT_CLICK_DESTROYING(true, "If true, if you left-click your own shop sign you won't open chest's inventory, but instead you will start destroying the sign.\n"),
@ -42,6 +43,9 @@ public enum Property {
RECORD_TIME_TO_LIVE(600, "How long should transaction information be stored in the database (in seconds, -1 means forever)?\n"),
USE_BUILT_IN_PROTECTION(true, "Do you want to use built-in protection against chest destruction?"),
STICK_SIGNS_TO_CHESTS(false, "Do you want to have shop signs \"stick\" to chests?"),
TURN_OFF_DEFAULT_PROTECTION_WHEN_PROTECTED_EXTERNALLY(false, "EXPERIMENTAL: Do you want to turn off the default protection when another plugin is protecting the block? (Will leave the chest visually open - CraftBukkit bug!)"),
TURN_OFF_SIGN_PROTECTION(false, "Do you want to turn off the default sign protection? Warning! Other players will be able to destroy other people's shops!"),
PROTECT_CHEST_WITH_LWC(false, "Do you want to protect shop chests with LWC?"),
PROTECT_SIGN_WITH_LWC(false, "Do you want to protect shop signs with LWC?\n"),
@ -77,10 +81,6 @@ public enum Property {
return new Value(value, comment);
}
public String toString() {
return name();
}
public static Map<String, Value> getValues() {
return PROPERTIES;
}

View File

@ -80,9 +80,6 @@ public class Dependencies {
case SimpleChestLock:
listener = SimpleChestLock.getSimpleChestLock(plugin);
break;
case SecureChests:
listener = new SecureChests();
break;
case Residence:
listener = new ResidenceChestProtection();
break;
@ -155,7 +152,6 @@ public class Dependencies {
Lockette,
Deadbolt,
SimpleChestLock,
SecureChests,
Residence,
OddItem,

View File

@ -50,6 +50,10 @@ public class Economy {
}
public static boolean hasEnough(String name, double amount) {
if (amount <= 0) {
return true;
}
return economy.hasEnough(uName.getName(name), roundUp(amount));
}

View File

@ -12,6 +12,7 @@ public class ProtectionCheckEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private Result result = Result.DEFAULT;
private boolean ignoreBuiltInProtection = false;
private Block block;
private Player player;
@ -20,6 +21,16 @@ public class ProtectionCheckEvent extends Event {
this.player = player;
}
public ProtectionCheckEvent(Block block, Player player, boolean ignoreBuiltInProtection) {
this.block = block;
this.player = player;
this.ignoreBuiltInProtection = ignoreBuiltInProtection;
}
public boolean isBuiltInProtectionIgnored() {
return ignoreBuiltInProtection;
}
public Result getResult() {
return result;
}

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.List;
import static com.Acrobot.ChestShop.Config.Property.SHOP_REFUND_PRICE;
import static com.Acrobot.ChestShop.Config.Property.TURN_OFF_SIGN_PROTECTION;
/**
* @author Acrobot
@ -39,7 +40,7 @@ public class BlockBreak implements Listener {
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 (playerIsNotOwner(player, sign)) return !isAdmin(player) && (!BlockUtil.isSign(block) || !Config.getBoolean(TURN_OFF_SIGN_PROTECTION)); //If the player isn't the owner or an admin - cancel!
if (weShouldReturnMoney() && !Permission.has(player, Permission.NOFEE)) {
float refundPrice = Config.getFloat(SHOP_REFUND_PRICE);

View File

@ -0,0 +1,32 @@
package com.Acrobot.ChestShop.Listeners.Block.Break;
import com.Acrobot.ChestShop.Config.Config;
import com.Acrobot.ChestShop.Listeners.Player.PlayerInteract;
import com.Acrobot.ChestShop.Plugins.ChestShop;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import static com.Acrobot.ChestShop.Config.Property.USE_BUILT_IN_PROTECTION;
import static org.bukkit.Material.CHEST;
/**
* @author Acrobot
*/
public class ChestBreak implements Listener {
@EventHandler(ignoreCancelled = true)
public static void onChestBreak(BlockBreakEvent event) {
if (event.getBlock().getType() != CHEST || !Config.getBoolean(USE_BUILT_IN_PROTECTION)) {
return;
}
Player player = event.getPlayer();
Block block = event.getBlock();
if (!PlayerInteract.canOpenOtherShops(player) && !ChestShop.canAccess(player, block)) {
event.setCancelled(true);
}
}
}

View File

@ -19,6 +19,7 @@ import com.Acrobot.ChestShop.Utils.uBlock;
import com.Acrobot.ChestShop.Utils.uName;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Chest;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
@ -30,6 +31,7 @@ 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.Config.Property.STICK_SIGNS_TO_CHESTS;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
/**
@ -123,10 +125,47 @@ public class SignChange implements Listener {
player.sendMessage(Config.getLocal(SHOP_CREATED));
}
if (!isAdminShop(line[NAME_LINE]) && Config.getBoolean(STICK_SIGNS_TO_CHESTS)) {
stickSign(signBlock, event);
}
ShopCreatedEvent sEvent = new ShopCreatedEvent(player, (Sign) signBlock.getState(), connectedChest, event.getLines());
ChestShop.callEvent(sEvent);
}
private static void stickSign(Block block, SignChangeEvent event) {
if (block.getType() != Material.SIGN_POST) {
return;
}
BlockFace chestFace = null;
for (BlockFace face : uBlock.CHEST_EXTENSION_FACES) {
if (block.getRelative(face).getType() == Material.CHEST) {
chestFace = face;
break;
}
}
if (chestFace == null) {
return;
}
org.bukkit.material.Sign signMaterial = new org.bukkit.material.Sign(Material.WALL_SIGN);
signMaterial.setFacingDirection(chestFace.getOppositeFace());
block.setType(Material.WALL_SIGN);
block.setData(signMaterial.getData());
Sign sign = (Sign) block.getState();
for (int i = 0; i < event.getLines().length; ++i) {
sign.setLine(i, event.getLine(i));
}
sign.update(true);
}
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 != NO_PRICE && sellPrice != NO_PRICE && sellPrice > buyPrice) {

View File

@ -1,6 +1,7 @@
package com.Acrobot.ChestShop.Listeners.Player;
import com.Acrobot.Breeze.Utils.BlockUtil;
import com.Acrobot.Breeze.Utils.InventoryUtil;
import com.Acrobot.Breeze.Utils.MaterialUtil;
import com.Acrobot.Breeze.Utils.PriceUtil;
import com.Acrobot.ChestShop.Config.Config;
@ -54,18 +55,23 @@ public class PlayerInteract implements Listener {
Player player = event.getPlayer();
if (Config.getBoolean(USE_BUILT_IN_PROTECTION) && clickedBlock.getType() == Material.CHEST) {
if (Config.getBoolean(TURN_OFF_DEFAULT_PROTECTION_WHEN_PROTECTED_EXTERNALLY)) {
return;
}
if (!canOpenOtherShops(player) && !ChestShop.canAccess(player, clickedBlock)) {
player.sendMessage(Config.getLocal(ACCESS_DENIED));
event.setCancelled(true);
return;
}
return; //The else doesn't matter, because the clicked block is a chest
}
if (!BlockUtil.isSign(clickedBlock)) return;
Sign sign = (Sign) clickedBlock.getState();
if (player.getItemInHand() != null && player.getItemInHand().getType() == Material.SIGN) return;
if (!ChestShopSign.isValid(sign) || player.isSneaking()) return;
if (!ChestShopSign.isValid(sign) || (ChestShopSign.canAccess(player, sign) && player.isSneaking())) return;
if (action == RIGHT_CLICK_BLOCK) {
event.setCancelled(true);
@ -108,6 +114,15 @@ public class PlayerInteract implements Listener {
ItemStack item = MaterialUtil.getItem(sign.getLine(ITEM_LINE));
int amount = Integer.parseInt(sign.getLine(QUANTITY_LINE));
if (Config.getBoolean(SHIFT_SELLS_EVERYTHING) && player.isSneaking() && price != PriceUtil.NO_PRICE) {
int newAmount = getItemAmount(item, ownerInventory, player, action);
if (newAmount > 0) {
price = (price / amount) * newAmount;
amount = newAmount;
}
}
item.setAmount(amount);
ItemStack[] items = {item};
@ -116,7 +131,20 @@ public class PlayerInteract implements Listener {
return new PreTransactionEvent(ownerInventory, player.getInventory(), items, price, player, owner, sign, transactionType);
}
private static boolean canOpenOtherShops(Player player) {
private static int getItemAmount(ItemStack item, Inventory inventory, Player player, Action action) {
int amount;
Action buy = Config.getBoolean(REVERSE_BUTTONS) ? LEFT_CLICK_BLOCK : RIGHT_CLICK_BLOCK;
if (action == buy) {
amount = InventoryUtil.getAmount(item, inventory);
} else {
amount = InventoryUtil.getAmount(item, player.getInventory());
}
return amount;
}
public static boolean canOpenOtherShops(Player player) {
return Permission.has(player, Permission.ADMIN) || Permission.has(player, Permission.MOD);
}

View File

@ -0,0 +1,47 @@
package com.Acrobot.ChestShop.Listeners.Player;
import com.Acrobot.ChestShop.Config.Config;
import com.Acrobot.ChestShop.Plugins.ChestShop;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Chest;
import org.bukkit.block.DoubleChest;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import static com.Acrobot.ChestShop.Config.Language.ACCESS_DENIED;
import static com.Acrobot.ChestShop.Config.Property.TURN_OFF_DEFAULT_PROTECTION_WHEN_PROTECTED_EXTERNALLY;
/**
* @author Acrobot
*/
public class PlayerInventory implements Listener {
@EventHandler
public static void onInventoryOpen(InventoryOpenEvent event) {
if (event.getInventory().getType() != InventoryType.CHEST) {
return;
}
if (!Config.getBoolean(TURN_OFF_DEFAULT_PROTECTION_WHEN_PROTECTED_EXTERNALLY)) {
return;
}
HumanEntity entity = event.getPlayer();
if (!(entity instanceof Player) || (!(event.getInventory().getHolder() instanceof Chest) && !(event.getInventory().getHolder() instanceof DoubleChest))) {
return;
}
Player player = (Player) entity;
Block chest = ((BlockState) event.getInventory().getHolder()).getBlock();
if (!PlayerInteract.canOpenOtherShops(player) && !ChestShop.canAccess(player, chest)) {
player.sendMessage(Config.getLocal(ACCESS_DENIED));
event.setCancelled(true);
}
}
}

View File

@ -1,12 +1,15 @@
package com.Acrobot.ChestShop.Listeners.PostTransaction;
import com.Acrobot.Breeze.Utils.InventoryUtil;
import com.Acrobot.ChestShop.Config.Config;
import com.Acrobot.ChestShop.Events.TransactionEvent;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.Material;
import org.bukkit.block.Chest;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -18,20 +21,26 @@ import static com.Acrobot.ChestShop.Config.Property.REMOVE_EMPTY_SHOPS;
* @author Acrobot
*/
public class EmptyShopDeleter implements Listener {
@EventHandler
@EventHandler(priority = EventPriority.HIGHEST)
public static void onTransaction(TransactionEvent event) {
if (event.getTransactionType() != TransactionEvent.TransactionType.BUY) {
return;
}
if (shopShouldBeRemoved(event.getOwnerInventory(), event.getStock())) {
if (Config.getBoolean(REMOVE_EMPTY_CHESTS) && !ChestShopSign.isAdminShop(event.getSign()) && chestIsEmpty(event.getOwnerInventory())) {
Chest connectedChest = uBlock.findConnectedChest(event.getSign());
connectedChest.getBlock().setType(Material.AIR);
}
Inventory ownerInventory = event.getOwnerInventory();
Sign sign = event.getSign();
event.getSign().getBlock().setType(Material.AIR);
event.getOwnerInventory().addItem(new ItemStack(Material.SIGN, 1));
if (!shopShouldBeRemoved(ownerInventory, event.getStock())) {
return;
}
sign.getBlock().setType(Material.AIR);
if (Config.getBoolean(REMOVE_EMPTY_CHESTS) && !ChestShopSign.isAdminShop(sign) && chestIsEmpty(event.getOwnerInventory())) {
Chest connectedChest = uBlock.findConnectedChest(sign);
connectedChest.getBlock().setType(Material.AIR);
} else {
ownerInventory.addItem(new ItemStack(Material.SIGN, 1));
}
}
@ -51,11 +60,11 @@ public class EmptyShopDeleter implements Listener {
private static boolean hasMoreStock(Inventory inventory, ItemStack[] stock) {
for (ItemStack stack : stock) {
if (!inventory.contains(stack, 1)) {
return false;
if (InventoryUtil.getAmount(stack, inventory) > 0) {
return true;
}
}
return true;
return false;
}
}

View File

@ -20,7 +20,7 @@ import org.bukkit.event.Listener;
public class ChestShop implements Listener {
@EventHandler
public static void onProtectionCheck(ProtectionCheckEvent event) {
if (event.getResult() == Event.Result.DENY) {
if (event.getResult() == Event.Result.DENY || event.isBuiltInProtectionIgnored()) {
return;
}

View File

@ -1,60 +0,0 @@
package com.Acrobot.ChestShop.Plugins;
import com.Acrobot.ChestShop.Events.Protection.ProtectBlockEvent;
import com.Acrobot.ChestShop.Events.Protection.ProtectionCheckEvent;
import me.HAklowner.SecureChests.Lock;
import me.HAklowner.SecureChests.Managers.LockManager;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
/**
* @author Acrobot
*/
public class SecureChests implements Listener {
private LockManager lockManager;
public SecureChests() {
lockManager = me.HAklowner.SecureChests.SecureChests.getInstance().getLockManager();
}
@EventHandler
public void onProtectionCheck(ProtectionCheckEvent event) {
if (event.getResult() == Event.Result.DENY) {
return;
}
Block block = event.getBlock();
Lock lock = lockManager.getLock(block.getLocation());
if (!lock.isLocked()) {
return;
}
String owner = lock.getOwner();
if (!event.getPlayer().getName().equals(owner)) {
event.setResult(Event.Result.DENY);
}
}
@EventHandler
public void onBlockProtect(ProtectBlockEvent event) {
if (event.isProtected()) {
return;
}
Block block = event.getBlock();
String player = event.getName();
if (block == null || player == null) {
return;
}
Lock lock = lockManager.getLock(block.getLocation());
if (!lock.isLocked()) {
lock.lock(player);
}
}
}

View File

@ -30,7 +30,11 @@ public class Security {
}
public static boolean canAccess(Player player, Block block) {
ProtectionCheckEvent event = new ProtectionCheckEvent(block, player);
return canAccess(player, block, false);
}
public static boolean canAccess(Player player, Block block, boolean ignoreDefault) {
ProtectionCheckEvent event = new ProtectionCheckEvent(block, player, ignoreDefault);
ChestShop.callEvent(event);
return event.getResult() != Event.Result.DENY;

View File

@ -23,7 +23,7 @@ public class ChestShopSign {
public static final Pattern[] SHOP_SIGN_PATTERN = {
Pattern.compile("^[\\w ]*$"),
Pattern.compile("[0-9]+"),
Pattern.compile("(?i)^[\\dbs(free) :]+$"),
Pattern.compile("(?i)^[\\d.bs(free) :]+$"),
Pattern.compile("[\\w : -]+")
};

View File

@ -2,7 +2,6 @@ package com.Acrobot.ChestShop.Signs;
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 org.bukkit.Location;
@ -16,6 +15,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.SignChangeEvent;
import static com.Acrobot.ChestShop.Config.Language.ACCESS_DENIED;
import static com.Acrobot.ChestShop.Config.Language.RESTRICTED_SIGN_CREATED;
import static com.Acrobot.ChestShop.Events.PreTransactionEvent.TransactionOutcome.SHOP_IS_RESTRICTED;
/**
@ -45,7 +46,7 @@ public class RestrictedSign implements Listener {
if (isRestricted(lines)) {
if (!hasPermission(player, lines)) {
player.sendMessage(Config.getLocal(Language.ACCESS_DENIED));
player.sendMessage(Config.getLocal(ACCESS_DENIED));
dropSignAndCancelEvent(event);
return;
}
@ -61,6 +62,8 @@ public class RestrictedSign implements Listener {
if (!ChestShopSign.isValid(sign) || !ChestShopSign.canAccess(player, sign)) {
dropSignAndCancelEvent(event);
}
player.sendMessage(Config.getLocal(RESTRICTED_SIGN_CREATED));
}
}

View File

@ -13,9 +13,9 @@ import org.bukkit.material.Attachable;
* @author Acrobot
*/
public class uBlock {
private static final BlockFace[] CHEST_EXTENSION_FACES = {BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
private static final BlockFace[] SHOP_FACES = {BlockFace.SELF, BlockFace.DOWN, BlockFace.UP, BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
private static final BlockFace[] NEIGHBOR_FACES = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
public static final BlockFace[] CHEST_EXTENSION_FACES = {BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
public static final BlockFace[] SHOP_FACES = {BlockFace.SELF, BlockFace.DOWN, BlockFace.UP, BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
public static final BlockFace[] NEIGHBOR_FACES = {BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
public static Sign getConnectedSign(Chest chest) {
Sign sign = uBlock.findAnyNearbyShopSign(chest.getBlock());

View File

@ -2,7 +2,7 @@ name: ChestShop
main: com.Acrobot.ChestShop.ChestShop
version: 3.50t0005
version: 3.50t0007
#for CButD
dev-url: http://dev.bukkit.org/server-mods/chestshop/
@ -14,7 +14,7 @@ description: >
softdepend: [LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes,
iConomy, BOSEconomy, Essentials, SimpleChestLock, SecureChests, Residence]
iConomy, BOSEconomy, Essentials, SimpleChestLock, Residence]
commands:
iteminfo:
aliases: [iinfo]