Add per-item tax and fix value

This commit is contained in:
DaniFoldi 2021-12-16 22:18:39 +01:00
parent 582389672e
commit 679cc39db0
8 changed files with 55 additions and 22 deletions

View File

@ -6,7 +6,7 @@
<groupId>de.epiceric</groupId>
<artifactId>ShopChest</artifactId>
<version>1.13-SNAPSHOT</version>
<version>1.14-SNAPSHOT</version>
<name>ShopChest</name>
<url>https://www.spigotmc.org/resources/shopchest.11431/</url>
@ -217,7 +217,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>

View File

@ -189,6 +189,8 @@ public class ShopChest extends JavaPlugin {
case "v1_16_R1":
case "v1_16_R2":
case "v1_16_R3":
case "v1_17_R1":
//case "v1_18_R1":
break;
default:
debug("Server version not officially supported: " + Utils.getServerVersion() + "!");

View File

@ -537,7 +537,8 @@ class ShopCommandExecutor implements CommandExecutor {
return;
}
AtomicInteger count = new AtomicInteger();
AtomicInteger buyCount = new AtomicInteger();
AtomicInteger sellCount = new AtomicInteger();
AtomicReference<Double> buyPrice = new AtomicReference<>(0d);
AtomicReference<Double> sellPrice = new AtomicReference<>(0d);
Set<UUID> sellers = new HashSet<>();
@ -554,17 +555,27 @@ class ShopCommandExecutor implements CommandExecutor {
}
sellers.add(shop.getVendor().getUniqueId());
count.getAndIncrement();
buyPrice.updateAndGet(v -> v + shop.getBuyPrice());
sellPrice.updateAndGet(v -> v + shop.getSellPrice());
if (shop.getBuyPrice() != 0) {
buyPrice.updateAndGet(v -> v + shop.getBuyPrice());
buyCount.getAndIncrement();
}
if (shop.getSellPrice() != 0) {
sellPrice.updateAndGet(v -> v + shop.getSellPrice());
sellCount.getAndIncrement();
}
});
if (count.get() == 0) {
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_NO_SHOPS));
return;
if (buyCount.get() == 0) {
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_NO_SHOPS_BUY));
} else {
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_OF_ITEM_BUY, new Replacement(Placeholder.AMOUNT, sellers.size()), new Replacement(Placeholder.BUY_PRICE, buyPrice.get() / (double) buyCount.get())));
}
if (sellCount.get() == 0) {
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_NO_SHOPS_SELL));
} else {
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_OF_ITEM_SELL, new Replacement(Placeholder.AMOUNT, sellers.size()), new Replacement(Placeholder.SELL_PRICE, sellPrice.get() / (double) buyCount.get())));
}
p.sendMessage(LanguageUtils.getMessage(Message.VALUE_OF_ITEM, new Replacement(Placeholder.AMOUNT, sellers.size()), new Replacement(Placeholder.BUY_PRICE, buyPrice.get() / (double)count.get()), new Replacement(Placeholder.SELL_PRICE, sellPrice.get() / (double)count.get())));
}
private boolean changeConfig(CommandSender sender, String[] args) {

View File

@ -8,7 +8,9 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.inventory.ItemStack;
@ -61,6 +63,8 @@ public class Config {
**/
public static List<String> areashopRemoveShopEvents;
public static Map<String, Double> shopTaxes;
/**
* The hostname used in ShopChest's MySQL database
**/
@ -468,6 +472,7 @@ public class Config {
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);
shopTaxes = (plugin.getConfig().getConfigurationSection("shop-taxes") == null ? Map.of("default", 0d) : plugin.getConfig().getConfigurationSection("shop-taxes").getKeys(true).stream().collect(Collectors.toMap(i -> i, i -> plugin.getConfig().getConfigurationSection("shop-taxes").getDouble(i))));
allowDecimalsInPrice = plugin.getConfig().getBoolean("allow-decimals-in-price");
allowBrokenItems = plugin.getConfig().getBoolean("allow-broken-items");
autoCalculateItemAmount = (allowDecimalsInPrice && plugin.getConfig().getBoolean("auto-calculate-item-amount"));

View File

@ -2592,8 +2592,10 @@ public class LanguageUtils {
messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_SET, langConfig.getString("message.config.set", "&6Changed &a%PROPERTY% &6to &a%VALUE%&6.")));
messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_REMOVED, langConfig.getString("message.config.removed", "&6Removed &a%VALUE% &6from &a%PROPERTY%&6.")));
messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_ADDED, langConfig.getString("message.config.added", "&6Added &a%VALUE% &6to &a%PROPERTY%&6.")));
messages.add(new LocalizedMessage(Message.VALUE_OF_ITEM, langConfig.getString("message.valueOfItem", "&6This item is sold by &a%COUNT% &6players for an average price of &a%SELL-PRICE%&6, and bought for &a%BUY-PRICE%.")));
messages.add(new LocalizedMessage(Message.VALUE_NO_SHOPS, langConfig.getString("message.valueNoShops", "&cNo shops are currently selling this item.")));
messages.add(new LocalizedMessage(Message.VALUE_OF_ITEM_BUY, langConfig.getString("message.valueOfItemBuy", "&6This item is bought by &a%COUNT% &6players for an average price of &a%SELL-PRICE%&6.")));
messages.add(new LocalizedMessage(Message.VALUE_OF_ITEM_SELL, langConfig.getString("message.valueOfItemSell", "&6This item is sold by &a%COUNT% &6players for an average price of &a%SELL-PRICE%&6.")));
messages.add(new LocalizedMessage(Message.VALUE_NO_SHOPS_BUY, langConfig.getString("message.valueNoShopsBuy", "&cNo shops are currently buying this item.")));
messages.add(new LocalizedMessage(Message.VALUE_NO_SHOPS_SELL, langConfig.getString("message.valueNoShopsSell", "&cNo shops are currently selling this item.")));
}
/**

View File

@ -97,6 +97,8 @@ public enum Message {
CHANGED_CONFIG_SET,
CHANGED_CONFIG_REMOVED,
CHANGED_CONFIG_ADDED,
VALUE_OF_ITEM,
VALUE_NO_SHOPS
VALUE_OF_ITEM_BUY,
VALUE_OF_ITEM_SELL,
VALUE_NO_SHOPS_BUY,
VALUE_NO_SHOPS_SELL
}

View File

@ -822,6 +822,7 @@ public class ShopInteractListener implements Listener {
ShopProduct newProduct = new ShopProduct(product, newAmount);
double newPrice = (finalPrice / finalAmount) * newAmount;
double tax = Config.shopTaxes.getOrDefault(itemStack.getType().toString(), Config.shopTaxes.get("default"));
if (freeSpace >= newAmount) {
plugin.debug(executor.getName() + " has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
@ -829,7 +830,7 @@ public class ShopInteractListener implements Listener {
EconomyResponse r = econ.withdrawPlayer(executor, worldName, newPrice);
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, newPrice * (100 - tax)) : null;
if (r2 != null) {
if (r2.transactionSuccess()) {
@ -841,7 +842,7 @@ public class ShopInteractListener implements Listener {
if (event.isCancelled()) {
econ.depositPlayer(executor, worldName, newPrice);
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice);
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice * (100 - tax));
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
return;
}
@ -867,6 +868,7 @@ public class ShopInteractListener implements Listener {
new Replacement(Placeholder.VENDOR, vendorName)));
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
plugin.getLogger().info(String.format("%s bought %d of %s from %s", executor.name(), finalNewAmount, newProduct.getItemStack().toString(), vendorName));
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(finalNewAmount)),
@ -885,7 +887,7 @@ public class ShopInteractListener implements Listener {
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.depositPlayer(executor, worldName, newPrice * (100 - tax));
});
}
} else {
@ -895,7 +897,7 @@ public class ShopInteractListener implements Listener {
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
econ.depositPlayer(executor, worldName, newPrice);
econ.depositPlayer(executor, worldName, newPrice * (100 - tax));
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
return;
}
@ -918,6 +920,7 @@ public class ShopInteractListener implements Listener {
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice))));
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
plugin.getLogger().info(String.format("%s bought %d of %s from %s", executor.name(), finalNewAmount1, newProduct.getItemStack().toString(), "ADMIN"));
});
}
} else {
@ -1010,6 +1013,7 @@ public class ShopInteractListener implements Listener {
ShopProduct newProduct = new ShopProduct(product, newAmount);
double newPrice = (finalPrice / finalAmount) * newAmount;
double tax = plugin.getShopChestConfig().shopTaxes.getOrDefault(itemStack.getType().toString(), plugin.getShopChestConfig().shopTaxes.get("default"));
if (freeSpace >= newAmount || shop.getShopType() == ShopType.ADMIN) {
plugin.debug("Chest has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
@ -1017,7 +1021,7 @@ public class ShopInteractListener implements Listener {
int finalNewAmount = newAmount;
CompletableFuture.runAsync(() -> {
EconomyResponse r = econ.depositPlayer(executor, worldName, newPrice);
EconomyResponse r = econ.depositPlayer(executor, worldName, newPrice * (100 - tax));
if (r.transactionSuccess()) {
EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.withdrawPlayer(shop.getVendor(), worldName, newPrice) : null;
@ -1030,7 +1034,7 @@ public class ShopInteractListener implements Listener {
if (event.isCancelled()) {
CompletableFuture.runAsync(() -> {
econ.withdrawPlayer(executor, worldName, newPrice);
econ.withdrawPlayer(executor, worldName, newPrice * (100 - tax));
econ.depositPlayer(shop.getVendor(), worldName, newPrice);
plugin.debug("Sell event cancelled (#" + shop.getID() + ")");
});
@ -1058,6 +1062,7 @@ public class ShopInteractListener implements Listener {
new Replacement(Placeholder.VENDOR, vendorName)));
plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")");
plugin.getLogger().info(String.format("%s sold %d of %s from %s", executor.name(), finalNewAmount, newProduct.getItemStack().toString(), vendorName));
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_SOLD, new Replacement(Placeholder.AMOUNT, String.valueOf(finalNewAmount)),
@ -1075,7 +1080,7 @@ public class ShopInteractListener implements Listener {
CompletableFuture.runAsync(() -> {
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(executor, worldName, newPrice);
econ.withdrawPlayer(executor, worldName, newPrice * (100 - tax));
econ.depositPlayer(shop.getVendor(), worldName, newPrice);
});
}
@ -1086,7 +1091,7 @@ public class ShopInteractListener implements Listener {
if (event.isCancelled()) {
CompletableFuture.runAsync(() -> {
econ.withdrawPlayer(executor, worldName, newPrice);
econ.withdrawPlayer(executor, worldName, newPrice * (100 - tax));
plugin.debug("Sell event cancelled (#" + shop.getID() + ")");
});
return;
@ -1110,6 +1115,7 @@ public class ShopInteractListener implements Listener {
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice))));
plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")");
plugin.getLogger().info(String.format("%s bought %d of %s from %s", executor.name(), finalNewAmount, newProduct.getItemStack().toString(), "ADMIN"));
}
} else {

View File

@ -147,6 +147,11 @@ shop-creation-price:
# ...an admin shop
admin: 0
shop-tax:
default: 0
enchanted_book: 30
# Shop limits are handled with permissions.
# A player with permission "shopchest.limit.X" has a limit of X shops,
# a player with permission "shopchest.limit.*" does not have a shop limit.