2016-06-28 18:30:48 +02:00
|
|
|
package de.epiceric.shopchest.listeners;
|
2015-09-02 13:06:48 +02:00
|
|
|
|
2020-04-27 18:13:10 +02:00
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.DataOutputStream;
|
2020-03-25 14:22:50 +01:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Optional;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.UUID;
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
import com.google.gson.JsonPrimitive;
|
2018-07-26 15:51:50 +02:00
|
|
|
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.Bukkit;
|
2017-05-25 12:21:51 +02:00
|
|
|
import org.bukkit.GameMode;
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Material;
|
|
|
|
import org.bukkit.block.Block;
|
2016-07-01 16:13:44 +02:00
|
|
|
import org.bukkit.block.BlockFace;
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.block.Chest;
|
2016-11-20 14:15:53 +01:00
|
|
|
import org.bukkit.block.DoubleChest;
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.event.EventHandler;
|
2016-08-04 21:12:19 +02:00
|
|
|
import org.bukkit.event.EventPriority;
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.event.Listener;
|
|
|
|
import org.bukkit.event.block.Action;
|
2017-05-20 20:10:07 +02:00
|
|
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
2015-09-02 13:06:48 +02:00
|
|
|
import org.bukkit.event.player.PlayerInteractEvent;
|
2017-05-25 12:21:51 +02:00
|
|
|
import org.bukkit.inventory.EquipmentSlot;
|
|
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
import org.bukkit.inventory.ItemStack;
|
|
|
|
import org.bukkit.inventory.PlayerInventory;
|
2017-05-20 20:10:07 +02:00
|
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
2018-08-03 18:24:09 +02:00
|
|
|
import org.codemc.worldguardwrapper.WorldGuardWrapper;
|
2019-04-27 17:36:11 +02:00
|
|
|
import org.codemc.worldguardwrapper.flag.IWrappedFlag;
|
|
|
|
import org.codemc.worldguardwrapper.flag.WrappedState;
|
2018-08-03 18:24:09 +02:00
|
|
|
|
2020-03-25 14:22:50 +01:00
|
|
|
import de.epiceric.shopchest.ShopChest;
|
|
|
|
import de.epiceric.shopchest.config.Config;
|
|
|
|
import de.epiceric.shopchest.config.Placeholder;
|
|
|
|
import de.epiceric.shopchest.event.ShopBuySellEvent;
|
|
|
|
import de.epiceric.shopchest.event.ShopCreateEvent;
|
|
|
|
import de.epiceric.shopchest.event.ShopInfoEvent;
|
|
|
|
import de.epiceric.shopchest.event.ShopOpenEvent;
|
|
|
|
import de.epiceric.shopchest.event.ShopRemoveEvent;
|
2020-04-25 16:23:21 +02:00
|
|
|
import de.epiceric.shopchest.external.PlotSquaredOldShopFlag;
|
2020-03-25 14:22:50 +01:00
|
|
|
import de.epiceric.shopchest.external.PlotSquaredShopFlag;
|
|
|
|
import de.epiceric.shopchest.language.LanguageUtils;
|
|
|
|
import de.epiceric.shopchest.language.Message;
|
|
|
|
import de.epiceric.shopchest.language.Replacement;
|
|
|
|
import de.epiceric.shopchest.nms.JsonBuilder;
|
|
|
|
import de.epiceric.shopchest.shop.Shop;
|
|
|
|
import de.epiceric.shopchest.shop.Shop.ShopType;
|
|
|
|
import de.epiceric.shopchest.shop.ShopProduct;
|
|
|
|
import de.epiceric.shopchest.sql.Database;
|
|
|
|
import de.epiceric.shopchest.utils.ClickType;
|
|
|
|
import de.epiceric.shopchest.utils.ClickType.CreateClickType;
|
|
|
|
import de.epiceric.shopchest.utils.ItemUtils;
|
|
|
|
import de.epiceric.shopchest.utils.Permissions;
|
|
|
|
import de.epiceric.shopchest.utils.ShopUtils;
|
|
|
|
import de.epiceric.shopchest.utils.Utils;
|
|
|
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
|
|
|
import net.milkbowl.vault.economy.Economy;
|
|
|
|
import net.milkbowl.vault.economy.EconomyResponse;
|
2015-09-02 13:06:48 +02:00
|
|
|
|
2016-06-28 18:30:48 +02:00
|
|
|
public class ShopInteractListener implements Listener {
|
2018-07-26 15:51:50 +02:00
|
|
|
private static final Pattern COLOR_CODE_PATTERN = Pattern.compile(".*([§]([a-fA-F0-9]))");
|
|
|
|
private static final Pattern FORMAT_CODE_PATTERN = Pattern.compile(".*([§]([l-oL-OkK]))");
|
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
private ShopChest plugin;
|
2016-06-22 20:51:19 +02:00
|
|
|
private Economy econ;
|
|
|
|
private Database database;
|
2016-07-13 15:03:54 +02:00
|
|
|
private ShopUtils shopUtils;
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-06-28 18:30:48 +02:00
|
|
|
public ShopInteractListener(ShopChest plugin) {
|
2016-05-28 15:47:57 +02:00
|
|
|
this.plugin = plugin;
|
2016-06-22 20:51:19 +02:00
|
|
|
this.econ = plugin.getEconomy();
|
|
|
|
this.database = plugin.getShopDatabase();
|
2016-07-13 15:03:54 +02:00
|
|
|
this.shopUtils = plugin.getShopUtils();
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2017-05-20 20:10:07 +02:00
|
|
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
|
|
|
public void onInventoryClick(InventoryClickEvent e) {
|
|
|
|
if (!plugin.getHologramFormat().isDynamic()) return;
|
|
|
|
|
|
|
|
Inventory chestInv = e.getInventory();
|
|
|
|
|
2017-06-27 21:57:17 +02:00
|
|
|
if (!(chestInv.getHolder() instanceof Chest || chestInv.getHolder() instanceof DoubleChest)) {
|
2017-05-20 20:10:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-06-27 21:57:17 +02:00
|
|
|
Location loc = null;
|
|
|
|
if (chestInv.getHolder() instanceof Chest) {
|
|
|
|
loc = ((Chest) chestInv.getHolder()).getLocation();
|
|
|
|
} else if (chestInv.getHolder() instanceof DoubleChest) {
|
|
|
|
loc = ((DoubleChest) chestInv.getHolder()).getLocation();
|
|
|
|
}
|
2017-05-20 20:10:07 +02:00
|
|
|
|
|
|
|
final Shop shop = plugin.getShopUtils().getShop(loc);
|
|
|
|
if (shop == null) return;
|
|
|
|
|
|
|
|
new BukkitRunnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
shop.updateHologramText();
|
|
|
|
}
|
|
|
|
}.runTaskLater(plugin, 1L);
|
|
|
|
}
|
|
|
|
|
2016-08-04 21:12:19 +02:00
|
|
|
@EventHandler(priority = EventPriority.HIGH)
|
|
|
|
public void onPlayerInteractCreate(PlayerInteractEvent e) {
|
|
|
|
Player p = e.getPlayer();
|
|
|
|
Block b = e.getClickedBlock();
|
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (e.getAction() != Action.RIGHT_CLICK_BLOCK)
|
|
|
|
return;
|
2017-04-19 14:04:57 +02:00
|
|
|
|
2019-05-28 15:53:26 +02:00
|
|
|
if (!(ClickType.getPlayerClickType(p) instanceof CreateClickType))
|
2019-05-03 16:47:35 +02:00
|
|
|
return;
|
2016-11-13 13:43:03 +01:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST)
|
|
|
|
return;
|
2017-03-28 14:37:12 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (ClickType.getPlayerClickType(p).getClickType() != ClickType.EnumClickType.CREATE)
|
|
|
|
return;
|
2017-04-19 14:04:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p))
|
|
|
|
return;
|
2017-03-28 14:37:12 +02:00
|
|
|
|
2019-05-28 15:53:26 +02:00
|
|
|
if (e.isCancelled() && !p.hasPermission(Permissions.CREATE_PROTECTED)) {
|
2019-05-03 16:47:35 +02:00
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED));
|
|
|
|
plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest");
|
2019-05-28 15:53:26 +02:00
|
|
|
} else if (shopUtils.isShop(b.getLocation())) {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_ALREADY_SHOP));
|
|
|
|
plugin.debug("Chest is already a shop");
|
2019-05-03 16:47:35 +02:00
|
|
|
} else if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED));
|
|
|
|
plugin.debug("Chest is blocked");
|
|
|
|
} else {
|
2019-05-28 15:53:26 +02:00
|
|
|
CreateClickType clickType = (CreateClickType) ClickType.getPlayerClickType(p);
|
2019-05-03 16:47:35 +02:00
|
|
|
ShopProduct product = clickType.getProduct();
|
|
|
|
double buyPrice = clickType.getBuyPrice();
|
|
|
|
double sellPrice = clickType.getSellPrice();
|
|
|
|
ShopType shopType = clickType.getShopType();
|
|
|
|
|
|
|
|
create(p, b.getLocation(), product, buyPrice, sellPrice, shopType);
|
|
|
|
}
|
2017-04-19 14:04:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
e.setCancelled(true);
|
|
|
|
ClickType.removePlayerClickType(p);
|
|
|
|
}
|
2017-03-28 14:37:12 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
private Map<UUID, Set<Integer>> needsConfirmation = new HashMap<>();
|
2017-04-19 14:04:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
private void handleInteractEvent(PlayerInteractEvent e) {
|
|
|
|
Block b = e.getClickedBlock();
|
|
|
|
Player p = e.getPlayer();
|
|
|
|
boolean inverted = Config.invertMouseButtons;
|
2017-04-17 17:07:47 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (Utils.getMajorVersion() >= 9 && e.getHand() == EquipmentSlot.OFF_HAND)
|
|
|
|
return;
|
2017-04-19 14:04:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.LEFT_CLICK_BLOCK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST)
|
|
|
|
return;
|
|
|
|
|
2019-05-28 15:53:26 +02:00
|
|
|
ClickType clickType = ClickType.getPlayerClickType(p);
|
|
|
|
if (clickType != null) {
|
2019-05-03 16:47:35 +02:00
|
|
|
if (e.getAction() != Action.RIGHT_CLICK_BLOCK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Shop shop = shopUtils.getShop(b.getLocation());
|
2019-05-28 15:53:26 +02:00
|
|
|
switch (clickType.getClickType()) {
|
|
|
|
case CREATE:
|
|
|
|
case SELECT_ITEM:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (shop == null) {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP));
|
|
|
|
plugin.debug("Chest is not a shop");
|
|
|
|
return;
|
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
}
|
2017-04-17 18:24:51 +02:00
|
|
|
|
2019-05-28 15:53:26 +02:00
|
|
|
switch (clickType.getClickType()) {
|
2019-05-03 16:47:35 +02:00
|
|
|
case INFO:
|
|
|
|
info(p, shop);
|
|
|
|
break;
|
|
|
|
case REMOVE:
|
|
|
|
remove(p, shop);
|
|
|
|
break;
|
|
|
|
case OPEN:
|
|
|
|
open(p, shop, true);
|
|
|
|
break;
|
2019-05-28 15:53:26 +02:00
|
|
|
default: return;
|
2019-05-03 16:47:35 +02:00
|
|
|
}
|
2017-04-26 17:03:39 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
e.setCancelled(true);
|
|
|
|
ClickType.removePlayerClickType(p);
|
|
|
|
} else {
|
|
|
|
Shop shop = shopUtils.getShop(b.getLocation());
|
2017-04-26 17:03:39 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (shop == null)
|
|
|
|
return;
|
2016-08-04 21:12:19 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
boolean confirmed = needsConfirmation.containsKey(p.getUniqueId()) && needsConfirmation.get(p.getUniqueId()).contains(shop.getID());
|
|
|
|
|
|
|
|
if (e.getAction() == Action.LEFT_CLICK_BLOCK && p.isSneaking() && Utils.hasAxeInHand(p)) {
|
|
|
|
return;
|
|
|
|
}
|
2016-08-04 21:12:19 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
ItemStack infoItem = Config.shopInfoItem;
|
|
|
|
if (infoItem != null) {
|
|
|
|
if (e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.LEFT_CLICK_BLOCK) {
|
|
|
|
ItemStack item = Utils.getItemInMainHand(p);
|
2016-08-04 21:12:19 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (item == null || !(infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability())) {
|
|
|
|
item = Utils.getItemInOffHand(p);
|
2016-08-04 21:12:19 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (item != null && infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability()) {
|
|
|
|
e.setCancelled(true);
|
|
|
|
info(p, shop);
|
|
|
|
return;
|
2016-08-06 13:32:37 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
e.setCancelled(true);
|
|
|
|
info(p, shop);
|
|
|
|
return;
|
2016-08-04 21:12:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (e.getAction() == Action.RIGHT_CLICK_BLOCK && p.getUniqueId().equals(shop.getVendor().getUniqueId()) && shop.getShopType() != ShopType.ADMIN) {
|
|
|
|
return;
|
|
|
|
}
|
2017-08-15 12:38:38 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (p.getGameMode() == GameMode.CREATIVE) {
|
|
|
|
e.setCancelled(true);
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.USE_IN_CREATIVE));
|
|
|
|
return;
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if ((e.getAction() == Action.RIGHT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.LEFT_CLICK_BLOCK && inverted)) {
|
|
|
|
e.setCancelled(true);
|
2017-03-21 15:40:23 +01:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (shop.getShopType() == ShopType.ADMIN || !shop.getVendor().getUniqueId().equals(p.getUniqueId())) {
|
|
|
|
plugin.debug(p.getName() + " wants to buy");
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (shop.getBuyPrice() > 0) {
|
|
|
|
if (p.hasPermission(Permissions.BUY)) {
|
|
|
|
// TODO: Outsource shop use external permission
|
|
|
|
boolean externalPluginsAllowed = true;
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) {
|
2020-04-25 16:23:21 +02:00
|
|
|
try {
|
|
|
|
Class.forName("com.plotsquared.core.PlotSquared");
|
|
|
|
com.plotsquared.core.location.Location plotLocation =
|
|
|
|
new com.plotsquared.core.location.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ());
|
|
|
|
com.plotsquared.core.plot.Plot plot = plotLocation.getOwnedPlot();
|
|
|
|
externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.USE_SHOP, p);
|
|
|
|
} catch (ClassNotFoundException ex) {
|
|
|
|
com.github.intellectualsites.plotsquared.plot.object.Location plotLocation =
|
|
|
|
new com.github.intellectualsites.plotsquared.plot.object.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ());
|
|
|
|
com.github.intellectualsites.plotsquared.plot.object.Plot plot = plotLocation.getOwnedPlot();
|
|
|
|
externalPluginsAllowed = PlotSquaredOldShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredOldShopFlag.USE_SHOP, p);
|
|
|
|
}
|
2017-08-15 12:38:38 +02:00
|
|
|
}
|
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) {
|
|
|
|
String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop");
|
|
|
|
WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance();
|
|
|
|
Optional<IWrappedFlag<WrappedState>> flag = wgWrapper.getFlag(flagName, WrappedState.class);
|
|
|
|
if (!flag.isPresent()) plugin.debug("WorldGuard flag '" + flagName + "' is not present!");
|
|
|
|
WrappedState state = flag.map(f -> wgWrapper.queryFlag(p, b.getLocation(), f).orElse(WrappedState.DENY)).orElse(WrappedState.DENY);
|
|
|
|
externalPluginsAllowed = state == WrappedState.ALLOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shop.getShopType() == ShopType.ADMIN) {
|
|
|
|
if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) {
|
|
|
|
if (confirmed || !Config.confirmShopping) {
|
|
|
|
buy(p, shop, p.isSneaking());
|
|
|
|
if (Config.confirmShopping) {
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.remove(shop.getID());
|
|
|
|
if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId());
|
|
|
|
else needsConfirmation.put(p.getUniqueId(), ids);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
plugin.debug("Needs confirmation");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM));
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.add(shop.getID());
|
|
|
|
needsConfirmation.put(p.getUniqueId(), ids);
|
2017-06-05 15:02:49 +02:00
|
|
|
}
|
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug(p.getName() + " doesn't have external plugin's permission");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE));
|
2017-06-05 15:02:49 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) {
|
|
|
|
Chest c = (Chest) b.getState();
|
|
|
|
ItemStack itemStack = shop.getProduct().getItemStack();
|
|
|
|
int amount = (p.isSneaking() ? itemStack.getMaxStackSize() : shop.getProduct().getAmount());
|
|
|
|
|
|
|
|
if (Utils.getAmount(c.getInventory(), itemStack) >= amount) {
|
|
|
|
if (confirmed || !Config.confirmShopping) {
|
|
|
|
buy(p, shop, p.isSneaking());
|
|
|
|
if (Config.confirmShopping) {
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.remove(shop.getID());
|
|
|
|
if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId());
|
|
|
|
else needsConfirmation.put(p.getUniqueId(), ids);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
plugin.debug("Needs confirmation");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM));
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.add(shop.getID());
|
|
|
|
needsConfirmation.put(p.getUniqueId(), ids);
|
2017-03-28 14:37:12 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), itemStack) > 0) {
|
|
|
|
if (confirmed || !Config.confirmShopping) {
|
|
|
|
buy(p, shop, p.isSneaking());
|
|
|
|
if (Config.confirmShopping) {
|
2017-08-15 12:38:38 +02:00
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
2019-05-03 16:47:35 +02:00
|
|
|
ids.remove(shop.getID());
|
|
|
|
if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId());
|
|
|
|
else needsConfirmation.put(p.getUniqueId(), ids);
|
2017-08-15 12:38:38 +02:00
|
|
|
}
|
2016-11-13 13:43:03 +01:00
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug("Needs confirmation");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM));
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.add(shop.getID());
|
|
|
|
needsConfirmation.put(p.getUniqueId(), ids);
|
2017-01-03 15:35:35 +01:00
|
|
|
}
|
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.OUT_OF_STOCK));
|
|
|
|
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())),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, shop.getProduct().getLocalizedName())));
|
2020-04-27 18:13:10 +02:00
|
|
|
} else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){
|
|
|
|
String message = LanguageUtils.getMessage(Message.VENDOR_OUT_OF_STOCK,
|
|
|
|
new Replacement(Placeholder.AMOUNT, String.valueOf(shop.getProduct().getAmount())),
|
|
|
|
new Replacement(Placeholder.ITEM_NAME, shop.getProduct().getLocalizedName()));
|
|
|
|
sendBungeeMessage(shop.getVendor().getName(), message);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug("Shop is out of stock");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug(p.getName() + " doesn't have external plugin's permission");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY));
|
|
|
|
plugin.debug(p.getName() + " is not permitted to buy");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.BUYING_DISABLED));
|
|
|
|
plugin.debug("Buying is disabled");
|
|
|
|
}
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
} else if ((e.getAction() == Action.LEFT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.RIGHT_CLICK_BLOCK && inverted)) {
|
|
|
|
e.setCancelled(true);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if ((shop.getShopType() == ShopType.ADMIN) || (!shop.getVendor().getUniqueId().equals(p.getUniqueId()))) {
|
|
|
|
plugin.debug(p.getName() + " wants to sell");
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (shop.getSellPrice() > 0) {
|
|
|
|
if (p.hasPermission(Permissions.SELL)) {
|
|
|
|
// TODO: Outsource shop use external permission
|
|
|
|
boolean externalPluginsAllowed = true;
|
2017-03-28 14:37:12 +02:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) {
|
2020-04-25 16:23:21 +02:00
|
|
|
try {
|
|
|
|
Class.forName("com.plotsquared.core.PlotSquared");
|
|
|
|
com.plotsquared.core.location.Location plotLocation =
|
|
|
|
new com.plotsquared.core.location.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ());
|
|
|
|
com.plotsquared.core.plot.Plot plot = plotLocation.getOwnedPlot();
|
|
|
|
externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.USE_SHOP, p);
|
|
|
|
} catch (ClassNotFoundException ex) {
|
|
|
|
com.github.intellectualsites.plotsquared.plot.object.Location plotLocation =
|
|
|
|
new com.github.intellectualsites.plotsquared.plot.object.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ());
|
|
|
|
com.github.intellectualsites.plotsquared.plot.object.Plot plot = plotLocation.getOwnedPlot();
|
|
|
|
externalPluginsAllowed = PlotSquaredOldShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredOldShopFlag.USE_SHOP, p);
|
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
}
|
2016-11-13 13:43:03 +01:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) {
|
|
|
|
String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop");
|
|
|
|
WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance();
|
|
|
|
Optional<IWrappedFlag<WrappedState>> flag = wgWrapper.getFlag(flagName, WrappedState.class);
|
|
|
|
if (!flag.isPresent()) plugin.debug("WorldGuard flag '" + flagName + "' is not present!");
|
|
|
|
WrappedState state = flag.map(f -> wgWrapper.queryFlag(p, b.getLocation(), f).orElse(WrappedState.DENY)).orElse(WrappedState.DENY);
|
|
|
|
externalPluginsAllowed = state == WrappedState.ALLOW;
|
|
|
|
}
|
2016-11-13 13:43:03 +01:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
ItemStack itemStack = shop.getProduct().getItemStack();
|
|
|
|
|
|
|
|
if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) {
|
|
|
|
boolean stack = p.isSneaking() && !Utils.hasAxeInHand(p);
|
|
|
|
int amount = stack ? itemStack.getMaxStackSize() : shop.getProduct().getAmount();
|
|
|
|
|
|
|
|
if (Utils.getAmount(p.getInventory(), itemStack) >= amount) {
|
|
|
|
if (confirmed || !Config.confirmShopping) {
|
|
|
|
sell(p, shop, stack);
|
|
|
|
if (Config.confirmShopping) {
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.remove(shop.getID());
|
|
|
|
if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId());
|
|
|
|
else needsConfirmation.put(p.getUniqueId(), ids);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
plugin.debug("Needs confirmation");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM));
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.add(shop.getID());
|
|
|
|
needsConfirmation.put(p.getUniqueId(), ids);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Config.autoCalculateItemAmount && Utils.getAmount(p.getInventory(), itemStack) > 0) {
|
|
|
|
if (confirmed || !Config.confirmShopping) {
|
|
|
|
sell(p, shop, stack);
|
|
|
|
if (Config.confirmShopping) {
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.remove(shop.getID());
|
|
|
|
if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId());
|
|
|
|
else needsConfirmation.put(p.getUniqueId(), ids);
|
2016-11-13 13:43:03 +01:00
|
|
|
}
|
2017-01-03 15:35:35 +01:00
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug("Needs confirmation");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM));
|
|
|
|
Set<Integer> ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet<Integer>();
|
|
|
|
ids.add(shop.getID());
|
|
|
|
needsConfirmation.put(p.getUniqueId(), ids);
|
2016-08-16 15:06:26 +02:00
|
|
|
}
|
2016-11-13 13:43:03 +01:00
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS));
|
|
|
|
plugin.debug(p.getName() + " doesn't have enough items");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-06-08 16:06:36 +02:00
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
} else {
|
2019-05-03 16:47:35 +02:00
|
|
|
plugin.debug(p.getName() + " doesn't have external plugin's permission");
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL_HERE));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL));
|
|
|
|
plugin.debug(p.getName() + " is not permitted to sell");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2019-05-03 16:47:35 +02:00
|
|
|
} else {
|
|
|
|
p.sendMessage(LanguageUtils.getMessage(Message.SELLING_DISABLED));
|
|
|
|
plugin.debug("Selling is disabled");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-18 17:32:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@EventHandler
|
|
|
|
public void onPlayerInteract(PlayerInteractEvent e) {
|
2018-07-25 14:37:02 +02:00
|
|
|
if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(e.getPlayer())) return;
|
2017-03-21 15:03:12 +01:00
|
|
|
handleInteractEvent(e);
|
2016-11-18 17:32:52 +01:00
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* Create a new shop
|
|
|
|
*
|
|
|
|
* @param executor Player, who executed the command, will receive the message and become the vendor of the shop
|
|
|
|
* @param location Where the shop will be located
|
|
|
|
* @param product Product of the Shop
|
|
|
|
* @param buyPrice Buy price
|
|
|
|
* @param sellPrice Sell price
|
|
|
|
* @param shopType Type of the shop
|
|
|
|
*/
|
2018-11-10 20:34:11 +01:00
|
|
|
private void create(final Player executor, final Location location, final ShopProduct product, final double buyPrice, final double sellPrice, final ShopType shopType) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " is creating new shop...");
|
2016-07-01 14:28:31 +02:00
|
|
|
|
2018-07-21 14:04:26 +02:00
|
|
|
if (!executor.hasPermission(Permissions.CREATE)) {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE));
|
2018-07-21 14:04:26 +02:00
|
|
|
plugin.debug(executor.getName() + " is not permitted to create the shop");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
double creationPrice = (shopType == ShopType.NORMAL) ? Config.shopCreationPriceNormal : Config.shopCreationPriceAdmin;
|
2017-02-09 21:51:39 +01:00
|
|
|
Shop shop = new Shop(plugin, executor, product, location, buyPrice, sellPrice, shopType);
|
2016-07-05 18:41:31 +02:00
|
|
|
|
2017-02-09 21:51:39 +01:00
|
|
|
ShopCreateEvent event = new ShopCreateEvent(executor, shop, creationPrice);
|
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
2019-05-03 16:47:35 +02:00
|
|
|
if (event.isCancelled() && !executor.hasPermission(Permissions.CREATE_PROTECTED)) {
|
2017-02-09 21:51:39 +01:00
|
|
|
plugin.debug("Create event cancelled");
|
2019-05-03 16:47:35 +02:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED));
|
2017-02-09 21:51:39 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-07-01 14:33:13 +02:00
|
|
|
|
2019-12-15 15:35:42 +01:00
|
|
|
if (creationPrice > 0) {
|
|
|
|
EconomyResponse r = plugin.getEconomy().withdrawPlayer(executor, location.getWorld().getName(), creationPrice);
|
|
|
|
if (!r.transactionSuccess()) {
|
|
|
|
plugin.debug("Economy transaction failed: " + r.errorMessage);
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage)));
|
|
|
|
return;
|
|
|
|
}
|
2017-02-09 21:51:39 +01:00
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2017-04-10 20:01:47 +02:00
|
|
|
shop.create(true);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2017-02-09 21:51:39 +01:00
|
|
|
plugin.debug("Shop created");
|
|
|
|
shopUtils.addShop(shop, true);
|
2017-02-08 17:02:03 +01:00
|
|
|
|
2019-05-03 16:47:35 +02:00
|
|
|
Message message = shopType == ShopType.ADMIN ? Message.ADMIN_SHOP_CREATED : Message.SHOP_CREATED;
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(message, new Replacement(Placeholder.CREATION_PRICE, creationPrice)));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* Remove a shop
|
|
|
|
* @param executor Player, who executed the command and will receive the message
|
|
|
|
* @param shop Shop to be removed
|
|
|
|
*/
|
2016-05-28 15:47:57 +02:00
|
|
|
private void remove(Player executor, Shop shop) {
|
2019-05-03 16:47:35 +02:00
|
|
|
if (shop.getShopType() == ShopType.ADMIN && !executor.hasPermission(Permissions.REMOVE_ADMIN)) {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_ADMIN));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shop.getShopType() == ShopType.NORMAL && !executor.getUniqueId().equals(shop.getVendor().getUniqueId())
|
|
|
|
&& !executor.hasPermission(Permissions.REMOVE_OTHER)) {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_OTHERS));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-29 20:05:56 +02:00
|
|
|
plugin.debug(executor.getName() + " is removing " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
ShopRemoveEvent event = new ShopRemoveEvent(executor, shop);
|
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
2016-08-03 13:49:31 +02:00
|
|
|
if (event.isCancelled()) {
|
|
|
|
plugin.debug("Remove event cancelled (#" + shop.getID() + ")");
|
|
|
|
return;
|
|
|
|
}
|
2016-07-05 18:41:31 +02:00
|
|
|
|
2019-06-03 16:53:23 +02:00
|
|
|
double creationPrice = shop.getShopType() == ShopType.ADMIN ? Config.shopCreationPriceAdmin : Config.shopCreationPriceNormal;
|
|
|
|
if (creationPrice > 0 && Config.refundShopCreation && executor.getUniqueId().equals(shop.getVendor().getUniqueId())) {
|
2018-11-04 14:21:14 +01:00
|
|
|
EconomyResponse r = plugin.getEconomy().depositPlayer(executor, shop.getLocation().getWorld().getName(), creationPrice);
|
2018-11-03 21:44:02 +01:00
|
|
|
if (!r.transactionSuccess()) {
|
|
|
|
plugin.debug("Economy transaction failed: " + r.errorMessage);
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED,
|
|
|
|
new Replacement(Placeholder.ERROR, r.errorMessage)));
|
2019-06-03 16:53:23 +02:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND,
|
|
|
|
new Replacement(Placeholder.CREATION_PRICE, 0)));
|
|
|
|
} else {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND,
|
|
|
|
new Replacement(Placeholder.CREATION_PRICE, creationPrice)));
|
2018-11-03 21:44:02 +01:00
|
|
|
}
|
2019-06-03 16:53:23 +02:00
|
|
|
} else {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED));
|
2018-11-03 21:44:02 +01:00
|
|
|
}
|
|
|
|
|
2016-07-13 15:03:54 +02:00
|
|
|
shopUtils.removeShop(shop, true);
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Removed shop (#" + shop.getID() + ")");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2017-03-21 15:03:12 +01:00
|
|
|
/**
|
|
|
|
* Open a shop
|
|
|
|
* @param executor Player, who executed the command and will receive the message
|
|
|
|
* @param shop Shop to be opened
|
2018-02-24 20:12:32 +01:00
|
|
|
* @param message Whether the player should receive the {@link Message#OPENED_SHOP} message
|
2017-03-21 15:03:12 +01:00
|
|
|
*/
|
|
|
|
private void open(Player executor, Shop shop, boolean message) {
|
2019-05-03 16:47:35 +02:00
|
|
|
if (!executor.getUniqueId().equals(shop.getVendor().getUniqueId()) && !executor.hasPermission(Permissions.OPEN_OTHER)) {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_OPEN_OTHERS));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-21 15:03:12 +01:00
|
|
|
plugin.debug(executor.getName() + " is opening " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")");
|
|
|
|
ShopOpenEvent event = new ShopOpenEvent(executor, shop);
|
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
if (event.isCancelled()) {
|
|
|
|
plugin.debug("Open event cancelled (#" + shop.getID() + ")");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
executor.openInventory(shop.getInventoryHolder().getInventory());
|
|
|
|
plugin.debug("Opened shop (#" + shop.getID() + ")");
|
2018-02-24 20:12:32 +01:00
|
|
|
if (message) executor.sendMessage(LanguageUtils.getMessage(Message.OPENED_SHOP,
|
|
|
|
new Replacement(Placeholder.VENDOR, shop.getVendor().getName())));
|
2017-03-21 15:03:12 +01:00
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param executor Player, who executed the command and will retrieve the information
|
|
|
|
* @param shop Shop from which the information will be retrieved
|
|
|
|
*/
|
2016-05-28 15:47:57 +02:00
|
|
|
private void info(Player executor, Shop shop) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " is retrieving shop info (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
ShopInfoEvent event = new ShopInfoEvent(executor, shop);
|
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2016-08-03 13:49:31 +02:00
|
|
|
if (event.isCancelled()) {
|
|
|
|
plugin.debug("Info event cancelled (#" + shop.getID() + ")");
|
|
|
|
return;
|
|
|
|
}
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
Chest c = (Chest) shop.getLocation().getBlock().getState();
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack itemStack = shop.getProduct().getItemStack();
|
|
|
|
int amount = Utils.getAmount(c.getInventory(), itemStack);
|
2019-06-03 17:03:24 +02:00
|
|
|
int space = Utils.getFreeSpaceForItem(c.getInventory(), itemStack);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2017-04-16 18:31:50 +02:00
|
|
|
String vendorName = (shop.getVendor().getName() == null ?
|
|
|
|
shop.getVendor().getUniqueId().toString() : shop.getVendor().getName());
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
String vendorString = LanguageUtils.getMessage(Message.SHOP_INFO_VENDOR,
|
|
|
|
new Replacement(Placeholder.VENDOR, vendorName));
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
// Make JSON message with item preview
|
|
|
|
JsonBuilder jb = getProductJson(shop.getProduct());
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
String disabled = LanguageUtils.getMessage(Message.SHOP_INFO_DISABLED);
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
String priceString = LanguageUtils.getMessage(Message.SHOP_INFO_PRICE,
|
|
|
|
new Replacement(Placeholder.BUY_PRICE, (shop.getBuyPrice() > 0 ? String.valueOf(shop.getBuyPrice()) : disabled)),
|
|
|
|
new Replacement(Placeholder.SELL_PRICE, (shop.getSellPrice() > 0 ? String.valueOf(shop.getSellPrice()) : disabled)));
|
2017-04-16 18:31:50 +02:00
|
|
|
|
|
|
|
String shopType = LanguageUtils.getMessage(shop.getShopType() == ShopType.NORMAL ?
|
2018-02-24 20:12:32 +01:00
|
|
|
Message.SHOP_INFO_NORMAL : Message.SHOP_INFO_ADMIN);
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
String stock = LanguageUtils.getMessage(Message.SHOP_INFO_STOCK,
|
2019-06-03 17:03:24 +02:00
|
|
|
new Replacement(Placeholder.STOCK, amount));
|
|
|
|
|
|
|
|
String chestSpace = LanguageUtils.getMessage(Message.SHOP_INFO_CHEST_SPACE,
|
|
|
|
new Replacement(Placeholder.CHEST_SPACE, space));
|
2016-08-05 22:16:14 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
executor.sendMessage(" ");
|
|
|
|
if (shop.getShopType() != ShopType.ADMIN) executor.sendMessage(vendorString);
|
|
|
|
jb.sendJson(executor);
|
2019-06-03 17:03:24 +02:00
|
|
|
if (shop.getShopType() != ShopType.ADMIN && shop.getBuyPrice() > 0) executor.sendMessage(stock);
|
|
|
|
if (shop.getShopType() != ShopType.ADMIN && shop.getSellPrice() > 0) executor.sendMessage(chestSpace);
|
2018-07-26 15:51:50 +02:00
|
|
|
executor.sendMessage(priceString);
|
|
|
|
executor.sendMessage(shopType);
|
|
|
|
executor.sendMessage(" ");
|
|
|
|
}
|
2017-05-20 20:10:07 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
/**
|
|
|
|
* Create a {@link JsonBuilder} containing the shop info message for the product
|
|
|
|
* in which you can hover the item name to get a preview.
|
|
|
|
* @param product The product of the shop
|
|
|
|
* @return A {@link JsonBuilder} that can send the message via {@link JsonBuilder#sendJson(Player)}
|
|
|
|
*/
|
2018-11-10 20:34:11 +01:00
|
|
|
private JsonBuilder getProductJson(ShopProduct product) {
|
2018-07-26 15:51:50 +02:00
|
|
|
// 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());
|
2019-08-07 19:57:09 +02:00
|
|
|
String productName = product.getLocalizedName();
|
2018-07-26 15:51:50 +02:00
|
|
|
String jsonItem = "";
|
|
|
|
JsonBuilder jb = new JsonBuilder(plugin);
|
|
|
|
JsonBuilder.PartArray rootArray = new JsonBuilder.PartArray();
|
|
|
|
|
|
|
|
try {
|
|
|
|
Class<?> craftItemStackClass = Utils.getCraftClass("inventory.CraftItemStack");
|
2018-11-10 20:34:11 +01:00
|
|
|
Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, product.getItemStack());
|
2018-07-26 15:51:50 +02:00
|
|
|
Class<?> nbtTagCompoundClass = Utils.getNMSClass("NBTTagCompound");
|
|
|
|
Object nbtTagCompound = nbtTagCompoundClass.getConstructor().newInstance();
|
|
|
|
nmsStack.getClass().getMethod("save", nbtTagCompoundClass).invoke(nmsStack, nbtTagCompound);
|
|
|
|
jsonItem = new JsonPrimitive(nbtTagCompound.toString()).toString();
|
|
|
|
} catch (Exception e) {
|
|
|
|
plugin.getLogger().severe("Failed to create JSON from item. Product preview will not be available.");
|
|
|
|
plugin.debug("Failed to create JSON from item:");
|
|
|
|
plugin.debug(e);
|
|
|
|
jb.setRootPart(new JsonBuilder.Part(productString.replace(Placeholder.ITEM_NAME.toString(), productName)));
|
|
|
|
return jb;
|
2016-06-22 20:51:19 +02:00
|
|
|
}
|
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
for (int i = 0; i < parts.length; i++) {
|
|
|
|
String part = parts[i];
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
// Remove spaces at start and end that were added before
|
|
|
|
if (i == 0 && part.startsWith(" ")) {
|
|
|
|
part = part.substring(1);
|
|
|
|
} else if (i == parts.length - 1 && part.endsWith(" ")) {
|
|
|
|
part = part.substring(0, part.length() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
String formatPrefix = "";
|
|
|
|
|
|
|
|
// A color code resets all format codes, so only format codes
|
|
|
|
// after the last color code have to be found.
|
|
|
|
int lastColorGroupEndIndex = 0;
|
|
|
|
|
|
|
|
Matcher colorMatcher = COLOR_CODE_PATTERN.matcher(part);
|
|
|
|
if (colorMatcher.find()) {
|
|
|
|
formatPrefix = colorMatcher.group(1);
|
|
|
|
lastColorGroupEndIndex = colorMatcher.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher formatMatcher = FORMAT_CODE_PATTERN.matcher(part);
|
|
|
|
while (formatMatcher.find(lastColorGroupEndIndex)) {
|
|
|
|
formatPrefix += formatMatcher.group(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
rootArray.addPart(new JsonBuilder.Part(part));
|
|
|
|
|
|
|
|
if (i < parts.length - 1) {
|
|
|
|
JsonBuilder.PartMap hoverEvent = new JsonBuilder.PartMap();
|
|
|
|
hoverEvent.setValue("action", new JsonBuilder.Part("show_item"));
|
|
|
|
hoverEvent.setValue("value", new JsonBuilder.Part(jsonItem, false));
|
2017-04-16 18:31:50 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
JsonBuilder.PartMap itemNameMap = JsonBuilder.parse(formatPrefix + productName).toMap();
|
|
|
|
itemNameMap.setValue("hoverEvent", hoverEvent);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
rootArray.addPart(itemNameMap);
|
|
|
|
}
|
2017-04-16 18:31:50 +02:00
|
|
|
}
|
|
|
|
|
2018-07-26 15:51:50 +02:00
|
|
|
jb.setRootPart(rootArray);
|
|
|
|
return jb;
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* A player buys from a shop
|
|
|
|
* @param executor Player, who executed the command and will buy the product
|
|
|
|
* @param shop Shop, from which the player buys
|
2017-03-21 15:40:23 +01:00
|
|
|
* @param stack Whether a whole stack should be bought
|
2016-06-30 21:59:06 +02:00
|
|
|
*/
|
2017-08-15 12:53:15 +02:00
|
|
|
private void buy(Player executor, final Shop shop, boolean stack) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " is buying (#" + shop.getID() + ")");
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack itemStack = shop.getProduct().getItemStack();
|
2017-03-21 15:40:23 +01:00
|
|
|
int amount = shop.getProduct().getAmount();
|
2018-11-10 20:34:11 +01:00
|
|
|
if (stack) amount = itemStack.getMaxStackSize();
|
2017-03-21 15:40:23 +01:00
|
|
|
|
2017-06-02 14:56:34 +02:00
|
|
|
String worldName = shop.getLocation().getWorld().getName();
|
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
double price = shop.getBuyPrice();
|
|
|
|
if (stack) price = (price / shop.getProduct().getAmount()) * amount;
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (econ.getBalance(executor, worldName) >= price || Config.autoCalculateItemAmount) {
|
2017-03-21 15:40:23 +01:00
|
|
|
|
2017-06-02 14:56:34 +02:00
|
|
|
int amountForMoney = (int) (amount / price * econ.getBalance(executor, worldName));
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (amountForMoney == 0 && Config.autoCalculateItemAmount) {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_MONEY));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
plugin.debug(executor.getName() + " has enough money for " + amountForMoney + " item(s) (#" + shop.getID() + ")");
|
2016-05-28 15:47:57 +02:00
|
|
|
|
|
|
|
Block b = shop.getLocation().getBlock();
|
|
|
|
Chest c = (Chest) b.getState();
|
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
int amountForChestItems = Utils.getAmount(c.getInventory(), itemStack);
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
if (amountForChestItems == 0 && shop.getShopType() != ShopType.ADMIN) {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.OUT_OF_STOCK));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack product = new ItemStack(itemStack);
|
2017-03-21 15:40:23 +01:00
|
|
|
if (stack) product.setAmount(amount);
|
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
Inventory inventory = executor.getInventory();
|
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
int freeSpace = Utils.getFreeSpaceForItem(inventory, product);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
if (freeSpace == 0) {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_INVENTORY_SPACE));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
int newAmount = amount;
|
2016-08-17 13:14:35 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (Config.autoCalculateItemAmount) {
|
2016-08-17 13:14:35 +02:00
|
|
|
if (shop.getShopType() == ShopType.ADMIN)
|
|
|
|
newAmount = Math.min(amountForMoney, freeSpace);
|
|
|
|
else
|
|
|
|
newAmount = Math.min(Math.min(amountForMoney, amountForChestItems), freeSpace);
|
|
|
|
}
|
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
if (newAmount > amount) newAmount = amount;
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ShopProduct newProduct = new ShopProduct(product, newAmount);
|
2017-03-21 15:40:23 +01:00
|
|
|
double newPrice = (price / amount) * newAmount;
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2017-03-21 15:40:23 +01:00
|
|
|
if (freeSpace >= newAmount) {
|
2016-08-16 15:06:26 +02:00
|
|
|
plugin.debug(executor.getName() + " has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
|
|
|
|
|
2016-11-23 16:11:07 +01:00
|
|
|
EconomyResponse r = econ.withdrawPlayer(executor, worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
|
|
|
if (r.transactionSuccess()) {
|
2016-11-23 16:11:07 +01:00
|
|
|
EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.depositPlayer(shop.getVendor(), worldName, newPrice) : null;
|
2016-09-07 17:00:59 +02:00
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
if (r2 != null) {
|
|
|
|
if (r2.transactionSuccess()) {
|
2016-08-16 15:06:26 +02:00
|
|
|
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice);
|
2016-07-05 18:41:31 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
|
|
|
|
if (event.isCancelled()) {
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.depositPlayer(executor, worldName, newPrice);
|
|
|
|
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice);
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-01 12:20:10 +02:00
|
|
|
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
|
2016-08-18 13:30:14 +02:00
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
addToInventory(inventory, newProduct);
|
|
|
|
removeFromInventory(c.getInventory(), newProduct);
|
2016-05-31 18:07:38 +02:00
|
|
|
executor.updateInventory();
|
2016-08-19 12:48:11 +02:00
|
|
|
|
2017-08-15 12:53:15 +02:00
|
|
|
new BukkitRunnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (plugin.getHologramFormat().isDynamic()) {
|
|
|
|
shop.updateHologramText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.runTaskLater(plugin, 1L);
|
|
|
|
|
2016-08-19 12:48:11 +02:00
|
|
|
String vendorName = (shop.getVendor().getName() == null ? shop.getVendor().getUniqueId().toString() : shop.getVendor().getName());
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)),
|
2018-02-24 20:12:32 +01:00
|
|
|
new Replacement(Placeholder.VENDOR, vendorName)));
|
2016-05-31 18:07:38 +02:00
|
|
|
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
|
|
|
|
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)),
|
2018-02-24 20:12:32 +01:00
|
|
|
new Replacement(Placeholder.PLAYER, executor.getName())));
|
2020-04-27 18:13:10 +02:00
|
|
|
} else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){
|
|
|
|
String message = 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.PLAYER, executor.getName()));
|
|
|
|
sendBungeeMessage(shop.getVendor().getName(),message);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-05-31 18:07:38 +02:00
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
} else {
|
2016-09-07 17:00:59 +02:00
|
|
|
plugin.debug("Economy transaction failed (r2): " + r2.errorMessage + " (#" + shop.getID() + ")");
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r2.errorMessage)));
|
2017-06-08 11:31:23 +02:00
|
|
|
econ.withdrawPlayer(shop.getVendor(), worldName, newPrice);
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.depositPlayer(executor, worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
2016-08-16 15:06:26 +02:00
|
|
|
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice);
|
2016-07-05 18:41:31 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
|
|
|
|
if (event.isCancelled()) {
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.depositPlayer(executor, worldName, newPrice);
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Buy event cancelled (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-01 12:20:10 +02:00
|
|
|
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
|
2016-08-18 13:30:14 +02:00
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
addToInventory(inventory, newProduct);
|
2016-05-31 18:07:38 +02:00
|
|
|
executor.updateInventory();
|
2017-08-15 12:53:15 +02:00
|
|
|
|
|
|
|
new BukkitRunnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (plugin.getHologramFormat().isDynamic()) {
|
|
|
|
shop.updateHologramText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.runTaskLater(plugin, 1L);
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS_ADMIN, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice))));
|
2016-08-03 13:49:31 +02:00
|
|
|
|
|
|
|
plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
2016-09-07 17:00:59 +02:00
|
|
|
plugin.debug("Economy transaction failed (r): " + r.errorMessage + " (#" + shop.getID() + ")");
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage)));
|
2017-06-08 11:31:23 +02:00
|
|
|
econ.depositPlayer(executor, worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_INVENTORY_SPACE));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_MONEY));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* A player sells to a shop
|
|
|
|
* @param executor Player, who executed the command and will sell the product
|
|
|
|
* @param shop Shop, to which the player sells
|
|
|
|
*/
|
2017-08-15 12:53:15 +02:00
|
|
|
private void sell(Player executor, final Shop shop, boolean stack) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " is selling (#" + shop.getID() + ")");
|
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack itemStack = shop.getProduct().getItemStack();
|
2017-03-25 13:45:17 +01:00
|
|
|
int amount = shop.getProduct().getAmount();
|
2018-11-10 20:34:11 +01:00
|
|
|
if (stack) amount = itemStack.getMaxStackSize();
|
2017-03-25 13:45:17 +01:00
|
|
|
|
|
|
|
double price = shop.getSellPrice();
|
|
|
|
if (stack) price = (price / shop.getProduct().getAmount()) * amount;
|
|
|
|
|
2017-06-02 14:56:34 +02:00
|
|
|
String worldName = shop.getLocation().getWorld().getName();
|
|
|
|
|
2018-07-26 17:25:55 +02:00
|
|
|
if (shop.getShopType() == ShopType.ADMIN || econ.getBalance(shop.getVendor(), worldName) >= price || Config.autoCalculateItemAmount) {
|
|
|
|
int amountForMoney = 1;
|
|
|
|
|
|
|
|
if (shop.getShopType() != ShopType.ADMIN) {
|
|
|
|
amountForMoney = (int) (amount / price * econ.getBalance(shop.getVendor(), worldName));
|
|
|
|
}
|
2016-08-16 15:06:26 +02:00
|
|
|
|
|
|
|
plugin.debug("Vendor has enough money for " + amountForMoney + " item(s) (#" + shop.getID() + ")");
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (amountForMoney == 0 && Config.autoCalculateItemAmount && shop.getShopType() != ShopType.ADMIN) {
|
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.VENDOR_NOT_ENOUGH_MONEY));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
Block block = shop.getLocation().getBlock();
|
|
|
|
Chest chest = (Chest) block.getState();
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
int amountForItemCount = Utils.getAmount(executor.getInventory(), itemStack);
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2017-03-25 13:45:17 +01:00
|
|
|
if (amountForItemCount == 0) {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack product = new ItemStack(itemStack);
|
2017-03-25 13:45:17 +01:00
|
|
|
if (stack) product.setAmount(amount);
|
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
Inventory inventory = chest.getInventory();
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
int freeSpace = Utils.getFreeSpaceForItem(inventory, product);
|
|
|
|
|
2017-03-25 13:45:17 +01:00
|
|
|
if (freeSpace == 0 && shop.getShopType() != ShopType.ADMIN) {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE));
|
2016-08-16 15:06:26 +02:00
|
|
|
return;
|
2016-05-31 18:07:38 +02:00
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2017-03-25 13:45:17 +01:00
|
|
|
int newAmount = amount;
|
2016-08-17 13:14:35 +02:00
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (Config.autoCalculateItemAmount) {
|
2016-08-17 13:14:35 +02:00
|
|
|
if (shop.getShopType() == ShopType.ADMIN)
|
|
|
|
newAmount = amountForItemCount;
|
|
|
|
else
|
2017-03-25 13:45:17 +01:00
|
|
|
newAmount = Math.min(Math.min(amountForMoney, amountForItemCount), freeSpace);
|
2016-08-17 13:14:35 +02:00
|
|
|
}
|
|
|
|
|
2017-03-25 13:45:17 +01:00
|
|
|
if (newAmount > amount) newAmount = amount;
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2018-11-10 20:34:11 +01:00
|
|
|
ShopProduct newProduct = new ShopProduct(product, newAmount);
|
2017-03-25 13:45:17 +01:00
|
|
|
double newPrice = (price / amount) * newAmount;
|
2016-08-16 15:06:26 +02:00
|
|
|
|
2017-03-25 13:45:17 +01:00
|
|
|
if (freeSpace >= newAmount || shop.getShopType() == ShopType.ADMIN) {
|
2016-08-16 15:06:26 +02:00
|
|
|
plugin.debug("Chest has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")");
|
|
|
|
|
2016-11-23 16:11:07 +01:00
|
|
|
EconomyResponse r = econ.depositPlayer(executor, worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
if (r.transactionSuccess()) {
|
2016-11-23 16:11:07 +01:00
|
|
|
EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.withdrawPlayer(shop.getVendor(), worldName, newPrice) : null;
|
2016-09-07 17:00:59 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
if (r2 != null) {
|
2016-05-28 15:47:57 +02:00
|
|
|
if (r2.transactionSuccess()) {
|
2016-08-16 15:06:26 +02:00
|
|
|
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice);
|
2016-07-05 18:41:31 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
|
|
|
|
if (event.isCancelled()) {
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.withdrawPlayer(executor, worldName, newPrice);
|
|
|
|
econ.depositPlayer(shop.getVendor(), worldName, newPrice);
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Sell event cancelled (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-01 12:20:10 +02:00
|
|
|
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
|
2016-08-18 13:30:14 +02:00
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
addToInventory(inventory, newProduct);
|
|
|
|
removeFromInventory(executor.getInventory(), newProduct);
|
2016-05-31 18:07:38 +02:00
|
|
|
executor.updateInventory();
|
2016-08-19 12:48:11 +02:00
|
|
|
|
2017-08-15 12:53:15 +02:00
|
|
|
new BukkitRunnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (plugin.getHologramFormat().isDynamic()) {
|
|
|
|
shop.updateHologramText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.runTaskLater(plugin, 1L);
|
|
|
|
|
2016-08-19 12:48:11 +02:00
|
|
|
String vendorName = (shop.getVendor().getName() == null ? shop.getVendor().getUniqueId().toString() : shop.getVendor().getName());
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.SELL_SUCCESS, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)),
|
2018-02-24 20:12:32 +01:00
|
|
|
new Replacement(Placeholder.VENDOR, vendorName)));
|
2016-05-31 18:07:38 +02:00
|
|
|
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")");
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
if (shop.getVendor().isOnline() && Config.enableVendorMessages) {
|
|
|
|
shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_SOLD, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)),
|
2018-02-24 20:12:32 +01:00
|
|
|
new Replacement(Placeholder.PLAYER, executor.getName())));
|
2020-04-27 18:13:10 +02:00
|
|
|
} else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){
|
|
|
|
String message = LanguageUtils.getMessage( Message.SOMEONE_SOLD, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)),
|
|
|
|
new Replacement(Placeholder.PLAYER, executor.getName()));
|
|
|
|
sendBungeeMessage(shop.getVendor().getName(),message);
|
2016-05-31 18:07:38 +02:00
|
|
|
}
|
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
} else {
|
2016-09-07 17:00:59 +02:00
|
|
|
plugin.debug("Economy transaction failed (r2): " + r2.errorMessage + " (#" + shop.getID() + ")");
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r2.errorMessage)));
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.withdrawPlayer(executor, worldName, newPrice);
|
2017-06-08 11:31:23 +02:00
|
|
|
econ.depositPlayer(shop.getVendor(), worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-05-31 18:07:38 +02:00
|
|
|
|
2016-05-28 15:47:57 +02:00
|
|
|
} else {
|
2016-08-16 15:06:26 +02:00
|
|
|
ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice);
|
2016-07-05 18:41:31 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
|
|
|
|
if (event.isCancelled()) {
|
2017-06-02 14:56:34 +02:00
|
|
|
econ.withdrawPlayer(executor, worldName, newPrice);
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Sell event cancelled (#" + shop.getID() + ")");
|
2016-07-05 18:41:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-01 12:20:10 +02:00
|
|
|
database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
|
2016-08-18 13:30:14 +02:00
|
|
|
|
2016-08-16 15:06:26 +02:00
|
|
|
removeFromInventory(executor.getInventory(), newProduct);
|
2016-05-31 18:07:38 +02:00
|
|
|
executor.updateInventory();
|
2017-08-15 12:53:15 +02:00
|
|
|
|
|
|
|
new BukkitRunnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (plugin.getHologramFormat().isDynamic()) {
|
|
|
|
shop.updateHologramText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.runTaskLater(plugin, 1L);
|
|
|
|
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.SELL_SUCCESS_ADMIN, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)),
|
2019-08-07 19:57:09 +02:00
|
|
|
new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice))));
|
2016-08-03 13:49:31 +02:00
|
|
|
|
|
|
|
plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")");
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2016-09-07 17:00:59 +02:00
|
|
|
plugin.debug("Economy transaction failed (r): " + r.errorMessage + " (#" + shop.getID() + ")");
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage)));
|
2017-06-08 11:31:23 +02:00
|
|
|
econ.withdrawPlayer(executor, worldName, newPrice);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
} else {
|
2018-02-24 20:12:32 +01:00
|
|
|
executor.sendMessage(LanguageUtils.getMessage(Message.VENDOR_NOT_ENOUGH_MONEY));
|
2016-05-31 18:07:38 +02:00
|
|
|
}
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* Adds items to an inventory
|
|
|
|
* @param inventory The inventory, to which the items will be added
|
|
|
|
* @param itemStack Items to add
|
|
|
|
* @return Whether all items were added to the inventory
|
|
|
|
*/
|
2018-11-10 20:34:11 +01:00
|
|
|
private boolean addToInventory(Inventory inventory, ShopProduct product) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Adding items to inventory...");
|
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
HashMap<Integer, ItemStack> inventoryItems = new HashMap<>();
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack itemStack = product.getItemStack();
|
|
|
|
int amount = product.getAmount();
|
2016-05-31 18:07:38 +02:00
|
|
|
int added = 0;
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
if (inventory instanceof PlayerInventory) {
|
2016-06-22 20:51:19 +02:00
|
|
|
if (Utils.getMajorVersion() >= 9) {
|
2016-05-31 18:07:38 +02:00
|
|
|
inventoryItems.put(40, inventory.getItem(40));
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
for (int i = 0; i < 36; i++) {
|
|
|
|
inventoryItems.put(i, inventory.getItem(i));
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
} else {
|
|
|
|
for (int i = 0; i < inventory.getSize(); i++) {
|
|
|
|
inventoryItems.put(i, inventory.getItem(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
slotLoop:
|
|
|
|
for (int slot : inventoryItems.keySet()) {
|
|
|
|
while (added < amount) {
|
|
|
|
ItemStack item = inventory.getItem(slot);
|
|
|
|
|
2016-11-17 17:39:09 +01:00
|
|
|
if (item != null && item.getType() != Material.AIR) {
|
2017-01-03 13:06:29 +01:00
|
|
|
if (Utils.isItemSimilar(item, itemStack)) {
|
2016-05-31 18:07:38 +02:00
|
|
|
if (item.getAmount() != item.getMaxStackSize()) {
|
|
|
|
ItemStack newItemStack = new ItemStack(item);
|
|
|
|
newItemStack.setAmount(item.getAmount() + 1);
|
|
|
|
inventory.setItem(slot, newItemStack);
|
|
|
|
added++;
|
2016-05-28 15:47:57 +02:00
|
|
|
} else {
|
2016-05-31 18:07:38 +02:00
|
|
|
continue slotLoop;
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
2016-05-31 18:07:38 +02:00
|
|
|
continue slotLoop;
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-05-31 18:07:38 +02:00
|
|
|
} else {
|
|
|
|
ItemStack newItemStack = new ItemStack(itemStack);
|
|
|
|
newItemStack.setAmount(1);
|
|
|
|
inventory.setItem(slot, newItemStack);
|
|
|
|
added++;
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-05-31 18:07:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (added == amount);
|
|
|
|
}
|
|
|
|
|
2016-06-30 21:59:06 +02:00
|
|
|
/**
|
|
|
|
* Removes items to from an inventory
|
|
|
|
* @param inventory The inventory, from which the items will be removed
|
|
|
|
* @param itemStack Items to remove
|
|
|
|
* @return Whether all items were removed from the inventory
|
|
|
|
*/
|
2018-11-10 20:34:11 +01:00
|
|
|
private boolean removeFromInventory(Inventory inventory, ShopProduct product) {
|
2016-08-03 13:49:31 +02:00
|
|
|
plugin.debug("Removing items from inventory...");
|
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
HashMap<Integer, ItemStack> inventoryItems = new HashMap<>();
|
2018-11-10 20:34:11 +01:00
|
|
|
ItemStack itemStack = product.getItemStack();
|
|
|
|
int amount = product.getAmount();
|
2016-05-31 18:07:38 +02:00
|
|
|
int removed = 0;
|
|
|
|
|
|
|
|
if (inventory instanceof PlayerInventory) {
|
2016-06-22 20:51:19 +02:00
|
|
|
if (Utils.getMajorVersion() >= 9) {
|
2016-05-31 18:07:38 +02:00
|
|
|
inventoryItems.put(40, inventory.getItem(40));
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 18:07:38 +02:00
|
|
|
for (int i = 0; i < 36; i++) {
|
|
|
|
inventoryItems.put(i, inventory.getItem(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < inventory.getSize(); i++) {
|
|
|
|
inventoryItems.put(i, inventory.getItem(i));
|
|
|
|
}
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2016-05-31 18:07:38 +02:00
|
|
|
|
|
|
|
slotLoop:
|
|
|
|
for (int slot : inventoryItems.keySet()) {
|
|
|
|
while (removed < amount) {
|
|
|
|
ItemStack item = inventory.getItem(slot);
|
|
|
|
|
2016-11-17 17:39:09 +01:00
|
|
|
if (item != null && item.getType() != Material.AIR) {
|
2017-01-03 13:06:29 +01:00
|
|
|
if (Utils.isItemSimilar(item, itemStack)) {
|
2016-05-31 18:07:38 +02:00
|
|
|
if (item.getAmount() > 0) {
|
|
|
|
int newAmount = item.getAmount() - 1;
|
|
|
|
|
|
|
|
ItemStack newItemStack = new ItemStack(item);
|
|
|
|
newItemStack.setAmount(newAmount);
|
|
|
|
|
|
|
|
if (newAmount == 0)
|
|
|
|
inventory.setItem(slot, null);
|
|
|
|
else
|
|
|
|
inventory.setItem(slot, newItemStack);
|
|
|
|
|
|
|
|
removed++;
|
|
|
|
} else {
|
|
|
|
continue slotLoop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
continue slotLoop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
continue slotLoop;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (removed == amount);
|
2016-05-28 15:47:57 +02:00
|
|
|
}
|
2015-09-02 13:06:48 +02:00
|
|
|
|
2020-04-27 18:13:10 +02:00
|
|
|
public void sendBungeeMessage(String player, String message) {
|
|
|
|
try {
|
|
|
|
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
|
|
|
DataOutputStream out = new DataOutputStream(b);
|
|
|
|
|
|
|
|
out.writeUTF("Message");
|
|
|
|
out.writeUTF(player);
|
|
|
|
out.writeUTF(message);
|
|
|
|
|
|
|
|
if (!plugin.getServer().getOnlinePlayers().isEmpty()) {
|
|
|
|
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
|
|
Player p = plugin.getServer().getOnlinePlayers().iterator().next();
|
|
|
|
p.sendPluginMessage(plugin, "BungeeCord", b.toByteArray());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
plugin.debug("Failed to send bungee message");
|
|
|
|
plugin.debug(e);
|
|
|
|
plugin.getLogger().warning("Failed to send BungeeCord message");
|
|
|
|
}
|
|
|
|
}
|
2015-09-02 13:06:48 +02:00
|
|
|
}
|