This commit is contained in:
Aleksander Jagiello 2021-10-15 03:38:45 +02:00 committed by GitHub
commit 2548dfe691
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 29 deletions

View File

@ -121,6 +121,11 @@ public class Config {
**/
public static List<String> blacklist;
/**
* Percentage of VAT.
**/
public static double vat;
/**
* Whether prices may contain decimals
**/
@ -473,6 +478,7 @@ public class Config {
autoCalculateItemAmount = (allowDecimalsInPrice && plugin.getConfig().getBoolean("auto-calculate-item-amount"));
creativeSelectItem = plugin.getConfig().getBoolean("creative-select-item");
blacklist = (plugin.getConfig().getStringList("blacklist") == null) ? new ArrayList<String>() : plugin.getConfig().getStringList("blacklist");
vat = plugin.getConfig().getDouble("vat");
buyGreaterOrEqualSell = plugin.getConfig().getBoolean("buy-greater-or-equal-sell");
confirmShopping = plugin.getConfig().getBoolean("confirm-shopping");
refundShopCreation = plugin.getConfig().getBoolean("refund-shop-creation");

View File

@ -12,6 +12,7 @@ public enum Placeholder {
MAX_PRICE("%MAX-PRICE%"),
VERSION("%VERSION%"),
BUY_PRICE("%BUY-PRICE%"),
BUY_TAXED_PRICE("%BUY-TAXED-PRICE%"),
SELL_PRICE("%SELL-PRICE%"),
LIMIT("%LIMIT%"),
PLAYER("%PLAYER%"),

View File

@ -12,13 +12,15 @@ public class ShopBuySellEvent extends ShopEvent implements Cancellable {
private Type type;
private int newAmount;
private double newPrice;
private double newTaxedPrice;
private boolean cancelled;
public ShopBuySellEvent(Player player, Shop shop, Type type, int newAmount, double newPrice) {
public ShopBuySellEvent(Player player, Shop shop, Type type, int newAmount, double newPrice, double newTaxedPrice) {
super(player, shop);
this.type = type;
this.newAmount = newAmount;
this.newPrice = newPrice;
this.newTaxedPrice = newTaxedPrice;
}
/**
@ -42,6 +44,13 @@ public class ShopBuySellEvent extends ShopEvent implements Cancellable {
return newPrice;
}
/**
* @return The taxed price which might be modified because of automatic item amount calculation
*/
public double getNewTaxedPrice() {
return newTaxedPrice;
}
@Override
public boolean isCancelled() {
return cancelled;

View File

@ -626,6 +626,7 @@ public class ShopInteractListener implements Listener {
String priceString = LanguageUtils.getMessage(Message.SHOP_INFO_PRICE,
new Replacement(Placeholder.BUY_PRICE, (shop.getBuyPrice() > 0 ? String.valueOf(shop.getBuyPrice()) : disabled)),
new Replacement(Placeholder.BUY_TAXED_PRICE, (shop.getTaxedBuyPrice() > 0 ? String.valueOf(shop.getTaxedBuyPrice()) : disabled)),
new Replacement(Placeholder.SELL_PRICE, (shop.getSellPrice() > 0 ? String.valueOf(shop.getSellPrice()) : disabled)));
String shopType = LanguageUtils.getMessage(shop.getShopType() == ShopType.NORMAL ?
@ -743,12 +744,16 @@ public class ShopInteractListener implements Listener {
String worldName = shop.getLocation().getWorld().getName();
double price = shop.getBuyPrice();
if (stack) price = (price / shop.getProduct().getAmount()) * amount;
double realPrice = shop.getBuyPrice();
double taxedPrice = shop.getTaxedBuyPrice();
if (stack) {
realPrice = (realPrice / shop.getProduct().getAmount()) * amount;
taxedPrice = (taxedPrice / shop.getProduct().getAmount()) * amount;
}
if (econ.getBalance(executor, worldName) >= price || Config.autoCalculateItemAmount) {
if (econ.getBalance(executor, worldName) >= taxedPrice || Config.autoCalculateItemAmount) {
int amountForMoney = (int) (amount / price * econ.getBalance(executor, worldName));
int amountForMoney = (int) (amount / taxedPrice * econ.getBalance(executor, worldName));
if (amountForMoney == 0 && Config.autoCalculateItemAmount) {
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_MONEY));
@ -791,29 +796,30 @@ public class ShopInteractListener implements Listener {
if (newAmount > amount) newAmount = amount;
ShopProduct newProduct = new ShopProduct(product, newAmount);
double newPrice = (price / amount) * newAmount;
double newRealPrice = (realPrice / amount) * newAmount;
double newTaxedPrice = (taxedPrice / amount) * newAmount;
if (freeSpace >= newAmount) {
plugin.debug(executor.getName() + " has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
EconomyResponse r = econ.withdrawPlayer(executor, worldName, newPrice);
EconomyResponse r = econ.withdrawPlayer(executor, worldName, newTaxedPrice);
if (r.transactionSuccess()) {
EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.depositPlayer(shop.getVendor(), worldName, newPrice) : null;
EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.depositPlayer(shop.getVendor(), worldName, newRealPrice) : null;
if (r2 != null) {
if (r2.transactionSuccess()) {
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice);
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newRealPrice, newTaxedPrice);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
econ.depositPlayer(executor, worldName, newPrice);
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice);
econ.depositPlayer(executor, worldName, newTaxedPrice);
econ.withdrawPlayer(shop.getVendor(), worldName, newRealPrice);
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
return;
}
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
database.logEconomy(executor, shop, newProduct, newRealPrice, newTaxedPrice, ShopBuySellEvent.Type.BUY, null);
addToInventory(inventory, newProduct);
removeFromInventory(c.getInventory(), newProduct);
@ -830,14 +836,14 @@ public class ShopInteractListener implements Listener {
String vendorName = (shop.getVendor().getName() == null ? shop.getVendor().getUniqueId().toString() : shop.getVendor().getName());
executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)),
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newTaxedPrice)),
new Replacement(Placeholder.VENDOR, vendorName)));
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)),
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newRealPrice)),
new Replacement(Placeholder.PLAYER, executor.getName())));
} else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){
String message = LanguageUtils.getMessage( Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
@ -849,20 +855,20 @@ public class ShopInteractListener implements Listener {
} else {
plugin.debug("Economy transaction failed (r2): " + r2.errorMessage + " (#" + shop.getID() + ")");
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r2.errorMessage)));
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice);
econ.depositPlayer(executor, worldName, newPrice);
econ.withdrawPlayer(shop.getVendor(), worldName, newRealPrice);
econ.depositPlayer(executor, worldName, newTaxedPrice);
}
} else {
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice);
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newRealPrice, newTaxedPrice);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
econ.depositPlayer(executor, worldName, newPrice);
econ.depositPlayer(executor, worldName, newTaxedPrice);
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
return;
}
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
database.logEconomy(executor, shop, newProduct, newRealPrice, newTaxedPrice, ShopBuySellEvent.Type.BUY, null);
addToInventory(inventory, newProduct);
executor.updateInventory();
@ -877,14 +883,14 @@ public class ShopInteractListener implements Listener {
}.runTaskLater(plugin, 1L);
executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS_ADMIN, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice))));
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newTaxedPrice))));
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
}
} else {
plugin.debug("Economy transaction failed (r): " + r.errorMessage + " (#" + shop.getID() + ")");
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage)));
econ.depositPlayer(executor, worldName, newPrice);
econ.depositPlayer(executor, worldName, newTaxedPrice);
}
} else {
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_INVENTORY_SPACE));
@ -971,7 +977,7 @@ public class ShopInteractListener implements Listener {
if (r2 != null) {
if (r2.transactionSuccess()) {
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice);
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice, 0);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
@ -981,7 +987,7 @@ public class ShopInteractListener implements Listener {
return;
}
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
database.logEconomy(executor, shop, newProduct, newPrice, 0, ShopBuySellEvent.Type.SELL, null);
addToInventory(inventory, newProduct);
removeFromInventory(executor.getInventory(), newProduct);
@ -1022,7 +1028,7 @@ public class ShopInteractListener implements Listener {
}
} else {
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice);
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice, 0);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
@ -1031,7 +1037,7 @@ public class ShopInteractListener implements Listener {
return;
}
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
database.logEconomy(executor, shop, newProduct, newPrice, 0, ShopBuySellEvent.Type.SELL, null);
removeFromInventory(executor.getInventory(), newProduct);
executor.updateInventory();

View File

@ -55,6 +55,7 @@ public class Shop {
private final ShopProduct product;
private final Location location;
private final double buyPrice;
private final double taxedBuyPrice;
private final double sellPrice;
private final ShopType shopType;
@ -71,6 +72,7 @@ public class Shop {
this.product = product;
this.location = location;
this.buyPrice = buyPrice;
this.taxedBuyPrice = buyPrice + calculateVat(buyPrice, Config.vat, Config.allowDecimalsInPrice);
this.sellPrice = sellPrice;
this.shopType = shopType;
}
@ -79,6 +81,23 @@ public class Shop {
this(-1, plugin, vendor, product, location, buyPrice, sellPrice, shopType);
}
/**
* Calculate VAT on the given price
*
* @param price to make calculation on
* @param vat in percentage
* @param allowDecimal if round to int
* @return VAT, returns 0 if price is equal to 0
*/
private double calculateVat(double price, double vat, boolean allowDecimal) {
if (Double.compare(vat, 0) == 0) { // zero if disabled
return 0;
}
double result = vat * price;
return allowDecimal ? result : (int) Math.max(result, 1);
}
/**
* Test if this shop is equals to another
*
@ -286,6 +305,7 @@ public class Shop {
placeholders.put(Placeholder.ITEM_NAME, getProduct().getLocalizedName());
placeholders.put(Placeholder.ENCHANTMENT, LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(itemStack)));
placeholders.put(Placeholder.BUY_PRICE, getBuyPrice());
placeholders.put(Placeholder.BUY_TAXED_PRICE, getTaxedBuyPrice());
placeholders.put(Placeholder.SELL_PRICE, getSellPrice());
placeholders.put(Placeholder.POTION_EFFECT, LanguageUtils.getPotionEffectName(itemStack));
placeholders.put(Placeholder.MUSIC_TITLE, LanguageUtils.getMusicDiscName(itemStack.getType()));
@ -305,7 +325,7 @@ public class Shop {
switch (placeholder) {
case BUY_PRICE:
replace = plugin.getEconomy().format(getBuyPrice());
replace = plugin.getEconomy().format(getTaxedBuyPrice());
break;
case SELL_PRICE:
replace = plugin.getEconomy().format(getSellPrice());
@ -427,6 +447,13 @@ public class Shop {
return buyPrice;
}
/**
* @return Taxed price of the shop
*/
public double getTaxedBuyPrice() {
return taxedBuyPrice;
}
/**
* @return Sell price of the shop
*/

View File

@ -641,9 +641,9 @@ 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, ShopProduct product, double price, Type type, final Callback<Void> callback) {
public void logEconomy(final Player executor, Shop shop, ShopProduct product, double price, double taxedPrice, 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(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+ "vendor_name,vendor_uuid,admin,world,x,y,z,price,taxed_price,type) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
if (Config.enableEconomyLog) {
new BukkitRunnable() {
@ -670,7 +670,8 @@ public abstract class Database {
ps.setInt(14, shop.getLocation().getBlockY());
ps.setInt(15, shop.getLocation().getBlockZ());
ps.setDouble(16, price);
ps.setString(17, type.toString());
ps.setDouble(17, taxedPrice);
ps.setString(18, type.toString());
ps.executeUpdate();
if (callback != null) {

View File

@ -86,6 +86,7 @@ public class MySQL extends Database {
+ "y INTEGER NOT NULL,"
+ "z INTEGER NOT NULL,"
+ "price FLOAT NOT NULL,"
+ "taxed_price FLOAT NOT NULL,"
+ "type TINYTEXT NOT NULL)";
}

View File

@ -102,6 +102,7 @@ public class SQLite extends Database {
+ "y INTEGER NOT NULL,"
+ "z INTEGER NOT NULL,"
+ "price FLOAT NOT NULL,"
+ "taxed_price FLOAT NOT NULL,"
+ "type TINYTEXT NOT NULL)";
}

View File

@ -137,6 +137,9 @@ maximum-prices:
blacklist:
# - "DIORITE"
# Set the percentage of VAT.
vat: 0.1
# Set the price a player has to pay in order to create...
# You can set this to 0 to disable costs.
shop-creation-price: