mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-12-23 01:21:47 +00:00
Database improvements
- Support table prefixes (Fixes #138) - Support amounts above 127 in Paper (Fixes #149) - Split UUID, name and shop type in economy log - Split product and amount in economy log (Fixes #143) - Added product data (Base64) to economy log
This commit is contained in:
parent
4c6c87dc08
commit
6ae12f65c0
@ -13,6 +13,7 @@ import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.language.Message;
|
||||
import de.epiceric.shopchest.language.Replacement;
|
||||
import de.epiceric.shopchest.shop.Shop;
|
||||
import de.epiceric.shopchest.shop.ShopProduct;
|
||||
import de.epiceric.shopchest.utils.Callback;
|
||||
import de.epiceric.shopchest.utils.ClickType;
|
||||
import de.epiceric.shopchest.utils.ItemUtils;
|
||||
@ -354,11 +355,8 @@ class ShopCommandExecutor implements CommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack product = new ItemStack(inHand.getType(), amount, inHand.getDurability());
|
||||
product.setItemMeta(inHand.getItemMeta());
|
||||
|
||||
if (Enchantment.DURABILITY.canEnchantItem(product)) {
|
||||
if (product.getDurability() > 0 && !Config.allowBrokenItems) {
|
||||
if (Enchantment.DURABILITY.canEnchantItem(inHand)) {
|
||||
if (inHand.getDurability() > 0 && !Config.allowBrokenItems) {
|
||||
p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_BROKEN_ITEM));
|
||||
plugin.debug(p.getName() + "'s item is broken");
|
||||
return;
|
||||
@ -374,6 +372,7 @@ class ShopCommandExecutor implements CommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
ShopProduct product = new ShopProduct(inHand, amount);
|
||||
ShopPreCreateEvent event = new ShopPreCreateEvent(p, new Shop(plugin, p, product, null, buyPrice, sellPrice, shopType));
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
|
@ -87,7 +87,12 @@ public class Config {
|
||||
public static String databaseMySqlPassword;
|
||||
|
||||
/**
|
||||
* The database type used for ShopChest.
|
||||
* The prefix to be used for database tables
|
||||
*/
|
||||
public static String databaseTablePrefix;
|
||||
|
||||
/**
|
||||
* The database type used for ShopChest
|
||||
**/
|
||||
public static Database.DatabaseType databaseType;
|
||||
|
||||
@ -474,6 +479,7 @@ public class Config {
|
||||
databaseMySqlDatabase = plugin.getConfig().getString("database.mysql.database");
|
||||
databaseMySqlUsername = plugin.getConfig().getString("database.mysql.username");
|
||||
databaseMySqlPassword = plugin.getConfig().getString("database.mysql.password");
|
||||
databaseTablePrefix = plugin.getConfig().getString("database.table-prefix");
|
||||
databaseType = Database.DatabaseType.valueOf(plugin.getConfig().getString("database.type"));
|
||||
minimumPrices = (plugin.getConfig().getConfigurationSection("minimum-prices") == null) ? new HashSet<String>() : plugin.getConfig().getConfigurationSection("minimum-prices").getKeys(true);
|
||||
maximumPrices = (plugin.getConfig().getConfigurationSection("maximum-prices") == null) ? new HashSet<String>() : plugin.getConfig().getConfigurationSection("maximum-prices").getKeys(true);
|
||||
|
@ -57,8 +57,7 @@ public class NotifyPlayerOnJoinListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
long time = System.currentTimeMillis();
|
||||
plugin.getShopDatabase().logLogout(e.getPlayer(), time, null);
|
||||
plugin.getShopDatabase().logLogout(e.getPlayer(), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import de.epiceric.shopchest.language.Replacement;
|
||||
import de.epiceric.shopchest.nms.Hologram;
|
||||
import de.epiceric.shopchest.nms.JsonBuilder;
|
||||
import de.epiceric.shopchest.shop.Shop;
|
||||
import de.epiceric.shopchest.shop.ShopProduct;
|
||||
import de.epiceric.shopchest.shop.Shop.ShopType;
|
||||
import de.epiceric.shopchest.sql.Database;
|
||||
import de.epiceric.shopchest.utils.ClickType;
|
||||
@ -301,7 +302,7 @@ public class ShopInteractListener implements Listener {
|
||||
|
||||
if (b.getRelative(BlockFace.UP).getType() == Material.AIR) {
|
||||
ClickType clickType = ClickType.getPlayerClickType(p);
|
||||
ItemStack product = clickType.getProduct();
|
||||
ShopProduct product = clickType.getProduct();
|
||||
double buyPrice = clickType.getBuyPrice();
|
||||
double sellPrice = clickType.getSellPrice();
|
||||
ShopType shopType = clickType.getShopType();
|
||||
@ -484,9 +485,10 @@ public class ShopInteractListener implements Listener {
|
||||
} else {
|
||||
if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) {
|
||||
Chest c = (Chest) b.getState();
|
||||
int amount = (p.isSneaking() ? shop.getProduct().getMaxStackSize() : shop.getProduct().getAmount());
|
||||
ItemStack itemStack = shop.getProduct().getItemStack();
|
||||
int amount = (p.isSneaking() ? itemStack.getMaxStackSize() : shop.getProduct().getAmount());
|
||||
|
||||
if (Utils.getAmount(c.getInventory(), shop.getProduct()) >= amount) {
|
||||
if (Utils.getAmount(c.getInventory(), itemStack) >= amount) {
|
||||
if (confirmed || !Config.confirmShopping) {
|
||||
buy(p, shop, p.isSneaking());
|
||||
if (Config.confirmShopping) {
|
||||
@ -503,7 +505,7 @@ public class ShopInteractListener implements Listener {
|
||||
needsConfirmation.put(p.getUniqueId(), ids);
|
||||
}
|
||||
} else {
|
||||
if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), shop.getProduct()) > 0) {
|
||||
if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), itemStack) > 0) {
|
||||
if (confirmed || !Config.confirmShopping) {
|
||||
buy(p, shop, p.isSneaking());
|
||||
if (Config.confirmShopping) {
|
||||
@ -524,7 +526,7 @@ public class ShopInteractListener implements Listener {
|
||||
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
|
||||
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.VENDOR_OUT_OF_STOCK,
|
||||
new Replacement(Placeholder.AMOUNT, String.valueOf(shop.getProduct().getAmount())),
|
||||
new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(shop.getProduct()))));
|
||||
new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(itemStack))));
|
||||
}
|
||||
plugin.debug("Shop is out of stock");
|
||||
}
|
||||
@ -569,11 +571,13 @@ public class ShopInteractListener implements Listener {
|
||||
externalPluginsAllowed = WorldGuardWrapper.getInstance().queryStateFlag(p, b.getLocation(), flagName).orElse(false);
|
||||
}
|
||||
|
||||
ItemStack itemStack = shop.getProduct().getItemStack();
|
||||
|
||||
if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) {
|
||||
boolean stack = p.isSneaking() && !Utils.hasAxeInHand(p);
|
||||
int amount = stack ? shop.getProduct().getMaxStackSize() : shop.getProduct().getAmount();
|
||||
int amount = stack ? itemStack.getMaxStackSize() : shop.getProduct().getAmount();
|
||||
|
||||
if (Utils.getAmount(p.getInventory(), shop.getProduct()) >= amount) {
|
||||
if (Utils.getAmount(p.getInventory(), itemStack) >= amount) {
|
||||
if (confirmed || !Config.confirmShopping) {
|
||||
sell(p, shop, stack);
|
||||
if (Config.confirmShopping) {
|
||||
@ -590,7 +594,7 @@ public class ShopInteractListener implements Listener {
|
||||
needsConfirmation.put(p.getUniqueId(), ids);
|
||||
}
|
||||
} else {
|
||||
if (Config.autoCalculateItemAmount && Utils.getAmount(p.getInventory(), shop.getProduct()) > 0) {
|
||||
if (Config.autoCalculateItemAmount && Utils.getAmount(p.getInventory(), itemStack) > 0) {
|
||||
if (confirmed || !Config.confirmShopping) {
|
||||
sell(p, shop, stack);
|
||||
if (Config.confirmShopping) {
|
||||
@ -716,7 +720,7 @@ public class ShopInteractListener implements Listener {
|
||||
* @param sellPrice Sell price
|
||||
* @param shopType Type of the shop
|
||||
*/
|
||||
private void create(final Player executor, final Location location, final ItemStack product, final double buyPrice, final double sellPrice, final ShopType shopType) {
|
||||
private void create(final Player executor, final Location location, final ShopProduct product, final double buyPrice, final double sellPrice, final ShopType shopType) {
|
||||
plugin.debug(executor.getName() + " is creating new shop...");
|
||||
|
||||
if (!executor.hasPermission(Permissions.CREATE)) {
|
||||
@ -825,7 +829,8 @@ public class ShopInteractListener implements Listener {
|
||||
}
|
||||
|
||||
Chest c = (Chest) shop.getLocation().getBlock().getState();
|
||||
int amount = Utils.getAmount(c.getInventory(), shop.getProduct());
|
||||
ItemStack itemStack = shop.getProduct().getItemStack();
|
||||
int amount = Utils.getAmount(c.getInventory(), itemStack);
|
||||
|
||||
String vendorName = (shop.getVendor().getName() == null ?
|
||||
shop.getVendor().getUniqueId().toString() : shop.getVendor().getName());
|
||||
@ -863,21 +868,21 @@ public class ShopInteractListener implements Listener {
|
||||
* @param product The product of the shop
|
||||
* @return A {@link JsonBuilder} that can send the message via {@link JsonBuilder#sendJson(Player)}
|
||||
*/
|
||||
private JsonBuilder getProductJson(ItemStack product) {
|
||||
private JsonBuilder getProductJson(ShopProduct product) {
|
||||
// Add spaces at start and end, so there will always be a part before and after
|
||||
// the item name after splitting at Placeholder.ITEM_NAME
|
||||
String productString = " " + LanguageUtils.getMessage(Message.SHOP_INFO_PRODUCT,
|
||||
new Replacement(Placeholder.AMOUNT, String.valueOf(product.getAmount()))) + " ";
|
||||
|
||||
String[] parts = productString.split(Placeholder.ITEM_NAME.toString());
|
||||
String productName = LanguageUtils.getItemName(product);
|
||||
String productName = LanguageUtils.getItemName(product.getItemStack());
|
||||
String jsonItem = "";
|
||||
JsonBuilder jb = new JsonBuilder(plugin);
|
||||
JsonBuilder.PartArray rootArray = new JsonBuilder.PartArray();
|
||||
|
||||
try {
|
||||
Class<?> craftItemStackClass = Utils.getCraftClass("inventory.CraftItemStack");
|
||||
Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, product);
|
||||
Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, product.getItemStack());
|
||||
Class<?> nbtTagCompoundClass = Utils.getNMSClass("NBTTagCompound");
|
||||
Object nbtTagCompound = nbtTagCompoundClass.getConstructor().newInstance();
|
||||
nmsStack.getClass().getMethod("save", nbtTagCompoundClass).invoke(nmsStack, nbtTagCompound);
|
||||
@ -944,8 +949,9 @@ public class ShopInteractListener implements Listener {
|
||||
private void buy(Player executor, final Shop shop, boolean stack) {
|
||||
plugin.debug(executor.getName() + " is buying (#" + shop.getID() + ")");
|
||||
|
||||
ItemStack itemStack = shop.getProduct().getItemStack();
|
||||
int amount = shop.getProduct().getAmount();
|
||||
if (stack) amount = shop.getProduct().getMaxStackSize();
|
||||
if (stack) amount = itemStack.getMaxStackSize();
|
||||
|
||||
String worldName = shop.getLocation().getWorld().getName();
|
||||
|
||||
@ -966,14 +972,14 @@ public class ShopInteractListener implements Listener {
|
||||
Block b = shop.getLocation().getBlock();
|
||||
Chest c = (Chest) b.getState();
|
||||
|
||||
int amountForChestItems = Utils.getAmount(c.getInventory(), shop.getProduct());
|
||||
int amountForChestItems = Utils.getAmount(c.getInventory(), itemStack);
|
||||
|
||||
if (amountForChestItems == 0 && shop.getShopType() != ShopType.ADMIN) {
|
||||
executor.sendMessage(LanguageUtils.getMessage(Message.OUT_OF_STOCK));
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack product = new ItemStack(shop.getProduct());
|
||||
ItemStack product = new ItemStack(itemStack);
|
||||
if (stack) product.setAmount(amount);
|
||||
|
||||
Inventory inventory = executor.getInventory();
|
||||
@ -996,14 +1002,12 @@ public class ShopInteractListener implements Listener {
|
||||
|
||||
if (newAmount > amount) newAmount = amount;
|
||||
|
||||
ShopProduct newProduct = new ShopProduct(product, newAmount);
|
||||
double newPrice = (price / amount) * newAmount;
|
||||
|
||||
if (freeSpace >= newAmount) {
|
||||
plugin.debug(executor.getName() + " has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
|
||||
|
||||
ItemStack newProduct = new ItemStack(product);
|
||||
newProduct.setAmount(newAmount);
|
||||
|
||||
EconomyResponse r = econ.withdrawPlayer(executor, worldName, newPrice);
|
||||
|
||||
if (r.transactionSuccess()) {
|
||||
@ -1105,8 +1109,9 @@ public class ShopInteractListener implements Listener {
|
||||
private void sell(Player executor, final Shop shop, boolean stack) {
|
||||
plugin.debug(executor.getName() + " is selling (#" + shop.getID() + ")");
|
||||
|
||||
ItemStack itemStack = shop.getProduct().getItemStack();
|
||||
int amount = shop.getProduct().getAmount();
|
||||
if (stack) amount = shop.getProduct().getMaxStackSize();
|
||||
if (stack) amount = itemStack.getMaxStackSize();
|
||||
|
||||
double price = shop.getSellPrice();
|
||||
if (stack) price = (price / shop.getProduct().getAmount()) * amount;
|
||||
@ -1130,14 +1135,14 @@ public class ShopInteractListener implements Listener {
|
||||
Block block = shop.getLocation().getBlock();
|
||||
Chest chest = (Chest) block.getState();
|
||||
|
||||
int amountForItemCount = Utils.getAmount(executor.getInventory(), shop.getProduct());
|
||||
int amountForItemCount = Utils.getAmount(executor.getInventory(), itemStack);
|
||||
|
||||
if (amountForItemCount == 0) {
|
||||
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS));
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack product = new ItemStack(shop.getProduct());
|
||||
ItemStack product = new ItemStack(itemStack);
|
||||
if (stack) product.setAmount(amount);
|
||||
|
||||
Inventory inventory = chest.getInventory();
|
||||
@ -1160,14 +1165,12 @@ public class ShopInteractListener implements Listener {
|
||||
|
||||
if (newAmount > amount) newAmount = amount;
|
||||
|
||||
ShopProduct newProduct = new ShopProduct(product, newAmount);
|
||||
double newPrice = (price / amount) * newAmount;
|
||||
|
||||
if (freeSpace >= newAmount || shop.getShopType() == ShopType.ADMIN) {
|
||||
plugin.debug("Chest has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
|
||||
|
||||
ItemStack newProduct = new ItemStack(product);
|
||||
newProduct.setAmount(newAmount);
|
||||
|
||||
EconomyResponse r = econ.depositPlayer(executor, worldName, newPrice);
|
||||
|
||||
if (r.transactionSuccess()) {
|
||||
@ -1271,11 +1274,12 @@ public class ShopInteractListener implements Listener {
|
||||
* @param itemStack Items to add
|
||||
* @return Whether all items were added to the inventory
|
||||
*/
|
||||
private boolean addToInventory(Inventory inventory, ItemStack itemStack) {
|
||||
private boolean addToInventory(Inventory inventory, ShopProduct product) {
|
||||
plugin.debug("Adding items to inventory...");
|
||||
|
||||
HashMap<Integer, ItemStack> inventoryItems = new HashMap<>();
|
||||
int amount = itemStack.getAmount();
|
||||
ItemStack itemStack = product.getItemStack();
|
||||
int amount = product.getAmount();
|
||||
int added = 0;
|
||||
|
||||
if (inventory instanceof PlayerInventory) {
|
||||
@ -1329,11 +1333,12 @@ public class ShopInteractListener implements Listener {
|
||||
* @param itemStack Items to remove
|
||||
* @return Whether all items were removed from the inventory
|
||||
*/
|
||||
private boolean removeFromInventory(Inventory inventory, ItemStack itemStack) {
|
||||
private boolean removeFromInventory(Inventory inventory, ShopProduct product) {
|
||||
plugin.debug("Removing items from inventory...");
|
||||
|
||||
HashMap<Integer, ItemStack> inventoryItems = new HashMap<>();
|
||||
int amount = itemStack.getAmount();
|
||||
ItemStack itemStack = product.getItemStack();
|
||||
int amount = product.getAmount();
|
||||
int removed = 0;
|
||||
|
||||
if (inventory instanceof PlayerInventory) {
|
||||
|
@ -48,7 +48,7 @@ public class Shop {
|
||||
|
||||
private final ShopChest plugin;
|
||||
private final OfflinePlayer vendor;
|
||||
private final ItemStack product;
|
||||
private final ShopProduct product;
|
||||
private final Location location;
|
||||
private final double buyPrice;
|
||||
private final double sellPrice;
|
||||
@ -60,7 +60,7 @@ public class Shop {
|
||||
private Location holoLocation;
|
||||
private ShopItem item;
|
||||
|
||||
public Shop(int id, ShopChest plugin, OfflinePlayer vendor, ItemStack product, Location location, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
public Shop(int id, ShopChest plugin, OfflinePlayer vendor, ShopProduct product, Location location, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
this.id = id;
|
||||
this.plugin = plugin;
|
||||
this.vendor = vendor;
|
||||
@ -71,7 +71,7 @@ public class Shop {
|
||||
this.shopType = shopType;
|
||||
}
|
||||
|
||||
public Shop(ShopChest plugin, OfflinePlayer vendor, ItemStack product, Location location, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
public Shop(ShopChest plugin, OfflinePlayer vendor, ShopProduct product, Location location, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
this(-1, plugin, vendor, product, location, buyPrice, sellPrice, shopType);
|
||||
}
|
||||
|
||||
@ -179,13 +179,9 @@ public class Shop {
|
||||
plugin.debug("Creating item (#" + id + ")");
|
||||
|
||||
Location itemLocation;
|
||||
ItemStack itemStack;
|
||||
|
||||
itemLocation = new Location(location.getWorld(), holoLocation.getX(), location.getY() + 0.9, holoLocation.getZ());
|
||||
itemStack = product.clone();
|
||||
itemStack.setAmount(1);
|
||||
|
||||
item = new ShopItem(plugin, itemStack, itemLocation);
|
||||
item = new ShopItem(plugin, product.getItemStack(), itemLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,39 +256,41 @@ public class Shop {
|
||||
private String[] getHologramText(Inventory inventory) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
|
||||
ItemStack itemStack = getProduct().getItemStack();
|
||||
|
||||
Map<HologramFormat.Requirement, Object> requirements = new EnumMap<>(HologramFormat.Requirement.class);
|
||||
requirements.put(HologramFormat.Requirement.VENDOR, getVendor().getName());
|
||||
requirements.put(HologramFormat.Requirement.AMOUNT, getProduct().getAmount());
|
||||
requirements.put(HologramFormat.Requirement.ITEM_TYPE, getProduct().getType() + (getProduct().getDurability() > 0 ? ":" + getProduct().getDurability() : ""));
|
||||
requirements.put(HologramFormat.Requirement.ITEM_NAME, getProduct().hasItemMeta() ? getProduct().getItemMeta().getDisplayName() : null);
|
||||
requirements.put(HologramFormat.Requirement.HAS_ENCHANTMENT, !LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(getProduct())).isEmpty());
|
||||
requirements.put(HologramFormat.Requirement.ITEM_TYPE, itemStack.getType() + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : ""));
|
||||
requirements.put(HologramFormat.Requirement.ITEM_NAME, itemStack.hasItemMeta() ? itemStack.getItemMeta().getDisplayName() : null);
|
||||
requirements.put(HologramFormat.Requirement.HAS_ENCHANTMENT, !LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(itemStack)).isEmpty());
|
||||
requirements.put(HologramFormat.Requirement.BUY_PRICE, getBuyPrice());
|
||||
requirements.put(HologramFormat.Requirement.SELL_PRICE, getSellPrice());
|
||||
requirements.put(HologramFormat.Requirement.HAS_POTION_EFFECT, ItemUtils.getPotionEffect(getProduct()) != null);
|
||||
requirements.put(HologramFormat.Requirement.IS_MUSIC_DISC, getProduct().getType().isRecord());
|
||||
requirements.put(HologramFormat.Requirement.IS_POTION_EXTENDED, ItemUtils.isExtendedPotion(getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.IS_WRITTEN_BOOK, getProduct().getType() == Material.WRITTEN_BOOK);
|
||||
requirements.put(HologramFormat.Requirement.HAS_POTION_EFFECT, ItemUtils.getPotionEffect(itemStack) != null);
|
||||
requirements.put(HologramFormat.Requirement.IS_MUSIC_DISC, itemStack.getType().isRecord());
|
||||
requirements.put(HologramFormat.Requirement.IS_POTION_EXTENDED, ItemUtils.isExtendedPotion(itemStack));
|
||||
requirements.put(HologramFormat.Requirement.IS_WRITTEN_BOOK, itemStack.getType() == Material.WRITTEN_BOOK);
|
||||
requirements.put(HologramFormat.Requirement.ADMIN_SHOP, getShopType() == ShopType.ADMIN);
|
||||
requirements.put(HologramFormat.Requirement.NORMAL_SHOP, getShopType() == ShopType.NORMAL);
|
||||
requirements.put(HologramFormat.Requirement.IN_STOCK, Utils.getAmount(inventory, getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.MAX_STACK, getProduct().getMaxStackSize());
|
||||
requirements.put(HologramFormat.Requirement.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.DURABILITY, getProduct().getDurability());
|
||||
requirements.put(HologramFormat.Requirement.IN_STOCK, Utils.getAmount(inventory, itemStack));
|
||||
requirements.put(HologramFormat.Requirement.MAX_STACK, itemStack.getMaxStackSize());
|
||||
requirements.put(HologramFormat.Requirement.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, itemStack));
|
||||
requirements.put(HologramFormat.Requirement.DURABILITY, itemStack.getDurability());
|
||||
|
||||
Map<Placeholder, Object> placeholders = new EnumMap<>(Placeholder.class);
|
||||
placeholders.put(Placeholder.VENDOR, getVendor().getName());
|
||||
placeholders.put(Placeholder.AMOUNT, getProduct().getAmount());
|
||||
placeholders.put(Placeholder.ITEM_NAME, LanguageUtils.getItemName(getProduct()));
|
||||
placeholders.put(Placeholder.ENCHANTMENT, LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(getProduct())));
|
||||
placeholders.put(Placeholder.ITEM_NAME, LanguageUtils.getItemName(itemStack));
|
||||
placeholders.put(Placeholder.ENCHANTMENT, LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(itemStack)));
|
||||
placeholders.put(Placeholder.BUY_PRICE, getBuyPrice());
|
||||
placeholders.put(Placeholder.SELL_PRICE, getSellPrice());
|
||||
placeholders.put(Placeholder.POTION_EFFECT, LanguageUtils.getPotionEffectName(getProduct()));
|
||||
placeholders.put(Placeholder.MUSIC_TITLE, LanguageUtils.getMusicDiscName(getProduct().getType()));
|
||||
placeholders.put(Placeholder.GENERATION, LanguageUtils.getBookGenerationName(getProduct()));
|
||||
placeholders.put(Placeholder.STOCK, Utils.getAmount(inventory, getProduct()));
|
||||
placeholders.put(Placeholder.MAX_STACK, getProduct().getMaxStackSize());
|
||||
placeholders.put(Placeholder.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, getProduct()));
|
||||
placeholders.put(Placeholder.DURABILITY, getProduct().getDurability());
|
||||
placeholders.put(Placeholder.POTION_EFFECT, LanguageUtils.getPotionEffectName(itemStack));
|
||||
placeholders.put(Placeholder.MUSIC_TITLE, LanguageUtils.getMusicDiscName(itemStack.getType()));
|
||||
placeholders.put(Placeholder.GENERATION, LanguageUtils.getBookGenerationName(itemStack));
|
||||
placeholders.put(Placeholder.STOCK, Utils.getAmount(inventory, itemStack));
|
||||
placeholders.put(Placeholder.MAX_STACK, itemStack.getMaxStackSize());
|
||||
placeholders.put(Placeholder.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, itemStack));
|
||||
placeholders.put(Placeholder.DURABILITY, itemStack.getDurability());
|
||||
|
||||
int lineCount = plugin.getHologramFormat().getLineCount();
|
||||
|
||||
@ -407,7 +405,7 @@ public class Shop {
|
||||
/**
|
||||
* @return Product the shop sells (or buys)
|
||||
*/
|
||||
public ItemStack getProduct() {
|
||||
public ShopProduct getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
|
34
src/main/java/de/epiceric/shopchest/shop/ShopProduct.java
Normal file
34
src/main/java/de/epiceric/shopchest/shop/ShopProduct.java
Normal file
@ -0,0 +1,34 @@
|
||||
package de.epiceric.shopchest.shop;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ShopProduct {
|
||||
|
||||
private final ItemStack itemStack;
|
||||
private final int amount;
|
||||
|
||||
public ShopProduct(ItemStack itemStack, int amount) {
|
||||
this.itemStack = new ItemStack(itemStack);
|
||||
this.itemStack.setAmount(1);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public ShopProduct(ItemStack itemStack) {
|
||||
this(itemStack, itemStack.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link ItemStack} with an amount of {@code 1}.
|
||||
*/
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The amount
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
}
|
@ -7,6 +7,7 @@ import de.epiceric.shopchest.event.ShopBuySellEvent.Type;
|
||||
import de.epiceric.shopchest.exceptions.WorldNotFoundException;
|
||||
import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.shop.Shop;
|
||||
import de.epiceric.shopchest.shop.ShopProduct;
|
||||
import de.epiceric.shopchest.shop.Shop.ShopType;
|
||||
import de.epiceric.shopchest.utils.Callback;
|
||||
import de.epiceric.shopchest.utils.Utils;
|
||||
@ -18,11 +19,14 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -35,6 +39,10 @@ public abstract class Database {
|
||||
|
||||
private static Set<String> notFoundWorlds = new HashSet<>();
|
||||
|
||||
private String tableShops;
|
||||
private String tableLogs;
|
||||
private String tableLogouts;
|
||||
|
||||
ShopChest plugin;
|
||||
HikariDataSource dataSource;
|
||||
|
||||
@ -52,18 +60,31 @@ public abstract class Database {
|
||||
* that were found (as {@code int})
|
||||
*/
|
||||
public void connect(final Callback<Integer> callback) {
|
||||
if (!Config.databaseTablePrefix.matches("^([a-zA-Z0-9\\-\\_]+)?$")) {
|
||||
// Only letters, numbers dashes and underscores are allowed
|
||||
plugin.getLogger().severe("Database table prefix contains illegal letters, using 'shopchest_' prefix.");
|
||||
Config.databaseTablePrefix = "shopchest_";
|
||||
}
|
||||
|
||||
this.tableShops = Config.databaseTablePrefix + "shops";
|
||||
this.tableLogs = Config.databaseTablePrefix + "economy_logs";
|
||||
this.tableLogouts = Config.databaseTablePrefix + "player_logouts";
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
disconnect();
|
||||
|
||||
dataSource = getDataSource();
|
||||
|
||||
String autoIncrement = Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT";
|
||||
|
||||
String queryCreateTableShopList =
|
||||
"CREATE TABLE IF NOT EXISTS shops ("
|
||||
+ "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + ","
|
||||
"CREATE TABLE IF NOT EXISTS " + tableShops + " ("
|
||||
+ "id INTEGER PRIMARY KEY " + autoIncrement + ","
|
||||
+ "vendor TINYTEXT NOT NULL,"
|
||||
+ "product TEXT NOT NULL,"
|
||||
+ "amount INTEGER NOT NULL,"
|
||||
+ "world TINYTEXT NOT NULL,"
|
||||
+ "x INTEGER NOT NULL,"
|
||||
+ "y INTEGER NOT NULL,"
|
||||
@ -73,12 +94,19 @@ public abstract class Database {
|
||||
+ "shoptype TINYTEXT NOT NULL)";
|
||||
|
||||
String queryCreateTableShopLog =
|
||||
"CREATE TABLE IF NOT EXISTS `shop_log` ("
|
||||
+ "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + ","
|
||||
"CREATE TABLE IF NOT EXISTS " + tableLogs + " ("
|
||||
+ "id INTEGER PRIMARY KEY " + autoIncrement + ","
|
||||
+ "shop_id INTEGER NOT NULL,"
|
||||
+ "timestamp TINYTEXT NOT NULL,"
|
||||
+ "executor TINYTEXT NOT NULL,"
|
||||
+ "product TINYTEXT NOT NULL,"
|
||||
+ "vendor TINYTEXT NOT NULL,"
|
||||
+ "time LONG NOT NULL,"
|
||||
+ "player_name TINYTEXT NOT NULL,"
|
||||
+ "player_uuid TINYTEXT NOT NULL,"
|
||||
+ "product_name TINYTEXT NOT NULL,"
|
||||
+ "product TEXT NOT NULL,"
|
||||
+ "amount INTEGER NOT NULL,"
|
||||
+ "vendor_name TINYTEXT NOT NULL,"
|
||||
+ "vendor_uuid TINYTEXT NOT NULL,"
|
||||
+ "admin BIT NOT NULL,"
|
||||
+ "world TINYTEXT NOT NULL,"
|
||||
+ "x INTEGER NOT NULL,"
|
||||
+ "y INTEGER NOT NULL,"
|
||||
@ -87,23 +115,127 @@ public abstract class Database {
|
||||
+ "type TINYTEXT NOT NULL)";
|
||||
|
||||
String queryCreateTablePlayerLogout =
|
||||
"CREATE TABLE IF NOT EXISTS player_logout ("
|
||||
"CREATE TABLE IF NOT EXISTS " + tableLogouts + " ("
|
||||
+ "player VARCHAR(36) PRIMARY KEY NOT NULL,"
|
||||
+ "time LONG NOT NULL)";
|
||||
|
||||
try {
|
||||
// Create table "shops"
|
||||
try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
|
||||
String queryCheckIfOldFormat =
|
||||
Database.this instanceof SQLite ?
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='shop_log'" :
|
||||
"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='shop_log'";
|
||||
|
||||
String queryRenameTableLogouts = "ALTER TABLE player_logout RENAME TO " + tableLogouts;
|
||||
String queryRenameTableLogs = "ALTER TABLE shop_log RENAME TO backup_shop_log"; // for backup
|
||||
String queryRenameTableShops = "ALTER TABLE shops RENAME TO backup_shops"; // for backup
|
||||
|
||||
try (Connection con = dataSource.getConnection()) {
|
||||
// Check if database is in old format
|
||||
try (Statement s = con.createStatement()) {
|
||||
ResultSet rs = s.executeQuery(queryCheckIfOldFormat);
|
||||
if (rs.next()) {
|
||||
plugin.getLogger().warning("Database is using old format and will be converted.");
|
||||
|
||||
try (Statement s2 = con.createStatement()) {
|
||||
s.executeUpdate(queryRenameTableShops);
|
||||
|
||||
// Create new shops table
|
||||
try (Statement s3 = con.createStatement()) {
|
||||
s3.executeUpdate(queryCreateTableShopList);
|
||||
}
|
||||
|
||||
// Create new log table
|
||||
try (Statement s4 = con.createStatement()) {
|
||||
s4.executeUpdate(queryCreateTableShopLog);
|
||||
}
|
||||
|
||||
// Convert shop table
|
||||
try (Statement s3 = con.createStatement()) {
|
||||
ResultSet rs2 = s3.executeQuery("SELECT id,product FROM backup_shops");
|
||||
while (rs2.next()) {
|
||||
ItemStack is = Utils.decode(rs2.getString("product"));
|
||||
int amount = is.getAmount();
|
||||
is.setAmount(1);
|
||||
String product = Utils.encode(is);
|
||||
|
||||
String insertQuery = "INSERT INTO " + tableShops + " SELECT id,vendor,?,?,world,x,y,z,buyprice,sellprice,shoptype FROM backup_shops WHERE id = ?";
|
||||
try (PreparedStatement ps = con.prepareStatement(insertQuery)) {
|
||||
ps.setString(1, product);
|
||||
ps.setInt(2, amount);
|
||||
ps.setInt(3, rs2.getInt("id"));
|
||||
ps.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert log table
|
||||
try (Statement s3 = con.createStatement()) {
|
||||
ResultSet rs2 = s3.executeQuery("SELECT id,timestamp,executor,product,vendor FROM shop_log");
|
||||
while (rs2.next()) {
|
||||
String timestamp = rs2.getString("timestamp");
|
||||
long time = 0L;
|
||||
|
||||
try {
|
||||
time = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(timestamp).getTime();
|
||||
} catch (ParseException e) {
|
||||
plugin.debug("Failed to parse timestamp '" + timestamp + "': Time is set to 0");
|
||||
plugin.debug(e);
|
||||
}
|
||||
|
||||
String player = rs2.getString("executor");
|
||||
String playerUuid = player.substring(0, 36);
|
||||
String playerName = player.substring(38, player.length() - 1);
|
||||
|
||||
String oldProduct = rs2.getString("product");
|
||||
String product = oldProduct.split(" x ")[1];
|
||||
int amount = Integer.valueOf(oldProduct.split(" x ")[0]);
|
||||
|
||||
String vendor = rs2.getString("vendor");
|
||||
String vendorUuid = vendor.substring(0, 36);
|
||||
String vendorName = vendor.substring(38).replaceAll("\\)( \\(ADMIN\\))?", "");
|
||||
boolean admin = vendor.endsWith("(ADMIN)");
|
||||
|
||||
String insertQuery = "INSERT INTO " + tableLogs + " SELECT id,-1,timestamp,?,?,?,?,'Unknown',?,?,?,?,world,x,y,z,price,type FROM shop_log WHERE id = ?";
|
||||
try (PreparedStatement ps = con.prepareStatement(insertQuery)) {
|
||||
ps.setLong(1, time);
|
||||
ps.setString(2, playerName);
|
||||
ps.setString(3, playerUuid);
|
||||
ps.setString(4, product);
|
||||
ps.setInt(5, amount);
|
||||
ps.setString(6, vendorName);
|
||||
ps.setString(7, vendorUuid);
|
||||
ps.setBoolean(8, admin);
|
||||
ps.setInt(9, rs2.getInt("id"));
|
||||
ps.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rename log table
|
||||
try (Statement s3 = con.createStatement()) {
|
||||
s3.executeUpdate(queryRenameTableLogs);
|
||||
}
|
||||
|
||||
// Rename logout table
|
||||
try (Statement s3 = con.createStatement()) {
|
||||
s3.executeUpdate(queryRenameTableLogouts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create shop table
|
||||
try (Statement s = con.createStatement()) {
|
||||
s.executeUpdate(queryCreateTableShopList);
|
||||
}
|
||||
|
||||
// Create table "shop_log"
|
||||
try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
|
||||
// Create log table
|
||||
try (Statement s = con.createStatement()) {
|
||||
s.executeUpdate(queryCreateTableShopLog);
|
||||
}
|
||||
|
||||
// Create table "player_logout"
|
||||
try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
|
||||
// Create logout table
|
||||
try (Statement s = con.createStatement()) {
|
||||
s.executeUpdate(queryCreateTablePlayerLogout);
|
||||
}
|
||||
|
||||
@ -112,19 +244,19 @@ public abstract class Database {
|
||||
cleanUpEconomy(false);
|
||||
}
|
||||
|
||||
// Count entries in table "shops"
|
||||
try (Connection con = dataSource.getConnection(); Statement s = con.createStatement();) {
|
||||
ResultSet rs = s.executeQuery("SELECT id FROM shops");
|
||||
// Count shops entries in database
|
||||
try (Statement s = con.createStatement();) {
|
||||
ResultSet rs = s.executeQuery("SELECT COUNT(id) FROM " + tableShops);
|
||||
if (rs.next()) {
|
||||
int count = rs.getInt(1);
|
||||
|
||||
plugin.debug("Initialized database with " + count + " entries");
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
count++;
|
||||
}
|
||||
|
||||
plugin.debug("Initialized database with " + count + " entries");
|
||||
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(count);
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(count);
|
||||
}
|
||||
} else {
|
||||
throw new SQLException("Count result set has no entries");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
@ -151,7 +283,7 @@ public abstract class Database {
|
||||
@Override
|
||||
public void run() {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("DELETE FROM shops WHERE id = ?")) {
|
||||
PreparedStatement ps = con.prepareStatement("DELETE FROM " + tableShops + " WHERE id = ?")) {
|
||||
ps.setInt(1, shop.getID());
|
||||
ps.executeUpdate();
|
||||
|
||||
@ -173,53 +305,14 @@ public abstract class Database {
|
||||
}.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id ID of the shop
|
||||
* @param callback Callback that - if succeeded - returns whether a shop with
|
||||
* the given ID exists (as {@code boolean})
|
||||
*/
|
||||
public void isShop(final int id, final Callback<Boolean> callback) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM shops WHERE id = ?")) {
|
||||
ps.setInt(1, id);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("id") == id) {
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(false);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
if (callback != null) {
|
||||
callback.callSyncError(ex);
|
||||
}
|
||||
|
||||
plugin.getLogger().severe("Failed to check if shop exists in the database");
|
||||
plugin.debug("Failed to check if shop with ID exists (#" + id + ")");
|
||||
plugin.debug(ex);
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all shops from the database
|
||||
*
|
||||
* @param showConsoleMessages Whether console messages (errors or warnings)
|
||||
* should be shown
|
||||
* @param callback Callback that - if succeeded - returns a read-only
|
||||
* collection of all shops (as
|
||||
* {@code Collection<Shop>})
|
||||
* @param showConsoleMessages Whether console messages (errors or warnings)
|
||||
* should be shown
|
||||
*/
|
||||
public void getShops(final boolean showConsoleMessages, final Callback<Collection<Shop>> callback) {
|
||||
new BukkitRunnable() {
|
||||
@ -228,7 +321,7 @@ public abstract class Database {
|
||||
ArrayList<Shop> shops = new ArrayList<>();
|
||||
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM shops")) {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableShops + "")) {
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
@ -238,9 +331,6 @@ public abstract class Database {
|
||||
|
||||
String worldName = rs.getString("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
int x = rs.getInt("x");
|
||||
int y = rs.getInt("y");
|
||||
int z = rs.getInt("z");
|
||||
|
||||
if (world == null) {
|
||||
WorldNotFoundException ex = new WorldNotFoundException(worldName);
|
||||
@ -253,16 +343,20 @@ public abstract class Database {
|
||||
continue;
|
||||
}
|
||||
|
||||
int x = rs.getInt("x");
|
||||
int y = rs.getInt("y");
|
||||
int z = rs.getInt("z");
|
||||
Location location = new Location(world, x, y, z);
|
||||
|
||||
plugin.debug("Initializing new shop... (#" + id + ")");
|
||||
|
||||
OfflinePlayer vendor = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor")));
|
||||
ItemStack product = Utils.decode(rs.getString("product"));
|
||||
ItemStack itemStack = Utils.decode(rs.getString("product"));
|
||||
int amount = rs.getInt("amount");
|
||||
ShopProduct product = new ShopProduct(itemStack, amount);
|
||||
double buyPrice = rs.getDouble("buyprice");
|
||||
double sellPrice = rs.getDouble("sellprice");
|
||||
ShopType shopType = ShopType.valueOf(rs.getString("shoptype"));
|
||||
|
||||
plugin.debug("Initializing new shop... (#" + id + ")");
|
||||
|
||||
shops.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType));
|
||||
}
|
||||
|
||||
@ -291,8 +385,8 @@ public abstract class Database {
|
||||
* given (as {@code int})
|
||||
*/
|
||||
public void addShop(final Shop shop, final Callback<Integer> callback) {
|
||||
final String queryNoId = "REPLACE INTO shops (vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?)";
|
||||
final String queryWithId = "REPLACE INTO shops (id,vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?)";
|
||||
final String queryNoId = "REPLACE INTO " + tableShops + " (vendor,product,amount,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?)";
|
||||
final String queryWithId = "REPLACE INTO " + tableShops + " (id,vendor,product,amount,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
@ -308,14 +402,15 @@ public abstract class Database {
|
||||
}
|
||||
|
||||
ps.setString(i+1, shop.getVendor().getUniqueId().toString());
|
||||
ps.setString(i+2, Utils.encode(shop.getProduct()));
|
||||
ps.setString(i+3, shop.getLocation().getWorld().getName());
|
||||
ps.setInt(i+4, shop.getLocation().getBlockX());
|
||||
ps.setInt(i+5, shop.getLocation().getBlockY());
|
||||
ps.setInt(i+6, shop.getLocation().getBlockZ());
|
||||
ps.setDouble(i+7, shop.getBuyPrice());
|
||||
ps.setDouble(i+8, shop.getSellPrice());
|
||||
ps.setString(i+9, shop.getShopType().toString());
|
||||
ps.setString(i+2, Utils.encode(shop.getProduct().getItemStack()));
|
||||
ps.setInt(i+3, shop.getProduct().getAmount());
|
||||
ps.setString(i+4, shop.getLocation().getWorld().getName());
|
||||
ps.setInt(i+5, shop.getLocation().getBlockX());
|
||||
ps.setInt(i+6, shop.getLocation().getBlockY());
|
||||
ps.setInt(i+7, shop.getLocation().getBlockZ());
|
||||
ps.setDouble(i+8, shop.getBuyPrice());
|
||||
ps.setDouble(i+9, shop.getSellPrice());
|
||||
ps.setString(i+10, shop.getShopType().toString());
|
||||
ps.executeUpdate();
|
||||
|
||||
if (!shop.hasId()) {
|
||||
@ -356,8 +451,10 @@ public abstract class Database {
|
||||
* @param type Whether the executor bought or sold
|
||||
* @param callback Callback that - if succeeded - returns {@code null}
|
||||
*/
|
||||
public void logEconomy(final Player executor, Shop shop, ItemStack product, double price, Type type, final Callback<Void> callback) {
|
||||
final String query = "INSERT INTO shop_log (timestamp,executor,product,vendor,world,x,y,z,price,type) VALUES(?,?,?,?,?,?,?,?,?,?)";
|
||||
public void logEconomy(final Player executor, Shop shop, ShopProduct product, double price, Type type, final Callback<Void> callback) {
|
||||
final String query = "INSERT INTO " + tableLogs + " (shop_id,timestamp,time,player_name,player_uuid,product_name,product,amount,"
|
||||
+ "vendor_name,vendor_uuid,admin,world,x,y,z,price,type) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
|
||||
if (Config.enableEconomyLog) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
@ -365,16 +462,25 @@ public abstract class Database {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement(query)) {
|
||||
|
||||
ps.setString(1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
|
||||
ps.setString(2, executor.getUniqueId().toString() + " (" + executor.getName() + ")");
|
||||
ps.setString(3, product.getAmount() + " x " + LanguageUtils.getItemName(product));
|
||||
ps.setString(4, shop.getVendor().getUniqueId().toString() + " (" + shop.getVendor().getName() + ")" + (shop.getShopType() == ShopType.ADMIN ? " (ADMIN)" : ""));
|
||||
ps.setString(5, shop.getLocation().getWorld().getName());
|
||||
ps.setInt(6, shop.getLocation().getBlockX());
|
||||
ps.setInt(7, shop.getLocation().getBlockY());
|
||||
ps.setInt(8, shop.getLocation().getBlockZ());
|
||||
ps.setDouble(9, price);
|
||||
ps.setString(10, type.toString());
|
||||
long millis = System.currentTimeMillis();
|
||||
|
||||
ps.setInt(1, shop.getID());
|
||||
ps.setString(2, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(millis));
|
||||
ps.setLong(3, millis);
|
||||
ps.setString(4, executor.getName());
|
||||
ps.setString(5, executor.getUniqueId().toString());
|
||||
ps.setString(6, LanguageUtils.getItemName(product.getItemStack()));
|
||||
ps.setString(7, Utils.encode(product.getItemStack()));
|
||||
ps.setInt(8, product.getAmount());
|
||||
ps.setString(9, shop.getVendor().getName());
|
||||
ps.setString(10, shop.getVendor().getUniqueId().toString());
|
||||
ps.setBoolean(11, shop.getShopType() == ShopType.ADMIN);
|
||||
ps.setString(12, shop.getLocation().getWorld().getName());
|
||||
ps.setInt(13, shop.getLocation().getBlockX());
|
||||
ps.setInt(14, shop.getLocation().getBlockY());
|
||||
ps.setInt(15, shop.getLocation().getBlockZ());
|
||||
ps.setDouble(16, price);
|
||||
ps.setString(17, type.toString());
|
||||
ps.executeUpdate();
|
||||
|
||||
if (callback != null) {
|
||||
@ -409,13 +515,9 @@ public abstract class Database {
|
||||
BukkitRunnable runnable = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
long time = System.currentTimeMillis();
|
||||
cal.add(Calendar.DATE, -Config.cleanupEconomyLogDays);
|
||||
time -= Config.cleanupEconomyLogDays * 86400000L;
|
||||
String logPurgeLimit = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTime());
|
||||
String queryCleanUpLog = "DELETE FROM shop_log WHERE timestamp < '" + logPurgeLimit + "'";
|
||||
String queryCleanUpPlayers = "DELETE FROM player_logout WHERE time < " + String.valueOf(time);
|
||||
long time = System.currentTimeMillis() - Config.cleanupEconomyLogDays * 86400000L;
|
||||
String queryCleanUpLog = "DELETE FROM " + tableLogs + " WHERE time < " + time;
|
||||
String queryCleanUpPlayers = "DELETE FROM " + tableLogouts + " WHERE time < " + time;
|
||||
|
||||
try (Connection con = dataSource.getConnection();
|
||||
Statement s = con.createStatement();
|
||||
@ -452,36 +554,24 @@ public abstract class Database {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String vendor = String.format("%s (%s)", player.getUniqueId().toString(), player.getName());
|
||||
double revenue = 0;
|
||||
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM shop_log WHERE vendor = ?")) {
|
||||
ps.setString(1, vendor);
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableLogs + " WHERE vendor_uuid = ?")) {
|
||||
ps.setString(1, player.getUniqueId().toString());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
if (rs.getString("vendor").equals(vendor)) {
|
||||
double singleRevenue = rs.getDouble("price");
|
||||
ShopBuySellEvent.Type type = ShopBuySellEvent.Type.valueOf(rs.getString("type"));
|
||||
long timestamp = rs.getLong("time");
|
||||
double singleRevenue = rs.getDouble("price");
|
||||
ShopBuySellEvent.Type type = ShopBuySellEvent.Type.valueOf(rs.getString("type"));
|
||||
|
||||
if (type == ShopBuySellEvent.Type.SELL) {
|
||||
singleRevenue = -singleRevenue;
|
||||
}
|
||||
if (type == ShopBuySellEvent.Type.SELL) {
|
||||
singleRevenue = -singleRevenue;
|
||||
}
|
||||
|
||||
long timestamp;
|
||||
|
||||
try {
|
||||
timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("timestamp")).getTime();
|
||||
} catch (ParseException ex) {
|
||||
plugin.debug("Failed to get revenue from player \"" + player.getUniqueId().toString() + "\"");
|
||||
plugin.debug(ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timestamp > logoutTime) {
|
||||
revenue += singleRevenue;
|
||||
}
|
||||
if (timestamp > logoutTime) {
|
||||
revenue += singleRevenue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,18 +595,16 @@ public abstract class Database {
|
||||
* Log a logout to the database
|
||||
*
|
||||
* @param player Player who logged out
|
||||
* @param timestamp Time in milliseconds when the player logged out
|
||||
* @param callback Callback that - if succeeded - returns {@code null}
|
||||
*/
|
||||
public void logLogout(final Player player, final long timestamp, final Callback<Void> callback) {
|
||||
public void logLogout(final Player player, final Callback<Void> callback) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("REPLACE INTO player_logout (player,time) VALUES(?,?)")) {
|
||||
PreparedStatement ps = con.prepareStatement("REPLACE INTO " + tableLogouts + " (player,time) VALUES(?,?)")) {
|
||||
ps.setString(1, player.getUniqueId().toString());
|
||||
ps.setLong(2, timestamp);
|
||||
ps.setLong(2, System.currentTimeMillis());
|
||||
ps.executeUpdate();
|
||||
|
||||
if (callback != null) {
|
||||
@ -549,19 +637,14 @@ public abstract class Database {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String uuid = player.getUniqueId().toString();
|
||||
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM player_logout WHERE player = ?")) {
|
||||
ps.setString(1, uuid);
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableLogouts + " WHERE player = ?")) {
|
||||
ps.setString(1, player.getUniqueId().toString());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
if (rs.getString("player").equals(uuid)) {
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(rs.getLong("time"));
|
||||
}
|
||||
return;
|
||||
if (rs.next()) {
|
||||
if (callback != null) {
|
||||
callback.callSyncResult(rs.getLong("time"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package de.epiceric.shopchest.utils;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.shop.ShopProduct;
|
||||
import de.epiceric.shopchest.shop.Shop.ShopType;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
@ -18,7 +18,7 @@ public class ClickType {
|
||||
private static Map<UUID, BukkitTask> playerTimers = new HashMap<>();
|
||||
|
||||
private EnumClickType enumClickType;
|
||||
private ItemStack product;
|
||||
private ShopProduct product;
|
||||
private double buyPrice;
|
||||
private double sellPrice;
|
||||
private ShopType shopType;
|
||||
@ -27,7 +27,7 @@ public class ClickType {
|
||||
this.enumClickType = enumClickType;
|
||||
}
|
||||
|
||||
public ClickType(EnumClickType enumClickType, ItemStack product, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
public ClickType(EnumClickType enumClickType, ShopProduct product, double buyPrice, double sellPrice, ShopType shopType) {
|
||||
this.enumClickType = enumClickType;
|
||||
this.product = product;
|
||||
this.sellPrice = sellPrice;
|
||||
@ -90,7 +90,7 @@ public class ClickType {
|
||||
/**
|
||||
* @return If {@link #getClickType()} returns {@link EnumClickType#CREATE}, this returns the item, the player has hold in his hands, else <b>null</b>.
|
||||
*/
|
||||
public ItemStack getProduct() {
|
||||
public ShopProduct getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
|
@ -251,6 +251,9 @@ database:
|
||||
# Either use 'SQLite' or 'MySQL'. Otherwise you will break the plugin!
|
||||
type: "SQLite"
|
||||
|
||||
# Set the prefix of all table names related to this plugin.
|
||||
table-prefix: "shopchest_"
|
||||
|
||||
# If the specified type is 'MySQL', here you configure the...
|
||||
# (You can leave this empty if you're using SQLite)
|
||||
mysql:
|
||||
|
Loading…
Reference in New Issue
Block a user