From 1c8cdb06392d0e0884db6cb123bd0ada5624388b Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 3 May 2019 16:47:35 +0200 Subject: [PATCH] Outsource external checks for shop creation Every supported plugin has its own listener for ShopCreateEvent and ShopExtendEvent. I also tried to clean up a bit, there can be done more though. --- .../java/de/epiceric/shopchest/ShopChest.java | 24 + .../shopchest/event/ShopExtendEvent.java | 37 + .../external/listeners/ASkyBlockListener.java | 62 ++ .../listeners/GriefPreventionListener.java | 62 ++ .../listeners/IslandWorldListener.java | 59 ++ .../listeners/PlotSquaredListener.java | 80 ++ .../external/listeners/TownyListener.java | 84 ++ .../external/listeners/USkyBlockListener.java | 61 ++ .../listeners/WorldGuardListener.java | 92 ++ .../shopchest/language/Replacement.java | 4 +- .../listeners/ChestProtectListener.java | 160 +--- .../listeners/ShopInteractListener.java | 808 +++++++----------- .../listeners/WorldGuardListener.java | 63 +- .../de/epiceric/shopchest/utils/Utils.java | 67 +- 14 files changed, 960 insertions(+), 703 deletions(-) create mode 100644 src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java create mode 100644 src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java diff --git a/src/main/java/de/epiceric/shopchest/ShopChest.java b/src/main/java/de/epiceric/shopchest/ShopChest.java index 0737071..d7cf84b 100644 --- a/src/main/java/de/epiceric/shopchest/ShopChest.java +++ b/src/main/java/de/epiceric/shopchest/ShopChest.java @@ -8,6 +8,12 @@ import de.epiceric.shopchest.config.HologramFormat; import de.epiceric.shopchest.event.ShopInitializedEvent; import de.epiceric.shopchest.external.PlotSquaredShopFlag; import de.epiceric.shopchest.external.WorldGuardShopFlag; +import de.epiceric.shopchest.external.listeners.ASkyBlockListener; +import de.epiceric.shopchest.external.listeners.GriefPreventionListener; +import de.epiceric.shopchest.external.listeners.IslandWorldListener; +import de.epiceric.shopchest.external.listeners.PlotSquaredListener; +import de.epiceric.shopchest.external.listeners.TownyListener; +import de.epiceric.shopchest.external.listeners.USkyBlockListener; import de.epiceric.shopchest.language.LanguageUtils; import de.epiceric.shopchest.listeners.AreaShopListener; import de.epiceric.shopchest.listeners.BlockExplodeListener; @@ -196,6 +202,7 @@ public class ShopChest extends JavaPlugin { 5L, TimeUnit.SECONDS, new LinkedBlockingQueue()); registerListeners(); + registerExternalListeners(); initializeShops(); updater = new ShopUpdater(this); @@ -393,6 +400,23 @@ public class ShopChest extends JavaPlugin { } } + private void registerExternalListeners() { + if (hasASkyBlock()) + getServer().getPluginManager().registerEvents(new ASkyBlockListener(this), this); + if (hasGriefPrevention()) + getServer().getPluginManager().registerEvents(new GriefPreventionListener(this), this); + if (hasIslandWorld()) + getServer().getPluginManager().registerEvents(new IslandWorldListener(this), this); + if (hasPlotSquared()) + getServer().getPluginManager().registerEvents(new PlotSquaredListener(this), this); + if (hasTowny()) + getServer().getPluginManager().registerEvents(new TownyListener(this), this); + if (hasUSkyBlock()) + getServer().getPluginManager().registerEvents(new USkyBlockListener(this), this); + if (hasWorldGuard()) + getServer().getPluginManager().registerEvents(new de.epiceric.shopchest.external.listeners.WorldGuardListener(this), this); + } + /** * Initializes the shops */ diff --git a/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java b/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java new file mode 100644 index 0000000..cc6a2d9 --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java @@ -0,0 +1,37 @@ +package de.epiceric.shopchest.event; + +import de.epiceric.shopchest.shop.Shop; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +/** + * Called when a player extends a shop (making a chest a double chest) + */ +public class ShopExtendEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + private Location newChestLocation; + + public ShopExtendEvent(Player player, Shop shop, Location newChest) { + super(player, shop); + this.newChestLocation = newChest; + } + + /** + * @return Location of the placed chest + */ + public Location getNewChestLocation() { + return newChestLocation; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java new file mode 100644 index 0000000..701d2d1 --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java @@ -0,0 +1,62 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import com.wasteofplastic.askyblock.ASkyBlockAPI; +import com.wasteofplastic.askyblock.Island; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class ASkyBlockListener implements Listener { + private final ShopChest plugin; + + public ASkyBlockListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + Island island = ASkyBlockAPI.getInstance().getIslandAt(loc); + if (island == null) + return false; + + if (!player.getUniqueId().equals(island.getOwner()) && !island.getMembers().contains(player.getUniqueId())) { + e.setCancelled(true); + plugin.debug("Cancel Reason: ASkyBlock"); + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java new file mode 100644 index 0000000..3246b0f --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java @@ -0,0 +1,62 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import me.ryanhamshire.GriefPrevention.Claim; +import me.ryanhamshire.GriefPrevention.GriefPrevention; + +public class GriefPreventionListener implements Listener { + private final ShopChest plugin; + private final GriefPrevention griefPrevention; + + public GriefPreventionListener(ShopChest plugin) { + this.plugin = plugin; + this.griefPrevention = plugin.getGriefPrevention(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableGriefPreventionIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + Claim claim = griefPrevention.dataStore.getClaimAt(loc, false, null); + if (claim == null) + return false; + + if (claim.allowContainers(player) != null) { + e.setCancelled(true); + plugin.debug("Cancel Reason: GriefPrevention"); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java new file mode 100644 index 0000000..2745008 --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java @@ -0,0 +1,59 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import pl.islandworld.api.IslandWorldApi; + +public class IslandWorldListener implements Listener { + private final ShopChest plugin; + + public IslandWorldListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableIslandWorldIntegration || !IslandWorldApi.isInitialized()) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableIslandWorldIntegration || !IslandWorldApi.isInitialized()) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + if (!loc.getWorld().getName().equals(IslandWorldApi.getIslandWorld().getName())) + return false; + + if (!IslandWorldApi.canBuildOnLocation(player, loc, true)) { + e.setCancelled(true); + plugin.debug("Cancel Reason: IslandWorld"); + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java new file mode 100644 index 0000000..9aab2b6 --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java @@ -0,0 +1,80 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import com.github.intellectualsites.plotsquared.plot.object.Location; +import com.github.intellectualsites.plotsquared.plot.object.Plot; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.external.PlotSquaredShopFlag; +import de.epiceric.shopchest.utils.Utils; + +public class PlotSquaredListener implements Listener { + private final ShopChest plugin; + + public PlotSquaredListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (org.bukkit.Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + // TODO: Outsource shop use external permission + + // @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + // public void onBuySell(ShopBuySellEvent e) { + // if (!Config.enablePlotsquaredIntegration) + // return; + + // ShopType shopType = e.getShop().getShopType(); + // GroupFlag flag = shopType == ShopType.ADMIN ? PlotSquaredShopFlag.USE_ADMIN_SHOP : PlotSquaredShopFlag.USE_SHOP; + + // Set chestLocations = Utils.getChestLocations(e.getShop()); + // for (org.bukkit.Location loc : chestLocations) { + // Location plotLocation = new Location(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + // Plot plot = plotLocation.getOwnedPlot(); + // if (!isFlagAllowed(plot, flag, e.getPlayer())) { + // e.setCancelled(true); + // plugin.debug("Cancel Reason: PlotSquared"); + // return; + // } + // } + // } + + private boolean handleForLocation(Player player, org.bukkit.Location loc, Cancellable e) { + Location plotLocation = new Location(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + Plot plot = plotLocation.getOwnedPlot(); + if (!PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.CREATE_SHOP, player)) { + e.setCancelled(true); + plugin.debug("Cancel Reason: PlotSquared"); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java new file mode 100644 index 0000000..85c736b --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java @@ -0,0 +1,84 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Optional; +import java.util.Set; + +import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.TownBlock; +import com.palmergames.bukkit.towny.object.TownyUniverse; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class TownyListener implements Listener { + private final ShopChest plugin; + + public TownyListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableTownyIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + TownBlock townBlock = TownyUniverse.getTownBlock(loc); + if (townBlock == null) + return false; + + try { + Town town = townBlock.getTown(); + Optional playerResident = town.getResidents().stream() + .filter(r -> r.getName().equals(player.getName())) + .findFirst(); + + if (!playerResident.isPresent()) { + e.setCancelled(true); + plugin.debug("Cancel Reason: Towny (no resident)"); + return true; + } + + Resident resident = playerResident.get(); + String plotType = townBlock.getType().name(); + boolean cancel = (resident.isMayor() && !Config.townyShopPlotsMayor.contains(plotType)) + || (resident.isKing() && !Config.townyShopPlotsKing.contains(plotType)) + || (!resident.isKing() && !resident.isMayor() && !Config.townyShopPlotsResidents.contains(plotType)); + + if (cancel) { + e.setCancelled(true); + plugin.debug("Cancel Reason: Towny (no permission)"); + return true; + } + } catch (NotRegisteredException ignored) { + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java new file mode 100644 index 0000000..ee86a8e --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java @@ -0,0 +1,61 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import us.talabrek.ultimateskyblock.api.IslandInfo; +import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; + +public class USkyBlockListener implements Listener { + private final ShopChest plugin; + private final uSkyBlockAPI uSkyBlockAPI; + + public USkyBlockListener(ShopChest plugin) { + this.plugin = plugin; + this.uSkyBlockAPI = plugin.getUSkyBlock(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableUSkyblockIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + IslandInfo islandInfo = uSkyBlockAPI.getIslandInfo(loc); + if (islandInfo == null) + return false; + + if (!player.getName().equals(islandInfo.getLeader()) && !islandInfo.getMembers().contains(player.getName())) { + e.setCancelled(true); + plugin.debug("Cancel Reason: uSkyBlock"); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java b/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java new file mode 100644 index 0000000..763f5d4 --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java @@ -0,0 +1,92 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Optional; +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.flag.IWrappedFlag; +import org.codemc.worldguardwrapper.flag.WrappedState; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class WorldGuardListener implements Listener { + + private final ShopChest plugin; + private final WorldGuardWrapper wgWrapper; + + public WorldGuardListener(ShopChest plugin) { + this.plugin = plugin; + this.wgWrapper = WorldGuardWrapper.getInstance(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableWorldGuardIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + IWrappedFlag flag = getStateFlag("create-shop"); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e, flag)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableWorldGuardIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e, getStateFlag("create-shop")); + } + + // TODO: Outsource shop use external permission + + // @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + // public void onBuySell(ShopBuySellEvent e) { + // if (!Config.enableWorldGuardIntegration) + // return; + + // Set chestLocations = Utils.getChestLocations(e.getShop()); + // String flagName = e.getShop().getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"; + // IWrappedFlag flag = getStateFlag(flagName); + // for (Location loc : chestLocations) { + // WrappedState state = wgWrapper.queryFlag(e.getPlayer(), loc, flag).orElse(WrappedState.DENY); + // if (state == WrappedState.DENY) { + // e.setCancelled(true); + // return; + // } + // } + // } + + private boolean handleForLocation(Player player, Location loc, Cancellable e, IWrappedFlag flag) { + WrappedState state = wgWrapper.queryFlag(player, loc, flag).orElse(WrappedState.DENY); + if (state == WrappedState.DENY) { + e.setCancelled(true); + plugin.debug("Cancel Reason: WorldGuard"); + return true; + } + return false; + } + + private IWrappedFlag getStateFlag(String flagName) { + Optional> flagOptional = wgWrapper.getFlag(flagName, WrappedState.class); + if (!flagOptional.isPresent()) { + plugin.getLogger().severe("Failed to get WorldGuard flag '" + flagName + "'."); + plugin.debug("WorldGuard flag '" + flagName + "' is not present!"); + return null; + } + return flagOptional.get(); + } + +} \ No newline at end of file diff --git a/src/main/java/de/epiceric/shopchest/language/Replacement.java b/src/main/java/de/epiceric/shopchest/language/Replacement.java index 3cf3c0d..9eb4591 100644 --- a/src/main/java/de/epiceric/shopchest/language/Replacement.java +++ b/src/main/java/de/epiceric/shopchest/language/Replacement.java @@ -7,9 +7,9 @@ public class Replacement { private Placeholder placeholder; private String replacement; - public Replacement(Placeholder placeholder, String replacement) { + public Replacement(Placeholder placeholder, Object replacement) { this.placeholder = placeholder; - this.replacement = replacement; + this.replacement = String.valueOf(replacement); } /** diff --git a/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java b/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java index 8210efb..9681573 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java @@ -1,19 +1,12 @@ package de.epiceric.shopchest.listeners; -import com.palmergames.bukkit.towny.object.Resident; -import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.TownBlock; -import com.palmergames.bukkit.towny.object.TownyUniverse; -import com.wasteofplastic.askyblock.ASkyBlockAPI; -import com.wasteofplastic.askyblock.Island; import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.config.Config; import de.epiceric.shopchest.config.Placeholder; -import de.epiceric.shopchest.external.PlotSquaredShopFlag; +import de.epiceric.shopchest.event.ShopExtendEvent; import de.epiceric.shopchest.language.LanguageUtils; import de.epiceric.shopchest.language.Message; import de.epiceric.shopchest.language.Replacement; -import de.epiceric.shopchest.nms.Hologram; import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop.ShopType; import de.epiceric.shopchest.utils.Callback; @@ -21,9 +14,9 @@ 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 me.ryanhamshire.GriefPrevention.Claim; import net.milkbowl.vault.economy.EconomyResponse; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -31,27 +24,18 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.DoubleChest; import org.bukkit.block.data.type.Chest.Type; -import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.InventoryHolder; -import org.codemc.worldguardwrapper.WorldGuardWrapper; -import org.codemc.worldguardwrapper.flag.IWrappedFlag; -import org.codemc.worldguardwrapper.flag.WrappedState; - -import pl.islandworld.api.IslandWorldApi; -import us.talabrek.ultimateskyblock.api.IslandInfo; import java.util.ArrayList; -import java.util.Optional; public class ChestProtectListener implements Listener { @@ -153,6 +137,9 @@ public class ChestProtectListener implements Listener { Chest c = (Chest) b.getState(); Block b2; + // Can't use Utils::getChestLocations since inventory holder + // has not been updated yet in this event (for 1.13+) + if (Utils.getMajorVersion() < 13) { InventoryHolder ih = c.getInventory().getHolder(); if (!(ih instanceof DoubleChest)) { @@ -197,117 +184,42 @@ public class ChestProtectListener implements Listener { b2 = b.getRelative(neighborFacing); } - if (shopUtils.isShop(b.getLocation()) || shopUtils.isShop(b2.getLocation())) { - final Shop shop = shopUtils.getShop(b2.getLocation()); + final Shop shop = shopUtils.getShop(b2.getLocation()); + if (shop == null) + return; - plugin.debug(String.format("%s tries to extend %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + plugin.debug(String.format("%s tries to extend %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); - boolean externalPluginsAllowed = true; - - if (plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { - WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); - Optional> flag = wgWrapper.getFlag("create-shop", WrappedState.class); - if (!flag.isPresent()) plugin.debug("WorldGuard flag 'create-shop' 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 (externalPluginsAllowed && plugin.hasTowny() && Config.enableTownyIntegration) { - TownBlock townBlock = TownyUniverse.getTownBlock(b.getLocation()); - if (townBlock != null) { - try { - Town town = townBlock.getTown(); - for (Resident resident : town.getResidents()) { - if (resident.getName().equals(p.getName())) { - if (resident.isMayor()) { - externalPluginsAllowed = (Config.townyShopPlotsMayor.contains(townBlock.getType().name())); - } else if (resident.isKing()) { - externalPluginsAllowed = (Config.townyShopPlotsKing.contains(townBlock.getType().name())); - } else { - externalPluginsAllowed = (Config.townyShopPlotsResidents.contains(townBlock.getType().name())); - } - break; - } - } - } catch (Exception ex) { - plugin.debug(ex); - } - } - } - - if (externalPluginsAllowed && plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { - com.github.intellectualsites.plotsquared.plot.object.Location loc = - new com.github.intellectualsites.plotsquared.plot.object.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ()); - - externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(loc.getOwnedPlot(), PlotSquaredShopFlag.CREATE_SHOP, p); - } - - if (externalPluginsAllowed && plugin.hasUSkyBlock() && Config.enableUSkyblockIntegration) { - IslandInfo islandInfo = plugin.getUSkyBlock().getIslandInfo(b.getLocation()); - if (islandInfo != null) { - externalPluginsAllowed = islandInfo.getMembers().contains(p.getName()) || islandInfo.getLeader().equals(p.getName()); - } - } - - if (externalPluginsAllowed && plugin.hasASkyBlock() && Config.enableASkyblockIntegration) { - Island island = ASkyBlockAPI.getInstance().getIslandAt(b.getLocation()); - if (island != null) { - if (island.getOwner() == null) { - externalPluginsAllowed = island.getMembers().contains(p.getUniqueId()); - } else { - externalPluginsAllowed = island.getMembers().contains(p.getUniqueId()) || island.getOwner().equals(p.getUniqueId()); - } - } - } - - if (externalPluginsAllowed && plugin.hasIslandWorld() && Config.enableIslandWorldIntegration && IslandWorldApi.isInitialized()) { - if (b.getWorld().getName().equals(IslandWorldApi.getIslandWorld().getName())) { - externalPluginsAllowed = IslandWorldApi.canBuildOnLocation(p, b.getLocation(), true); - } - } - - if (externalPluginsAllowed && plugin.hasGriefPrevention() && Config.enableGriefPreventionIntegration) { - Claim claim = plugin.getGriefPrevention().dataStore.getClaimAt(b.getLocation(), false, null); - if (claim != null) { - externalPluginsAllowed = claim.allowContainers(p) == null; - } - } - - if (externalPluginsAllowed || p.hasPermission(Permissions.EXTEND_PROTECTED)) { - if (shop.getVendor().getUniqueId().equals(p.getUniqueId()) || p.hasPermission(Permissions.EXTEND_OTHER)) { - if (ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { - final Shop newShop = new Shop(shop.getID(), plugin, shop.getVendor(), shop.getProduct(), shop.getLocation(), shop.getBuyPrice(), shop.getSellPrice(), shop.getShopType()); - - shopUtils.removeShop(shop, true, new Callback(plugin) { - @Override - public void onResult(Void result) { - newShop.create(true); - shopUtils.addShop(newShop, true); - plugin.debug(String.format("%s extended %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); - } - }); - } else { - e.setCancelled(true); - p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); - } - } else { - e.setCancelled(true); - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_OTHERS)); - } - } else { - e.setCancelled(true); - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_PROTECTED)); - } + ShopExtendEvent event = new ShopExtendEvent(p, shop, b.getLocation()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled() && !p.hasPermission(Permissions.EXTEND_PROTECTED)) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_PROTECTED)); + return; } - } - @EventHandler(ignoreCancelled = true) - public void onHologramDamage(EntityDamageEvent e) { - if (e.getEntity() instanceof ArmorStand) { - if (Hologram.isPartOfHologram((ArmorStand) e.getEntity())) { - e.setCancelled(true); - } + if (!p.getUniqueId().equals(shop.getVendor().getUniqueId()) && !p.hasPermission(Permissions.EXTEND_OTHER)) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_OTHERS)); + return; } + + if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); + return; + } + + final Shop newShop = new Shop(shop.getID(), plugin, shop.getVendor(), shop.getProduct(), shop.getLocation(), shop.getBuyPrice(), shop.getSellPrice(), shop.getShopType()); + + shopUtils.removeShop(shop, true, new Callback(plugin) { + @Override + public void onResult(Void result) { + newShop.create(true); + shopUtils.addShop(newShop, true); + plugin.debug(String.format("%s extended %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + } + }); } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java index ad153e6..83d6a0f 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java @@ -1,13 +1,7 @@ package de.epiceric.shopchest.listeners; -import com.google.gson.JsonPrimitive; import com.github.intellectualsites.plotsquared.plot.object.Plot; -import com.palmergames.bukkit.towny.object.Resident; -import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.TownBlock; -import com.palmergames.bukkit.towny.object.TownyUniverse; -import com.wasteofplastic.askyblock.ASkyBlockAPI; -import com.wasteofplastic.askyblock.Island; +import com.google.gson.JsonPrimitive; import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.config.Config; import de.epiceric.shopchest.config.Placeholder; @@ -33,7 +27,6 @@ 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 me.ryanhamshire.GriefPrevention.Claim; import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.EconomyResponse; @@ -54,12 +47,10 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerArmorStandManipulateEvent; import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.scheduler.BukkitRunnable; @@ -67,9 +58,6 @@ import org.codemc.worldguardwrapper.WorldGuardWrapper; import org.codemc.worldguardwrapper.flag.IWrappedFlag; import org.codemc.worldguardwrapper.flag.WrappedState; -import pl.islandworld.api.IslandWorldApi; -import us.talabrek.ultimateskyblock.api.IslandInfo; - import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -124,216 +112,47 @@ public class ShopInteractListener implements Listener { }.runTaskLater(plugin, 1L); } - @EventHandler(ignoreCancelled = true) - public void onPlayerManipulateArmorStand(PlayerArmorStandManipulateEvent e) { - // When clicking an armor stand with an armor item, the armor stand will take it. - // As a hologram consists of armor stands, they would also take the item. - ArmorStand armorStand = e.getRightClicked(); - if (Hologram.isPartOfHologram(armorStand)) { - e.setCancelled(true); - } - } - @EventHandler(priority = EventPriority.HIGH) public void onPlayerInteractCreate(PlayerInteractEvent e) { Player p = e.getPlayer(); Block b = e.getClickedBlock(); - if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p)) return; + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) + return; - if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { - if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) { - if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { - if (ClickType.getPlayerClickType(p) != null) { - if (ClickType.getPlayerClickType(p).getClickType() == ClickType.EnumClickType.CREATE) { - if (!shopUtils.isShop(b.getLocation())) { + if (ClickType.getPlayerClickType(p) == null) + return; - boolean externalPluginsAllowed = true; + if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) + return; - Location[] chestLocations = {b.getLocation(), null}; + if (ClickType.getPlayerClickType(p).getClickType() != ClickType.EnumClickType.CREATE) + return; - InventoryHolder ih = ((Chest) b.getState()).getInventory().getHolder(); - if (ih instanceof DoubleChest) { - DoubleChest dc = (DoubleChest) ih; - chestLocations[0] = ((Chest) dc.getLeftSide()).getLocation(); - chestLocations[1] = ((Chest) dc.getRightSide()).getLocation(); - } + if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p)) + return; - String denyReason = "Event Cancelled"; - - if (plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { - plugin.debug("Checking if WorldGuard allows shop creation..."); - WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); - Optional> flag = wgWrapper.getFlag("create-shop", WrappedState.class); - if (flag.isPresent()) { - for (Location loc : chestLocations) { - if (loc != null) { - WrappedState state = wgWrapper.queryFlag(p, loc, flag.get()).orElse(WrappedState.DENY); - externalPluginsAllowed = state == WrappedState.ALLOW; - } - } - } else { - plugin.debug("WorldGuard flag 'create-shop' is not present!"); - } - - if (!externalPluginsAllowed) denyReason = "WorldGuard"; - } - - if (externalPluginsAllowed && plugin.hasTowny() && Config.enableTownyIntegration) { - plugin.debug("Checking if Towny allows shop creation..."); - for (Location loc : chestLocations) { - if (loc != null) { - TownBlock townBlock = TownyUniverse.getTownBlock(loc); - if (townBlock != null) { - plugin.debug("Plot Type is " + townBlock.getType().name()); - try { - Town town = townBlock.getTown(); - boolean residentFound = false; - for (Resident resident : town.getResidents()) { - if (resident.getName().equals(p.getName())) { - residentFound = true; - if (resident.isMayor()) { - plugin.debug(p.getName() + " is mayor of town"); - externalPluginsAllowed &= (Config.townyShopPlotsMayor.contains(townBlock.getType().name())); - } else if (resident.isKing()) { - plugin.debug(p.getName() + " is king of town"); - externalPluginsAllowed &= (Config.townyShopPlotsKing.contains(townBlock.getType().name())); - } else { - plugin.debug(p.getName() + " is resident in town"); - externalPluginsAllowed &= (Config.townyShopPlotsResidents.contains(townBlock.getType().name())); - } - break; - } - } - if (!residentFound) { - plugin.debug(p.getName() + " is not resident in town"); - externalPluginsAllowed = false; - } - } catch (Exception ex) { - plugin.debug(ex); - } - } - } - } - - if (!externalPluginsAllowed) denyReason = "Towny"; - } - - if (externalPluginsAllowed && plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { - plugin.debug("Checking if PlotSquared allows shop creation..."); - for (Location loc : chestLocations) { - if (loc != null) { - com.github.intellectualsites.plotsquared.plot.object.Location plotLocation = new com.github.intellectualsites.plotsquared.plot.object.Location( - loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - - Plot plot = plotLocation.getOwnedPlot(); - externalPluginsAllowed &= PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.CREATE_SHOP, p); - } - } - - if (!externalPluginsAllowed) denyReason = "PlotSquared"; - } - - if (externalPluginsAllowed && plugin.hasUSkyBlock() && Config.enableUSkyblockIntegration) { - plugin.debug("Checking if uSkyBlock allows shop creation..."); - for (Location loc : chestLocations) { - if (loc != null) { - IslandInfo islandInfo = plugin.getUSkyBlock().getIslandInfo(loc); - if (islandInfo != null) { - plugin.debug("Chest is on island of " + islandInfo.getLeader()); - externalPluginsAllowed &= islandInfo.getMembers().contains(p.getName()) || islandInfo.getLeader().equals(p.getName()); - } - } - } - - if (!externalPluginsAllowed) denyReason = "uSkyBlock"; - } - - if (externalPluginsAllowed && plugin.hasASkyBlock() && Config.enableASkyblockIntegration) { - plugin.debug("Checking if ASkyBlock allows shop creation..."); - for (Location loc : chestLocations) { - if (loc != null) { - Island island = ASkyBlockAPI.getInstance().getIslandAt(loc); - if (island != null) { - if (island.getOwner() == null) { - plugin.debug("Chest is on an unowned island."); - externalPluginsAllowed &= island.getMembers().contains(p.getUniqueId()); - } else { - plugin.debug("Chest is on island of " + Bukkit.getOfflinePlayer(island.getOwner()).getName()); - externalPluginsAllowed &= island.getMembers().contains(p.getUniqueId()) || island.getOwner().equals(p.getUniqueId()); - } - } - } - } - - if (!externalPluginsAllowed) denyReason = "ASkyBlock"; - } - - if (externalPluginsAllowed && plugin.hasIslandWorld() && Config.enableIslandWorldIntegration && IslandWorldApi.isInitialized()) { - plugin.debug("Checking if IslandWorld allows shop creation..."); - for (Location loc : chestLocations) { - if (loc != null) { - if (loc.getWorld().getName().equals(IslandWorldApi.getIslandWorld().getName())) { - plugin.debug("Chest is in island world"); - externalPluginsAllowed &= IslandWorldApi.canBuildOnLocation(p, loc, true); - } - } - } - - if (!externalPluginsAllowed) denyReason = "IslandWorld"; - } - - if (externalPluginsAllowed && plugin.hasGriefPrevention() && Config.enableGriefPreventionIntegration) { - plugin.debug("Checking if GriefPrevention allows shop creation..."); - String gpDenyReason = null; - for (Location loc : chestLocations) { - if (loc != null) { - Claim claim = plugin.getGriefPrevention().dataStore.getClaimAt(loc, false, null); - if (claim != null) { - plugin.debug("Checking if claim allows container access"); - gpDenyReason = claim.allowContainers(p); - externalPluginsAllowed &= gpDenyReason == null; - } - } - } - - if (!externalPluginsAllowed) denyReason = "GriefPrevention (" + gpDenyReason + ")"; - } - - if ((e.isCancelled() || !externalPluginsAllowed) && !p.hasPermission(Permissions.CREATE_PROTECTED)) { - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED)); - ClickType.removePlayerClickType(p); - plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest because " + denyReason); - e.setCancelled(true); - return; - } - - e.setCancelled(true); - - if (ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { - ClickType clickType = ClickType.getPlayerClickType(p); - ShopProduct product = clickType.getProduct(); - double buyPrice = clickType.getBuyPrice(); - double sellPrice = clickType.getSellPrice(); - ShopType shopType = clickType.getShopType(); - - create(p, b.getLocation(), product, buyPrice, sellPrice, shopType); - } else { - p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); - plugin.debug("Chest is blocked"); - } - } else { - e.setCancelled(true); - p.sendMessage(LanguageUtils.getMessage(Message.CHEST_ALREADY_SHOP)); - plugin.debug("Chest is already a shop"); - } - - ClickType.removePlayerClickType(p); - } - } - } - } + if (shopUtils.isShop(b.getLocation())) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_ALREADY_SHOP)); + plugin.debug("Chest is already a shop"); + } else if (e.isCancelled() && !p.hasPermission(Permissions.CREATE_PROTECTED)) { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED)); + plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest"); + } else if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); + plugin.debug("Chest is blocked"); + } else { + ClickType clickType = ClickType.getPlayerClickType(p); + ShopProduct product = clickType.getProduct(); + double buyPrice = clickType.getBuyPrice(); + double sellPrice = clickType.getSellPrice(); + ShopType shopType = clickType.getShopType(); + + create(p, b.getLocation(), product, buyPrice, sellPrice, shopType); } + + e.setCancelled(true); + ClickType.removePlayerClickType(p); } private Map> needsConfirmation = new HashMap<>(); @@ -343,314 +162,292 @@ public class ShopInteractListener implements Listener { Player p = e.getPlayer(); boolean inverted = Config.invertMouseButtons; - if (Utils.getMajorVersion() >= 9) { - if (e.getHand() == EquipmentSlot.OFF_HAND) return; - } + if (Utils.getMajorVersion() >= 9 && e.getHand() == EquipmentSlot.OFF_HAND) + return; - if (e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.LEFT_CLICK_BLOCK) { - if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) { - if (ClickType.getPlayerClickType(p) != null) { - if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { - Shop shop = shopUtils.getShop(b.getLocation()); - if (shop != null || ClickType.getPlayerClickType(p).getClickType() == ClickType.EnumClickType.CREATE) { - switch (ClickType.getPlayerClickType(p).getClickType()) { - case CREATE: - break; - - case INFO: - e.setCancelled(true); + 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; + + if (ClickType.getPlayerClickType(p) != null) { + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) + return; - info(p, shop); + Shop shop = shopUtils.getShop(b.getLocation()); + if (shop == null && ClickType.getPlayerClickType(p).getClickType() != ClickType.EnumClickType.CREATE) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP)); + plugin.debug("Chest is not a shop"); + return; + } - ClickType.removePlayerClickType(p); - break; + switch (ClickType.getPlayerClickType(p).getClickType()) { + case CREATE: + return; + + case INFO: + info(p, shop); + break; - case REMOVE: - e.setCancelled(true); + case REMOVE: + remove(p, shop); + break; - if (shop.getShopType() == ShopType.ADMIN) { - if (p.hasPermission(Permissions.REMOVE_ADMIN)) { - remove(p, shop); - } else { - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_ADMIN)); - plugin.debug(p.getName() + " is not permitted to remove an admin shop"); - } - } else { - if (shop.getVendor().getUniqueId().equals(p.getUniqueId()) || p.hasPermission(Permissions.REMOVE_OTHER)) { - remove(p, shop); - } else { - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_OTHERS)); - plugin.debug(p.getName() + " is not permitted to remove another player's shop"); - } - } + case OPEN: + open(p, shop, true); + break; + } - ClickType.removePlayerClickType(p); - break; + e.setCancelled(true); + ClickType.removePlayerClickType(p); + } else { + Shop shop = shopUtils.getShop(b.getLocation()); - case OPEN: - e.setCancelled(true); + if (shop == null) + return; - if (p.getUniqueId().equals(shop.getVendor().getUniqueId()) || p.hasPermission(Permissions.OPEN_OTHER)) { - open(p, shop, true); - } else { - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_OPEN_OTHERS)); - plugin.debug(p.getName() + " is not permitted to open another player's shop"); - } + 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; + } - ClickType.removePlayerClickType(p); - break; - } - } else { - p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP)); - plugin.debug("Chest is not a shop"); + 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); + + if (item == null || !(infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability())) { + item = Utils.getItemInOffHand(p); + + if (item != null && infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability()) { + e.setCancelled(true); + info(p, shop); + return; } + } else { + e.setCancelled(true); + info(p, shop); + return; } - } else { - Shop shop = shopUtils.getShop(b.getLocation()); + } + } - if (shop != null) { - 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; - } + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && p.getUniqueId().equals(shop.getVendor().getUniqueId()) && shop.getShopType() != ShopType.ADMIN) { + return; + } - 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); + if (p.getGameMode() == GameMode.CREATIVE) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.USE_IN_CREATIVE)); + return; + } - if (item == null || !(infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability())) { - item = Utils.getItemInOffHand(p); + if ((e.getAction() == Action.RIGHT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.LEFT_CLICK_BLOCK && inverted)) { + e.setCancelled(true); - if (item != null && infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability()) { - e.setCancelled(true); - info(p, shop); - return; - } - } else { - e.setCancelled(true); - info(p, shop); - return; - } - } - } + if (shop.getShopType() == ShopType.ADMIN || !shop.getVendor().getUniqueId().equals(p.getUniqueId())) { + plugin.debug(p.getName() + " wants to buy"); - if (e.getAction() == Action.RIGHT_CLICK_BLOCK && p.getUniqueId().equals(shop.getVendor().getUniqueId()) && shop.getShopType() != ShopType.ADMIN) { - return; - } + if (shop.getBuyPrice() > 0) { + if (p.hasPermission(Permissions.BUY)) { + // TODO: Outsource shop use external permission + boolean externalPluginsAllowed = true; - if (p.getGameMode() == GameMode.CREATIVE) { - e.setCancelled(true); - p.sendMessage(LanguageUtils.getMessage(Message.USE_IN_CREATIVE)); - return; - } + if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { + 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()); - if ((e.getAction() == Action.RIGHT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.LEFT_CLICK_BLOCK && inverted)) { - e.setCancelled(true); + Plot plot = plotLocation.getOwnedPlot(); + GroupFlag flag = shop.getShopType() == Shop.ShopType.ADMIN ? PlotSquaredShopFlag.USE_ADMIN_SHOP : PlotSquaredShopFlag.USE_SHOP; - if (shop.getShopType() == ShopType.ADMIN || !shop.getVendor().getUniqueId().equals(p.getUniqueId())) { - plugin.debug(p.getName() + " wants to buy"); - - if (shop.getBuyPrice() > 0) { - if (p.hasPermission(Permissions.BUY)) { - boolean externalPluginsAllowed = true; - - if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { - 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()); - - Plot plot = plotLocation.getOwnedPlot(); - GroupFlag flag = shop.getShopType() == Shop.ShopType.ADMIN ? PlotSquaredShopFlag.USE_ADMIN_SHOP : PlotSquaredShopFlag.USE_SHOP; - - externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, flag, p); - } - - if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { - String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); - WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); - Optional> 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - ids.add(shop.getID()); - needsConfirmation.put(p.getUniqueId(), ids); - } - } else { - plugin.debug(p.getName() + " doesn't have external plugin's permission"); - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); - } - } 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - ids.add(shop.getID()); - needsConfirmation.put(p.getUniqueId(), ids); - } - } else { - if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), itemStack) > 0) { - if (confirmed || !Config.confirmShopping) { - buy(p, shop, p.isSneaking()); - if (Config.confirmShopping) { - Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - ids.add(shop.getID()); - needsConfirmation.put(p.getUniqueId(), ids); - } - } else { - 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())), - new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(itemStack)))); - } - plugin.debug("Shop is out of stock"); - } - } - } else { - plugin.debug(p.getName() + " doesn't have external plugin's permission"); - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); - } - } - } 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"); - } + externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, flag, p); } - } else if ((e.getAction() == Action.LEFT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.RIGHT_CLICK_BLOCK && inverted)) { - e.setCancelled(true); - - if ((shop.getShopType() == ShopType.ADMIN) || (!shop.getVendor().getUniqueId().equals(p.getUniqueId()))) { - plugin.debug(p.getName() + " wants to sell"); - - if (shop.getSellPrice() > 0) { - if (p.hasPermission(Permissions.SELL)) { - boolean externalPluginsAllowed = true; - - if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { - 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()); - - Plot plot = plotLocation.getOwnedPlot(); - GroupFlag flag = shop.getShopType() == Shop.ShopType.ADMIN ? PlotSquaredShopFlag.USE_ADMIN_SHOP : PlotSquaredShopFlag.USE_SHOP; - - externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, flag, p); - } - - if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { - String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); - WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); - Optional> 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; - } - - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); - ids.add(shop.getID()); - needsConfirmation.put(p.getUniqueId(), ids); - } - } else { - p.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS)); - plugin.debug(p.getName() + " doesn't have enough items"); - } - } - } else { - plugin.debug(p.getName() + " doesn't have external plugin's permission"); - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL_HERE)); + if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { + String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); + WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); + Optional> 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); } } else { - p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL)); - plugin.debug(p.getName() + " is not permitted to sell"); + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); } } else { - p.sendMessage(LanguageUtils.getMessage(Message.SELLING_DISABLED)); - plugin.debug("Selling is disabled"); + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); } } else { - e.setCancelled(false); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), itemStack) > 0) { + if (confirmed || !Config.confirmShopping) { + buy(p, shop, p.isSneaking()); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + 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())), + new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(itemStack)))); + } + plugin.debug("Shop is out of stock"); + } + } + } else { + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); + } } + } 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"); } } + + } else if ((e.getAction() == Action.LEFT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.RIGHT_CLICK_BLOCK && inverted)) { + e.setCancelled(true); + + if ((shop.getShopType() == ShopType.ADMIN) || (!shop.getVendor().getUniqueId().equals(p.getUniqueId()))) { + plugin.debug(p.getName() + " wants to sell"); + + if (shop.getSellPrice() > 0) { + if (p.hasPermission(Permissions.SELL)) { + // TODO: Outsource shop use external permission + boolean externalPluginsAllowed = true; + + if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { + 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()); + + Plot plot = plotLocation.getOwnedPlot(); + GroupFlag flag = shop.getShopType() == Shop.ShopType.ADMIN ? PlotSquaredShopFlag.USE_ADMIN_SHOP : PlotSquaredShopFlag.USE_SHOP; + + externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, flag, p); + } + + if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { + String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); + WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); + Optional> 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; + } + + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + 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 ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS)); + plugin.debug(p.getName() + " doesn't have enough items"); + } + } + } else { + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL_HERE)); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL)); + plugin.debug(p.getName() + " is not permitted to sell"); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.SELLING_DISABLED)); + plugin.debug("Selling is disabled"); + } + } else { + e.setCancelled(false); + } } } } @@ -752,17 +549,16 @@ public class ShopInteractListener implements Listener { ShopCreateEvent event = new ShopCreateEvent(executor, shop, creationPrice); Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { + if (event.isCancelled() && !executor.hasPermission(Permissions.CREATE_PROTECTED)) { plugin.debug("Create event cancelled"); + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED)); return; } 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))); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage))); return; } @@ -771,14 +567,8 @@ public class ShopInteractListener implements Listener { plugin.debug("Shop created"); shopUtils.addShop(shop, true); - Replacement placeholder = new Replacement( - Placeholder.CREATION_PRICE, String.valueOf(creationPrice)); - - if (shopType == ShopType.ADMIN) { - executor.sendMessage(LanguageUtils.getMessage(Message.ADMIN_SHOP_CREATED, placeholder)); - } else { - executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_CREATED, placeholder)); - } + Message message = shopType == ShopType.ADMIN ? Message.ADMIN_SHOP_CREATED : Message.SHOP_CREATED; + executor.sendMessage(LanguageUtils.getMessage(message, new Replacement(Placeholder.CREATION_PRICE, creationPrice))); } /** @@ -787,6 +577,17 @@ public class ShopInteractListener implements Listener { * @param shop Shop to be removed */ private void remove(Player executor, Shop shop) { + 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; + } + plugin.debug(executor.getName() + " is removing " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")"); ShopRemoveEvent event = new ShopRemoveEvent(executor, shop); Bukkit.getPluginManager().callEvent(event); @@ -817,6 +618,11 @@ public class ShopInteractListener implements Listener { * @param message Whether the player should receive the {@link Message#OPENED_SHOP} message */ private void open(Player executor, Shop shop, boolean message) { + if (!executor.getUniqueId().equals(shop.getVendor().getUniqueId()) && !executor.hasPermission(Permissions.OPEN_OTHER)) { + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_OPEN_OTHERS)); + return; + } + plugin.debug(executor.getName() + " is opening " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")"); ShopOpenEvent event = new ShopOpenEvent(executor, shop); Bukkit.getPluginManager().callEvent(event); diff --git a/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java b/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java index 07e746e..b81aef3 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java @@ -1,37 +1,28 @@ package de.epiceric.shopchest.listeners; -import de.epiceric.shopchest.ShopChest; -import de.epiceric.shopchest.config.Config; -import de.epiceric.shopchest.nms.Hologram; -import de.epiceric.shopchest.shop.Shop; -import de.epiceric.shopchest.utils.ClickType; -import de.epiceric.shopchest.utils.ClickType.EnumClickType; +import java.util.Optional; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Chest; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.Event.Result; -import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.inventory.InventoryOpenEvent; -import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.codemc.worldguardwrapper.WorldGuardWrapper; -import org.codemc.worldguardwrapper.event.AbstractWrappedEvent; -import org.codemc.worldguardwrapper.event.WrappedDamageEntityEvent; import org.codemc.worldguardwrapper.event.WrappedUseBlockEvent; -import org.codemc.worldguardwrapper.event.WrappedUseEntityEvent; import org.codemc.worldguardwrapper.flag.IWrappedFlag; import org.codemc.worldguardwrapper.flag.WrappedState; -import java.util.Optional; +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.ClickType.EnumClickType; public class WorldGuardListener implements Listener { @@ -61,7 +52,7 @@ public class WorldGuardListener implements Listener { if (shop != null) { // Don't show 'permission denied' messages for any kind of - // shop interaction even if entity/block interaction is not + // shop interaction even if block interaction is not // allowed in the region. return true; } @@ -69,44 +60,6 @@ public class WorldGuardListener implements Listener { return false; } - private void handleEntityInteraction(Player player, Entity entity, AbstractWrappedEvent event) { - if (entity.getType() == EntityType.ARMOR_STAND) { - if (!Hologram.isPartOfHologram((ArmorStand) entity)) - return; - - for (Shop shop : plugin.getShopUtils().getShops()) { - if (shop.getHologram() != null && shop.getHologram().contains((ArmorStand) entity)) { - if (isAllowed(player, shop.getLocation())) { - event.setResult(Result.ALLOW); - } - return; - } - } - } - } - - @EventHandler(priority = EventPriority.LOW) - public void onUseEntity(WrappedUseEntityEvent event) { - if (Config.enableWorldGuardIntegration) { - Player player = event.getPlayer(); - - if (event.getOriginalEvent() instanceof PlayerInteractAtEntityEvent) { - handleEntityInteraction(player, event.getEntity(), event); - } - } - } - - @EventHandler(priority = EventPriority.LOW) - public void onDamageEntity(WrappedDamageEntityEvent event) { - if (Config.enableWorldGuardIntegration) { - Player player = event.getPlayer(); - - if (event.getOriginalEvent() instanceof EntityDamageByEntityEvent) { - handleEntityInteraction(player, event.getEntity(), event); - } - } - } - @EventHandler(priority = EventPriority.LOW) public void onUseBlock(WrappedUseBlockEvent event) { if (Config.enableWorldGuardIntegration) { diff --git a/src/main/java/de/epiceric/shopchest/utils/Utils.java b/src/main/java/de/epiceric/shopchest/utils/Utils.java index b78a531..9ef2119 100644 --- a/src/main/java/de/epiceric/shopchest/utils/Utils.java +++ b/src/main/java/de/epiceric/shopchest/utils/Utils.java @@ -1,26 +1,5 @@ package de.epiceric.shopchest.utils; -import de.epiceric.shopchest.ShopChest; -import de.epiceric.shopchest.config.Placeholder; -import de.epiceric.shopchest.language.LanguageUtils; -import de.epiceric.shopchest.language.Message; -import de.epiceric.shopchest.language.Replacement; -import de.epiceric.shopchest.nms.CustomBookMeta; -import de.epiceric.shopchest.nms.JsonBuilder; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.inventory.meta.*; -import org.bukkit.util.Vector; - import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,12 +8,40 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.BookMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.Vector; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.nms.CustomBookMeta; +import de.epiceric.shopchest.nms.JsonBuilder; +import de.epiceric.shopchest.shop.Shop; + public class Utils { /** @@ -285,6 +292,24 @@ public class Utils { return true; } + /** + * Get a set for the location(s) of the shop's chest(s) + * @param shop The shop + * @return A set of 1 or 2 locations + */ + public static Set getChestLocations(Shop shop) { + Set chestLocations = new HashSet<>(); + InventoryHolder ih = shop.getInventoryHolder(); + if (ih instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) ih; + chestLocations.add(((Chest) dc.getLeftSide()).getLocation()); + chestLocations.add(((Chest) dc.getRightSide()).getLocation()); + } else { + chestLocations.add(shop.getLocation()); + } + return chestLocations; + } + /** * Send a clickable update notification to the given player. * @param plugin An instance of the {@link ShopChest} plugin