ChestShop 3.50 IS NEAR

This commit is contained in:
Acrobot 2013-01-24 22:35:28 +01:00
parent 4d73ef02a5
commit ebdf90a64e
29 changed files with 2637 additions and 448 deletions

View File

@ -4,7 +4,10 @@ import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

View File

@ -10,21 +10,29 @@ import java.sql.*;
* @author Acrobot
*/
public class Table {
private Database database;
private String name;
private final Database database;
private final String name;
private final String SELECT_ALL = "SELECT * FROM " + name;
private final String SELECT_STATEMENT = "SELECT * FROM " + name + " WHERE 's'";
private final String SELECT_ALL;
private final String SELECT_STATEMENT;
private final String INSERT_VALUES = "INSERT INTO " + name + " VALUES ('s')";
private final String UPDATE = "UPDATE " + name + " SET 's' WHERE 's'";
private final String INSERT_VALUES;
private final String UPDATE;
private final String CREATE = "CREATE TABLE IF NOT EXISTS " + name + " ('s')";
private final String CREATE;
public Table(Database database, String name) {
this.database = database;
this.name = name;
SELECT_ALL = "SELECT * FROM " + name;
SELECT_STATEMENT = "SELECT * FROM " + name + " WHERE %s";
INSERT_VALUES = "INSERT OR IGNORE INTO " + name + " VALUES (%s)";
UPDATE = "UPDATE " + name + " SET %s WHERE %s";
CREATE = "CREATE TABLE IF NOT EXISTS " + name + " (%s)";
}
/**
@ -74,7 +82,7 @@ public class Table {
*/
public Row getRow(String criteria) throws SQLException {
RowSet rs = select(criteria);
return rs.get(0);
return (rs.size() > 0 ? rs.get(0) : new Row());
}
/**
@ -132,6 +140,36 @@ public class Table {
stm.executeUpdate(statement);
}
/**
* Inserts a row into the table
*
* @param statement Row to insert
* @throws SQLException exception
*/
public void insertRow(String statement) throws SQLException {
insertRow(statement, null);
}
/**
* Inserts a row into the table
*
* @param statement Row to insert
* @param condition If the conditions are present, the row is updated when the conditions are met
* @throws SQLException exception
*/
public void insertRow(String statement, String condition) throws SQLException {
if (condition == null || condition.isEmpty()) {
statement = String.format(INSERT_VALUES, statement);
} else {
statement = String.format(UPDATE, statement, condition);
}
Connection connection = database.getConnection();
Statement stm = connection.createStatement();
stm.executeUpdate(statement);
}
/**
* Creates a table with given fields. If the table already exists, nothing happens
*
@ -145,4 +183,13 @@ public class Table {
stm.executeUpdate(statement);
}
/**
* Returns this table's name
*
* @return Table's name
*/
public String getName() {
return name;
}
}

View File

@ -1,36 +0,0 @@
package com.Acrobot.Breeze.Serialization;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @author Acrobot
*/
public class Decoder {
/**
* Decodes an object from string
*
* @param string String to decode
* @return Object returned
*/
public static Object fromString(String string) {
byte[] data = Base64.decodeBase64(string);
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -1,35 +0,0 @@
package com.Acrobot.Breeze.Serialization;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @author Acrobot
*/
public class Encoder {
/**
* Encodes a serializable object
*
* @param serializable Object to serialize
* @return Serialized object
*/
public static String toString(Serializable serializable) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ObjectOutputStream stream = new ObjectOutputStream(baos);
stream.writeObject(serializable);
stream.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
return Base64.encodeBase64String(baos.toByteArray());
}
}

View File

@ -0,0 +1,54 @@
package com.Acrobot.Breeze.Utils.Encoding;
/**
* Base62 encoding class
*
* @author Acrobot
*/
public class Base62 {
private static String ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static int BASE = ALPHABET.length();
/**
* Encodes a number to Base62 string
*
* @param number Number to encode
* @return Encoded number
*/
public static String encode(int number) {
if (number == 0) {
return ALPHABET.substring(0, 1);
}
StringBuilder code = new StringBuilder(16);
while (number > 0) {
int remainder = number % BASE;
number /= BASE;
code.append(ALPHABET.charAt(remainder));
}
return code.reverse().toString();
}
/**
* Decodes a Base62 string
*
* @param code Code to decode
* @return Decoded code
*/
public static int decode(String code) {
int number = 0;
for (int i = 0; i < code.length(); i++) {
int power = code.length() - (i + 1);
number += ALPHABET.indexOf(code.charAt(i)) * Math.pow(BASE, power);
}
return number;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
package com.Acrobot.Breeze.Utils;
import com.Acrobot.ChestShop.ChestShop;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import info.somethingodd.bukkit.OddItem.OddItem;
@ -9,6 +10,7 @@ import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.*;
import java.util.HashMap;
@ -22,6 +24,7 @@ import java.util.regex.Pattern;
public class MaterialUtil {
public static final Pattern DURABILITY = Pattern.compile(":(\\d)*");
public static final Pattern ENCHANTMENT = Pattern.compile("-([0-9a-zA-Z])*");
public static final Pattern METADATA = Pattern.compile("#([0-9a-zA-Z])*");
public static final boolean LONG_NAME = true;
public static final boolean SHORT_NAME = false;
@ -118,8 +121,8 @@ public class MaterialUtil {
name.append(':').append(itemStack.getDurability());
}
if (!itemStack.getEnchantments().isEmpty()) {
name.append('-').append(MaterialUtil.Enchantment.encodeEnchantment(itemStack));
if (!itemStack.hasItemMeta()) {
name.append('#').append(Metadata.getItemCode(itemStack));
}
return StringUtil.capitalizeFirstLetter(name.toString(), '_');
@ -138,7 +141,7 @@ public class MaterialUtil {
return itemStack;
}
String[] split = Iterables.toArray(Splitter.onPattern(":|-").trimResults().split(itemName), String.class);
String[] split = Iterables.toArray(Splitter.onPattern(":|-|#").trimResults().split(itemName), String.class);
Material material = getMaterial(split[0]);
@ -173,7 +176,7 @@ public class MaterialUtil {
itemStack.setDurability(durability);
Map<org.bukkit.enchantments.Enchantment, Integer> enchantments = getEnchantments(itemName);
Map<org.bukkit.enchantments.Enchantment, Integer> enchantments = getEnchantments(itemName); //TODO - it's obsolete, left only for backward compatibility
if (!enchantments.isEmpty()) {
try {
@ -183,6 +186,12 @@ public class MaterialUtil {
}
}
ItemMeta meta = getMetadata(itemName);
if (meta != null) {
itemStack.setItemMeta(meta);
}
return itemStack;
}
@ -227,6 +236,23 @@ public class MaterialUtil {
return Enchantment.getEnchantments(group);
}
/**
* Returns metadata from a string
*
* @param itemName Item name
* @return Metadata found
*/
public static ItemMeta getMetadata(String itemName) {
Matcher m = METADATA.matcher(itemName);
if (!m.find()) {
return null;
}
String group = m.group().substring(1);
return Metadata.getFromCode(group);
}
public static class Enchantment {
/**
* Returns enchantments this itemName contains
@ -397,6 +423,34 @@ public class MaterialUtil {
}
}
public static class Metadata {
/**
* Returns the ItemStack represented by this code
*
* @param code Code representing the item
* @return Item represented by code
*/
public static ItemMeta getFromCode(String code) {
ItemStack item = ChestShop.getItemDatabase().getFromCode(code);
if (item == null) {
return null;
} else {
return item.getItemMeta();
}
}
/**
* Returns the code for this item
*
* @param item Item being represented
* @return Code representing the item
*/
public static String getItemCode(ItemStack item) {
return ChestShop.getItemDatabase().getItemCode(item);
}
}
public static class Odd {
private static boolean isInitialized = false;

View File

@ -11,16 +11,23 @@ import com.Acrobot.ChestShop.DB.Transaction;
import com.Acrobot.ChestShop.Listeners.Block.BlockPlace;
import com.Acrobot.ChestShop.Listeners.Block.Break.ChestBreak;
import com.Acrobot.ChestShop.Listeners.Block.Break.SignBreak;
import com.Acrobot.ChestShop.Listeners.Block.SignChange;
import com.Acrobot.ChestShop.Listeners.Block.SignCreate;
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.PostShopCreation.CreationFeeGetter;
import com.Acrobot.ChestShop.Listeners.PostShopCreation.MessageSender;
import com.Acrobot.ChestShop.Listeners.PostShopCreation.SignSticker;
import com.Acrobot.ChestShop.Listeners.PostTransaction.*;
import com.Acrobot.ChestShop.Listeners.PreShopCreation.*;
import com.Acrobot.ChestShop.Listeners.PreTransaction.*;
import com.Acrobot.ChestShop.Listeners.PreTransaction.ErrorMessageSender;
import com.Acrobot.ChestShop.Listeners.PreTransaction.PermissionChecker;
import com.Acrobot.ChestShop.Listeners.ShopRefundListener;
import com.Acrobot.ChestShop.Logging.FileFormatter;
import com.Acrobot.ChestShop.Metadata.ItemDatabase;
import com.Acrobot.ChestShop.Signs.RestrictedSign;
import com.Acrobot.ChestShop.Utils.uName;
import com.avaje.ebean.EbeanServer;
@ -48,15 +55,15 @@ import java.util.logging.Logger;
* @author Acrobot
*/
public class ChestShop extends JavaPlugin {
public static File dataFolder;
public static com.Acrobot.Breeze.Database.Database data;
private static EbeanServer database;
private static PluginDescriptionFile description;
private static Server server;
private static Logger logger;
private static ChestShop plugin;
private static Server server;
private static PluginDescriptionFile description;
private static File dataFolder;
private static EbeanServer database;
private static ItemDatabase itemDatabase;
private static Logger logger;
private FileHandler handler;
public void onEnable() {
@ -66,6 +73,8 @@ public class ChestShop extends JavaPlugin {
description = getDescription();
server = getServer();
itemDatabase = new ItemDatabase();
Configuration.pairFileAndClass(loadFile("config.yml"), Properties.class);
Configuration.pairFileAndClass(loadFile("local.yml"), Messages.class);
@ -151,43 +160,73 @@ public class ChestShop extends JavaPlugin {
private void registerEvents() {
registerEvent(new com.Acrobot.ChestShop.Plugins.ChestShop()); //Chest protection
registerPreShopCreationEvents();
registerPreTransactionEvents();
registerPostShopCreationEvents();
registerPostTransactionEvents();
registerEvent(new SignBreak());
registerEvent(new SignCreate());
registerEvent(new ChestBreak());
registerEvent(new BlockPlace());
registerEvent(new SignChange());
registerEvent(new PlayerConnect());
registerEvent(new PlayerInteract());
registerEvent(new PlayerInventory());
registerEvent(new ItemInfoListener());
registerEvent(new EmptyShopDeleter());
registerEvent(new TransactionLogger());
registerEvent(new TransactionMessageSender());
registerEvent(new EconomicModule());
registerEvent(new ItemManager());
registerEvent(new CreativeModeIgnorer());
registerEvent(new PermissionChecker());
registerEvent(new PriceValidator());
registerEvent(new ShopValidator());
registerEvent(new StockFittingChecker());
registerEvent(new ErrorMessageSender());
registerEvent(new SpamClickProtector());
registerEvent(new RestrictedSign());
registerEvent(new DiscountModule());
registerEvent(new ShopRefundListener());
registerEvent(new ShortNameSaver());
}
private void registerPreShopCreationEvents() {
if (Properties.BLOCK_SHOPS_WITH_SELL_PRICE_HIGHER_THAN_BUY_PRICE) {
registerEvent(new PriceRatioChecker());
}
registerEvent(new ChestChecker());
registerEvent(new ItemChecker());
registerEvent(new MoneyChecker());
registerEvent(new NameChecker());
registerEvent(new com.Acrobot.ChestShop.Listeners.PreShopCreation.PermissionChecker());
registerEvent(new com.Acrobot.ChestShop.Listeners.PreShopCreation.ErrorMessageSender());
registerEvent(new PriceChecker());
registerEvent(new QuantityChecker());
registerEvent(new TerrainChecker());
}
private void registerPostShopCreationEvents() {
registerEvent(new CreationFeeGetter());
registerEvent(new MessageSender());
registerEvent(new SignSticker());
}
private void registerPreTransactionEvents() {
if (Properties.ALLOW_PARTIAL_TRANSACTIONS) {
registerEvent(new PartialTransactionModule());
} else {
registerEvent(new AmountAndPriceChecker());
}
registerEvent(new ShortNameSaver());
registerEvent(new CreativeModeIgnorer());
registerEvent(new DiscountModule());
registerEvent(new ErrorMessageSender());
registerEvent(new PermissionChecker());
registerEvent(new PriceValidator());
registerEvent(new ShopValidator());
registerEvent(new SpamClickProtector());
registerEvent(new StockFittingChecker());
}
private void registerPostTransactionEvents() {
registerEvent(new EconomicModule());
registerEvent(new EmptyShopDeleter());
registerEvent(new ItemManager());
registerEvent(new TransactionLogger());
registerEvent(new TransactionMessageSender());
}
public void registerEvent(Listener listener) {
@ -237,8 +276,13 @@ public class ChestShop extends JavaPlugin {
public EbeanServer getDatabase() {
return database;
}
///////////////////////////////////////////////////////////////////////////////
public static ItemDatabase getItemDatabase() {
return itemDatabase;
}
public static File getFolder() {
return dataFolder;
}
@ -267,6 +311,10 @@ public class ChestShop extends JavaPlugin {
return description.getSoftDepend();
}
public static ChestShop getPlugin() {
return plugin;
}
public static void registerListener(Listener listener) {
plugin.registerEvent(listener);
}

View File

@ -36,10 +36,10 @@ public class ItemInfo implements CommandExecutor {
}
String durability = getDurability(item);
String enchantment = getEnchantment(item);
String metadata = getMetadata(item);
sender.sendMessage(Messages.prefix(iteminfo));
sender.sendMessage(getNameAndID(item) + durability + enchantment + ChatColor.WHITE);
sender.sendMessage(getNameAndID(item) + durability + metadata + ChatColor.WHITE);
ItemInfoEvent event = new ItemInfoEvent(sender, item);
ChestShop.callEvent(event);
@ -61,13 +61,11 @@ public class ItemInfo implements CommandExecutor {
}
}
private static String getEnchantment(ItemStack item) {
String encodedEnchantments = MaterialUtil.Enchantment.encodeEnchantment(item);
if (encodedEnchantments != null) {
return ChatColor.DARK_AQUA + "-" + encodedEnchantments;
} else {
private static String getMetadata(ItemStack item) {
if (!item.hasItemMeta()) {
return "";
}
return ChatColor.GOLD + "#" + MaterialUtil.Metadata.getItemCode(item);
}
}

View File

@ -17,11 +17,13 @@ public class Messages {
public static String NOT_ENOUGH_MONEY = "You don't have enough money!";
public static String NOT_ENOUGH_MONEY_SHOP = "Shop owner doesn't have enough money!";
public static String DEPOSIT_FAILED = "Money deposit to shop owner failed!";
public static String DEPOSIT_FAILED_OWNER = "Money deposit to your account failed, shop transaction aborted!";
public static byte NEWLINE_NOT_ENOUGH_MONEY_SHO; ///////////////////////////////////////////////////
public static byte NEWLINE_NOT_ENOUGH_MONEY_SHOP; ///////////////////////////////////////////////////
public static String CLIENT_DEPOSIT_FAILED = "Money deposit to your account failed!";
public static String SHOP_DEPOSIT_FAILED = "Money deposit to shop owner failed!";
public static byte NEWLINE_SHOP_DEPOSIT_FAILED; ///////////////////////////////////////////////////
public static String NO_BUYING_HERE = "You can't buy here!";
public static String NO_SELLING_HERE = "You can't sell here!";
@ -58,6 +60,7 @@ public class Messages {
public static String PROTECTED_SHOP = "Successfully protected the shop with LWC!";
public static String SHOP_CREATED = "Shop successfully created!";
public static String SHOP_FEE_PAID = "You have been charged %amount";
public static String SHOP_REFUNDED = "You have been refunded %amount.";
public static byte NEWLINE_SHOP_REFUNDED; ///////////////////////////////////////////////////

View File

@ -27,6 +27,10 @@ public class PreShopCreationEvent extends Event {
return outcome != CreationOutcome.SHOP_CREATED_SUCCESSFULLY;
}
public CreationOutcome getOutcome() {
return outcome;
}
public void setOutcome(CreationOutcome outcome) {
this.outcome = outcome;
}

View File

@ -125,7 +125,8 @@ public class PreTransactionEvent extends Event {
CLIENT_DOES_NOT_HAVE_ENOUGH_MONEY,
SHOP_DOES_NOT_HAVE_ENOUGH_MONEY,
/** not enough space in shop's account for money deposit on sell */
CLIENT_DEPOSIT_FAILED,
SHOP_DEPOSIT_FAILED,
NOT_ENOUGH_SPACE_IN_CHEST,

View File

@ -27,6 +27,10 @@ public class ShopCreatedEvent extends Event {
this.signLines = signLines.clone();
}
public String getSignLine(short line) {
return signLines[line];
}
public String[] getSignLines() {
return signLines;
}

View File

@ -40,7 +40,7 @@ import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
* @author Acrobot
*/
public class SignBreak implements Listener {
private static final BlockFace[] SIGN_CONNECTION_FACES = {BlockFace.SOUTH, BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST};
private static final BlockFace[] SIGN_CONNECTION_FACES = {BlockFace.SOUTH, BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP};
@EventHandler(ignoreCancelled = true)
public static void onSignBreak(BlockBreakEvent event) {

View File

@ -1,266 +0,0 @@
package com.Acrobot.ChestShop.Listeners.Block;
import com.Acrobot.Breeze.Utils.BlockUtil;
import com.Acrobot.Breeze.Utils.MaterialUtil;
import com.Acrobot.Breeze.Utils.PriceUtil;
import com.Acrobot.Breeze.Utils.StringUtil;
import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Configuration.MaxPrice;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Economy.Economy;
import com.Acrobot.ChestShop.Events.Protection.BuildPermissionEvent;
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.Security;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
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;
import org.bukkit.event.EventHandler;
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.Configuration.Messages.*;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
/**
* @author Acrobot
*/
public class SignChange implements Listener {
@EventHandler(ignoreCancelled = true)
public static void onSignChange(SignChangeEvent event) {
Block signBlock = event.getBlock();
String[] line = event.getLines();
if (!BlockUtil.isSign(signBlock)) {
ChestShop.getBukkitLogger().severe("Player " + event.getPlayer().getName() + " tried to create a fake sign. Hacking?");
return;
}
ItemStack stock = MaterialUtil.getItem(line[ITEM_LINE]);
if (!ChestShopSign.isValidPreparedSign(line)) {
return;
}
if (stock == null) {
sendMessageAndExit(INCORRECT_ITEM_ID, event);
return;
}
Player player = event.getPlayer();
boolean isAdmin = Permission.has(player, Permission.ADMIN);
if (!playerCanUseName(player, line[NAME_LINE])) {
event.setLine(NAME_LINE, uName.stripName(player.getName()));
}
String formattedPrice = formatPriceLine(line[PRICE_LINE]);
if (formattedPrice == null) {
sendMessageAndExit(YOU_CANNOT_CREATE_SHOP, event);
return;
}
event.setLine(PRICE_LINE, formattedPrice);
event.setLine(ITEM_LINE, formatItemLine(line[ITEM_LINE], stock));
Chest connectedChest = uBlock.findConnectedChest(signBlock);
if (!isAdminShop(line[NAME_LINE])) {
if (connectedChest == null) {
sendMessageAndExit(NO_CHEST_DETECTED, event);
return;
}
if (!isAdmin && !Security.canPlaceSign(player, (Sign) signBlock.getState())) {
sendMessageAndExit(CANNOT_CREATE_SHOP_HERE, event);
return;
}
BuildPermissionEvent bEvent = new BuildPermissionEvent(player, connectedChest.getLocation(), signBlock.getLocation());
ChestShop.callEvent(bEvent);
if (!bEvent.isAllowed()) {
sendMessageAndExit(CANNOT_CREATE_SHOP_HERE, event);
return;
}
if (!isAdmin && !Security.canAccess(player, connectedChest.getBlock())) {
sendMessageAndExit(CANNOT_ACCESS_THE_CHEST, event);
return;
}
}
double buyPrice = PriceUtil.getBuyPrice(formattedPrice);
double sellPrice = PriceUtil.getSellPrice(formattedPrice);
if (buyPrice == 0 && sellPrice == 0) {
sendMessageAndExit(YOU_CANNOT_CREATE_SHOP, event);
return;
}
if (!isAdmin && (!canCreateShop(player, stock.getType(), buyPrice, sellPrice) || !MaxPrice.canCreate(buyPrice, sellPrice, stock.getType()))) {
sendMessageAndExit(YOU_CANNOT_CREATE_SHOP, event);
return;
}
double shopCreationPrice = Properties.SHOP_CREATION_PRICE;
if (shopCreationPrice != 0 && !ChestShopSign.isAdminShop(line[NAME_LINE]) && !Permission.has(player, Permission.NOFEE)) {
if (!Economy.hasEnough(player.getName(), shopCreationPrice)) {
sendMessageAndExit(NOT_ENOUGH_MONEY, event);
return;
}
Economy.subtract(player.getName(), shopCreationPrice);
player.sendMessage(Messages.prefix(Messages.SHOP_CREATED + " - " + Economy.formatBalance(shopCreationPrice)));
} else {
player.sendMessage(Messages.prefix(Messages.SHOP_CREATED));
}
if (!isAdminShop(line[NAME_LINE]) && Properties.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 (Properties.BLOCK_SHOPS_WITH_SELL_PRICE_HIGHER_THAN_BUY_PRICE) {
if (buyPrice != NO_PRICE && sellPrice != NO_PRICE && sellPrice > buyPrice) {
return false;
}
}
return canCreateShop(player, mat, buyPrice != -1, sellPrice != -1) && MaxPrice.canCreate(buyPrice, sellPrice, mat);
}
private static boolean canCreateShop(Player player, Material material, boolean buy, boolean sell) {
if (Permission.has(player, Permission.SHOP_CREATION_ID + Integer.toString(material.getId()))) {
return true;
}
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;
String[] split = line.toUpperCase().split(":");
if (PriceUtil.isPrice(split[0])) {
line = "B " + line;
}
if (split.length == 2 && PriceUtil.isPrice(split[1])) {
line += " S";
}
if (line.length() > 15) {
line = line.replace(" ", "");
}
line = line.replace('b', 'B').replace('s', 'S');
return (line.length() > 15 ? null : line);
}
private static String formatItemLine(String line, ItemStack item) {
if (MaterialUtil.Odd.getFromString(line) != null) {
return line;
}
String formatted, data = "";
String[] split = line.split(":|-", 2);
if (MaterialUtil.ENCHANTMENT.matcher(line).matches()) {
data = '-' + MaterialUtil.ENCHANTMENT.matcher(line).group();
}
String longItemName = MaterialUtil.getName(item, true);
ItemStack formattedItem = MaterialUtil.getItem(longItemName + data);
if (longItemName.length() < (15 - data.length()) && formattedItem != null && MaterialUtil.equals(formattedItem, item)) {
return StringUtil.capitalizeFirstLetter(longItemName + data);
}
formatted = MaterialUtil.getName(item, false);
data = (split.length == 2 ? split[1] : "");
if (formatted.length() > (15 - 1 - data.length())) {
formatted = formatted.substring(0, (15 - 1 - data.length()));
}
formattedItem = MaterialUtil.getItem(formatted);
if (formattedItem == null || formattedItem.getType() != item.getType()) {
formatted = String.valueOf(item.getTypeId());
}
if (split.length == 2) {
int dataValuePos = line.indexOf(split[1], split[0].length());
formatted += line.charAt(dataValuePos - 1) + split[1];
}
return StringUtil.capitalizeFirstLetter(formatted);
}
private static boolean playerCanUseName(Player player, String name) {
return !name.isEmpty() && (uName.canUseName(player, name) || Permission.has(player, Permission.ADMIN));
}
private static void sendMessageAndExit(String message, SignChangeEvent event) {
event.getPlayer().sendMessage(Messages.prefix(message));
dropSign(event);
}
private static void dropSign(SignChangeEvent event) {
event.setCancelled(true);
event.getBlock().breakNaturally();
}
}

View File

@ -0,0 +1,48 @@
package com.Acrobot.ChestShop.Listeners.Block;
import com.Acrobot.Breeze.Utils.BlockUtil;
import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.SignChangeEvent;
/**
* @author Acrobot
*/
public class SignCreate implements Listener {
@EventHandler
public static void onSignChange(SignChangeEvent event) {
Block signBlock = event.getBlock();
String[] line = event.getLines();
if (!BlockUtil.isSign(signBlock)) {
ChestShop.getBukkitLogger().severe("Player " + event.getPlayer().getName() + " tried to create a fake sign. Hacking?");
return;
}
if (!ChestShopSign.isValidPreparedSign(line)) {
return;
}
PreShopCreationEvent preEvent = new PreShopCreationEvent(event.getPlayer(), (Sign) signBlock.getState(), line);
ChestShop.callEvent(preEvent);
if (preEvent.isCancelled()) {
return;
}
for (byte i = 0; i < event.getLines().length; ++i) {
event.setLine(i, preEvent.getSignLine(i));
}
ShopCreatedEvent postEvent = new ShopCreatedEvent(preEvent.getPlayer(), preEvent.getSign(), uBlock.findConnectedChest(preEvent.getSign()), preEvent.getSignLines());
ChestShop.callEvent(postEvent);
}
}

View File

@ -41,7 +41,13 @@ public class ItemInfoListener implements Listener {
return;
}
Potion potion = Potion.fromItemStack(item);
Potion potion;
try {
potion = Potion.fromItemStack(item);
} catch (IllegalArgumentException ex) {
return;
}
StringBuilder message = new StringBuilder(50);

View File

@ -30,9 +30,11 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import static com.Acrobot.Breeze.Utils.BlockUtil.*;
import static com.Acrobot.Breeze.Utils.BlockUtil.isChest;
import static com.Acrobot.Breeze.Utils.BlockUtil.isSign;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.*;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.BUY;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.SELL;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
import static org.bukkit.event.block.Action.LEFT_CLICK_BLOCK;
import static org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK;

View File

@ -0,0 +1,43 @@
package com.Acrobot.ChestShop.Listeners.PostShopCreation;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Economy.Economy;
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import static com.Acrobot.ChestShop.Permission.NOFEE;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
/**
* @author Acrobot
*/
public class CreationFeeGetter implements Listener {
@EventHandler
public static void onShopCreation(ShopCreatedEvent event) {
double shopCreationPrice = Properties.SHOP_CREATION_PRICE;
if (shopCreationPrice == 0) {
return;
}
if (ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE))) {
return;
}
Player player = event.getPlayer();
if (Permission.has(player, NOFEE)) {
return;
}
Economy.subtract(player.getName(), shopCreationPrice);
player.sendMessage(Messages.prefix(Messages.SHOP_FEE_PAID.replace("%amount", Double.toString(shopCreationPrice))));
}
}

View File

@ -0,0 +1,18 @@
package com.Acrobot.ChestShop.Listeners.PostShopCreation;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
/**
* @author Acrobot
*/
public class MessageSender implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public static void onShopCreation(ShopCreatedEvent event) {
event.getPlayer().sendMessage(Messages.prefix(Messages.SHOP_CREATED));
}
}

View File

@ -0,0 +1,66 @@
package com.Acrobot.ChestShop.Listeners.PostShopCreation;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
/**
* @author Acrobot
*/
public class SignSticker implements Listener {
@EventHandler
public static void onShopCreation(ShopCreatedEvent event) {
if (!Properties.STICK_SIGNS_TO_CHESTS) {
return;
}
if (ChestShopSign.isAdminShop(event.getSign().getLine(NAME_LINE))) {
return;
}
stickSign(event.getSign().getBlock(), event.getSignLines());
}
private static void stickSign(Block signBlock, String[] lines) {
if (signBlock.getType() != Material.SIGN_POST) {
return;
}
BlockFace chestFace = null;
for (BlockFace face : uBlock.CHEST_EXTENSION_FACES) {
if (signBlock.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());
signBlock.setType(Material.WALL_SIGN);
signBlock.setData(signMaterial.getData());
Sign sign = (Sign) signBlock.getState();
for (int i = 0; i < lines.length; ++i) {
sign.setLine(i, lines[i]);
}
sign.update(true);
}
}

View File

@ -0,0 +1,57 @@
package com.Acrobot.ChestShop.Listeners.PreShopCreation;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
/**
* @author Acrobot
*/
public class ErrorMessageSender implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public static void onPreShopCreation(PreShopCreationEvent event) {
if (!event.isCancelled()) {
return;
}
String message = null;
switch (event.getOutcome()) {
case INVALID_ITEM:
message = Messages.INCORRECT_ITEM_ID;
break;
case INVALID_PRICE:
message = Messages.INVALID_SHOP_DETECTED;
break;
case INVALID_QUANTITY:
message = Messages.INVALID_SHOP_DETECTED;
break;
case SELL_PRICE_HIGHER_THAN_BUY_PRICE:
message = Messages.YOU_CANNOT_CREATE_SHOP;
break;
case NO_CHEST:
message = Messages.NO_CHEST_DETECTED;
break;
case NO_PERMISSION:
message = Messages.NO_PERMISSION;
break;
case NO_PERMISSION_FOR_TERRAIN:
message = Messages.CANNOT_CREATE_SHOP_HERE;
break;
case NO_PERMISSION_FOR_CHEST:
message = Messages.CANNOT_ACCESS_THE_CHEST;
break;
case NOT_ENOUGH_MONEY:
message = Messages.NOT_ENOUGH_MONEY;
break;
}
if (message != null) {
event.getPlayer().sendMessage(Messages.prefix(message));
event.getSign().getBlock().breakNaturally();
}
}
}

View File

@ -8,6 +8,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import java.util.regex.Matcher;
import static com.Acrobot.Breeze.Utils.MaterialUtil.*;
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.INVALID_ITEM;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
@ -32,12 +34,12 @@ public class ItemChecker implements Listener {
return; // The OddItem name is OK
}
String enchantment = getEnchantment(itemCode);
String metadata = getMetadata(itemCode);
String longName = MaterialUtil.getName(item, LONG_NAME);
if (longName.length() <= (MAXIMUM_SIGN_LETTERS - enchantment.length())) {
if (isStillValidItem(longName + enchantment, item)) {
String itemName = StringUtil.capitalizeFirstLetter(longName + enchantment);
if (longName.length() <= (MAXIMUM_SIGN_LETTERS - metadata.length())) {
if (isStillValidItem(longName + metadata, item)) {
String itemName = StringUtil.capitalizeFirstLetter(longName + metadata);
event.setSignLine(ITEM_LINE, itemName);
return;
@ -46,10 +48,10 @@ public class ItemChecker implements Listener {
String code = MaterialUtil.getName(item, SHORT_NAME);
String[] parts = itemCode.split("(?=:|-)", 2);
String[] parts = itemCode.split("(?=:|-|#)", 2);
String data = (parts.length > 1 ? parts[1] : "");
if (code.length() > (MAXIMUM_SIGN_LETTERS - 1 - data.length())) {
if (!data.isEmpty() && code.length() >= (MAXIMUM_SIGN_LETTERS - 1 - data.length())) {
code = code.substring(0, MAXIMUM_SIGN_LETTERS - 1 - data.length()) + data;
}
@ -68,11 +70,13 @@ public class ItemChecker implements Listener {
return newItem != null && MaterialUtil.equals(newItem, item);
}
private static String getEnchantment(String itemCode) {
if (!ENCHANTMENT.matcher(itemCode).matches()) {
private static String getMetadata(String itemCode) {
Matcher m = METADATA.matcher(itemCode);
if (!m.find()) {
return "";
}
return '-' + ENCHANTMENT.matcher(itemCode).group();
return m.group();
}
}

View File

@ -1,6 +1,7 @@
package com.Acrobot.ChestShop.Listeners.PreShopCreation;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Economy.Economy;
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
@ -8,6 +9,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.NOT_ENOUGH_MONEY;
import static com.Acrobot.ChestShop.Permission.NOFEE;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
@ -34,6 +36,8 @@ public class MoneyChecker implements Listener {
return;
}
if (!Economy.hasEnough(player.getName(), shopCreationPrice)) {
event.setOutcome(NOT_ENOUGH_MONEY);
}
}
}

View File

@ -1,5 +1,6 @@
package com.Acrobot.ChestShop.Listeners.PreTransaction;
import com.Acrobot.Breeze.Utils.InventoryUtil;
import com.Acrobot.Breeze.Utils.MaterialUtil;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Configuration.Properties;
@ -11,10 +12,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import java.util.LinkedList;
import java.util.List;
import static com.Acrobot.ChestShop.Configuration.Messages.*;
import static com.Acrobot.ChestShop.Configuration.Messages.CLIENT_DEPOSIT_FAILED;
import static com.Acrobot.ChestShop.Configuration.Messages.NOT_ENOUGH_STOCK_IN_YOUR_SHOP;
/**
* @author Acrobot
@ -58,10 +57,13 @@ public class ErrorMessageSender implements Listener {
sendMessageToOwner(event.getOwner(), messageOutOfStock);
message = Messages.NOT_ENOUGH_STOCK;
break;
case CLIENT_DEPOSIT_FAILED:
message = Messages.CLIENT_DEPOSIT_FAILED;
break;
case SHOP_DEPOSIT_FAILED:
String messageDepositFailed = Messages.prefix(DEPOSIT_FAILED);
String messageDepositFailed = Messages.prefix(CLIENT_DEPOSIT_FAILED);
sendMessageToOwner(event.getOwner(), messageDepositFailed);
message = DEPOSIT_FAILED;
message = Messages.SHOP_DEPOSIT_FAILED;
break;
case SHOP_IS_RESTRICTED:
message = Messages.ACCESS_DENIED;
@ -69,16 +71,6 @@ public class ErrorMessageSender implements Listener {
case INVALID_SHOP:
message = Messages.INVALID_SHOP_DETECTED;
break;
case CREATIVE_MODE_PROTECTION:
break;
case OTHER:
break;
case SPAM_CLICKING_PROTECTION:
break;
case TRANSACTION_SUCCESFUL:
break;
default:
break;
}
if (message != null) {
@ -87,22 +79,7 @@ public class ErrorMessageSender implements Listener {
}
private static String getItemNames(ItemStack[] stock) {
List<ItemStack> items = new LinkedList<ItemStack>();
for (ItemStack stack : stock) {
boolean hadItem = false;
for (ItemStack item : items) {
if (MaterialUtil.equals(stack, item)) {
item.setAmount(item.getAmount() + stack.getAmount());
hadItem = true;
}
}
if (!hadItem) {
items.add(stack.clone());
}
}
ItemStack[] items = InventoryUtil.mergeSimilarStacks(stock);
StringBuilder names = new StringBuilder(50);

View File

@ -47,16 +47,14 @@ public class PartialTransactionModule implements Listener {
event.setPrice(amountAffordable * pricePerItem);
event.setStock(getCountedItemStack(stock, amountAffordable));
}
String seller = event.getOwner().getName();
boolean added = Economy.add(seller, price);
if (added) {
// added amount successfully, owner has enough space for deposit
// --> undo the add, for some other event to actually do.
Economy.subtract(seller, price);
if (Economy.add(seller, price)) {
Economy.subtract(seller, price); //Cash can be safely deposited
} else {
event.setCancelled(SHOP_DEPOSIT_FAILED);
return;
event.setCancelled(SHOP_DEPOSIT_FAILED);
return;
}
stock = event.getStock();
@ -81,6 +79,7 @@ public class PartialTransactionModule implements Listener {
return;
}
String player = event.getClient().getName();
String ownerName = event.getOwner().getName();
ItemStack[] stock = event.getStock();
@ -102,6 +101,13 @@ public class PartialTransactionModule implements Listener {
stock = event.getStock();
if (Economy.add(player, price)) {
Economy.subtract(player, price); //Cash can be safely deposited
} else {
event.setCancelled(CLIENT_DEPOSIT_FAILED);
return;
}
if (!InventoryUtil.hasItems(stock, event.getClientInventory())) {
ItemStack[] itemsHad = getItems(stock, event.getClientInventory());
int posessedItemCount = InventoryUtil.countItems(itemsHad);

View File

@ -0,0 +1,97 @@
package com.Acrobot.ChestShop.Metadata;
import com.Acrobot.Breeze.Database.Database;
import com.Acrobot.Breeze.Database.Row;
import com.Acrobot.Breeze.Database.Table;
import com.Acrobot.Breeze.Utils.Encoding.Base62;
import com.Acrobot.Breeze.Utils.Encoding.Base64;
import com.Acrobot.ChestShop.ChestShop;
import org.bukkit.configuration.file.YamlConstructor;
import org.bukkit.configuration.file.YamlRepresenter;
import org.bukkit.inventory.ItemStack;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Saves items with Metadata in database, which allows for saving items on signs easily.
* @author Acrobot
*/
public class ItemDatabase {
private Yaml yaml;
private Table table;
public ItemDatabase() {
Database database = new Database("jdbc:sqlite:" + new File(ChestShop.getFolder(), "items.db").getAbsolutePath());
yaml = new Yaml(new YamlConstructor(), new YamlRepresenter(), new DumperOptions());
try {
Statement statement = database.getConnection().createStatement();
statement.executeUpdate("PRAGMA user_version = 1"); //We'll be able to change it later if we need to
} catch (SQLException e) {
e.printStackTrace();
}
try {
table = database.getTable("items");
table.create("id INTEGER PRIMARY KEY, code VARCHAR UNIQUE ON CONFLICT IGNORE");
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Gets the item code for this item
*
* @param item Item
* @return Item code for this item
*/
public String getItemCode(ItemStack item) {
try {
String code = Base64.encodeObject(yaml.dump(item));
table.insertRow("null, '" + code + '\'');
int id = Integer.parseInt(table.getRow("code='" + code + '\'').get("id"));
return Base62.encode(id);
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
/**
* Gets an ItemStack from a item code
*
* @param code Item code
* @return ItemStack represented by this code
*/
public ItemStack getFromCode(String code) {
try {
Row row = table.getRow("id='" + Base62.decode(code) + '\'');
if (row.getSize() == 0) {
return null;
}
String serialized = row.get("code");
return (ItemStack) yaml.load((String) Base64.decodeToObject(serialized));
} catch (SQLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -241,7 +241,7 @@ public class Metrics {
task.cancel();
task = null;
// Tell all plotters to stop gathering information.
for (Graph graph : graphs){
for (Graph graph : graphs) {
graph.onOptOut();
}
}
@ -273,7 +273,7 @@ public class Metrics {
* @return true if metrics should be opted out of it
*/
public boolean isOptOut() {
synchronized(optOutLock) {
synchronized (optOutLock) {
try {
// Reload the metrics file
configuration.load(getConfigFile());
@ -491,8 +491,8 @@ public class Metrics {
* </code>
*
* @param buffer the stringbuilder to append the data pair onto
* @param key the key value
* @param value the value
* @param key the key value
* @param value the value
*/
private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException {
buffer.append('&').append(encode(key)).append('=').append(encode(value));

View File

@ -27,7 +27,7 @@ public class ChestShopSign {
Pattern.compile("^[\\w -.]*$"),
Pattern.compile("^[1-9][0-9]*$"),
Pattern.compile("(?i)^[\\d.bs(free) :]+$"),
Pattern.compile("^[\\w : -]+$")
Pattern.compile("^[\\w #:-]+$")
};
public static boolean isAdminShop(Inventory ownerInventory) {