Allow shop item to be selected from creative menu

If the player does not hold an item, he is asked to select one.
This commit is contained in:
Eric 2019-05-28 15:53:26 +02:00
parent 655e1f8b07
commit ea894783fb
14 changed files with 450 additions and 82 deletions

View File

@ -18,6 +18,7 @@ import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.listeners.AreaShopListener; import de.epiceric.shopchest.listeners.AreaShopListener;
import de.epiceric.shopchest.listeners.BlockExplodeListener; import de.epiceric.shopchest.listeners.BlockExplodeListener;
import de.epiceric.shopchest.listeners.ChestProtectListener; import de.epiceric.shopchest.listeners.ChestProtectListener;
import de.epiceric.shopchest.listeners.CreativeModeListener;
import de.epiceric.shopchest.listeners.NotifyPlayerOnJoinListener; import de.epiceric.shopchest.listeners.NotifyPlayerOnJoinListener;
import de.epiceric.shopchest.listeners.ShopInteractListener; import de.epiceric.shopchest.listeners.ShopInteractListener;
import de.epiceric.shopchest.listeners.ShopItemListener; import de.epiceric.shopchest.listeners.ShopItemListener;
@ -29,6 +30,7 @@ import de.epiceric.shopchest.sql.Database;
import de.epiceric.shopchest.sql.MySQL; import de.epiceric.shopchest.sql.MySQL;
import de.epiceric.shopchest.sql.SQLite; import de.epiceric.shopchest.sql.SQLite;
import de.epiceric.shopchest.utils.Callback; import de.epiceric.shopchest.utils.Callback;
import de.epiceric.shopchest.utils.ClickType;
import de.epiceric.shopchest.utils.Permissions; import de.epiceric.shopchest.utils.Permissions;
import de.epiceric.shopchest.utils.ShopUpdater; import de.epiceric.shopchest.utils.ShopUpdater;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
@ -213,6 +215,8 @@ public class ShopChest extends JavaPlugin {
public void onDisable() { public void onDisable() {
debug("Disabling ShopChest..."); debug("Disabling ShopChest...");
ClickType.clear();
if (updater != null) { if (updater != null) {
debug("Stopping updater"); debug("Stopping updater");
updater.stop(); updater.stop();
@ -386,6 +390,7 @@ public class ShopChest extends JavaPlugin {
getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this); getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this);
getServer().getPluginManager().registerEvents(new NotifyPlayerOnJoinListener(this), this); getServer().getPluginManager().registerEvents(new NotifyPlayerOnJoinListener(this), this);
getServer().getPluginManager().registerEvents(new ChestProtectListener(this), this); getServer().getPluginManager().registerEvents(new ChestProtectListener(this), this);
getServer().getPluginManager().registerEvents(new CreativeModeListener(this), this);
if (!Utils.getServerVersion().equals("v1_8_R1")) { if (!Utils.getServerVersion().equals("v1_8_R1")) {
getServer().getPluginManager().registerEvents(new BlockExplodeListener(this), this); getServer().getPluginManager().registerEvents(new BlockExplodeListener(this), this);

View File

@ -7,6 +7,8 @@ import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.language.Message; import de.epiceric.shopchest.language.Message;
import de.epiceric.shopchest.language.Replacement; import de.epiceric.shopchest.language.Replacement;
import de.epiceric.shopchest.utils.Permissions; import de.epiceric.shopchest.utils.Permissions;
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.*; import org.bukkit.command.*;
@ -27,6 +29,7 @@ public class ShopCommand {
private ShopChest plugin; private ShopChest plugin;
private String name; private String name;
private PluginCommand pluginCommand; private PluginCommand pluginCommand;
private ShopCommandExecutor executor;
private List<ShopSubCommand> subCommands = new ArrayList<>(); private List<ShopSubCommand> subCommands = new ArrayList<>();
@ -40,8 +43,8 @@ public class ShopCommand {
this.plugin = plugin; this.plugin = plugin;
this.name = Config.mainCommandName; this.name = Config.mainCommandName;
this.pluginCommand = createPluginCommand(); this.pluginCommand = createPluginCommand();
this.executor = new ShopCommandExecutor(plugin);
ShopCommandExecutor executor = new ShopCommandExecutor(plugin);
ShopTabCompleter tabCompleter = new ShopTabCompleter(plugin); ShopTabCompleter tabCompleter = new ShopTabCompleter(plugin);
final Replacement cmdReplacement = new Replacement(Placeholder.COMMAND, name); final Replacement cmdReplacement = new Replacement(Placeholder.COMMAND, name);
@ -150,6 +153,14 @@ public class ShopCommand {
return pluginCommand; return pluginCommand;
} }
/**
* Call the second part of the create method after the player
* has selected an item from the creative inventory.
*/
public void createShopAfterSelected(Player player, SelectClickType clickType) {
executor.create2(player, clickType);
}
private PluginCommand createPluginCommand() { private PluginCommand createPluginCommand() {
plugin.debug("Creating plugin command"); plugin.debug("Creating plugin command");
try { try {

View File

@ -14,6 +14,7 @@ import de.epiceric.shopchest.language.Message;
import de.epiceric.shopchest.language.Replacement; import de.epiceric.shopchest.language.Replacement;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
import de.epiceric.shopchest.shop.ShopProduct; import de.epiceric.shopchest.shop.ShopProduct;
import de.epiceric.shopchest.shop.Shop.ShopType;
import de.epiceric.shopchest.utils.Callback; import de.epiceric.shopchest.utils.Callback;
import de.epiceric.shopchest.utils.ClickType; import de.epiceric.shopchest.utils.ClickType;
import de.epiceric.shopchest.utils.ItemUtils; import de.epiceric.shopchest.utils.ItemUtils;
@ -21,7 +22,11 @@ import de.epiceric.shopchest.utils.Permissions;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
import de.epiceric.shopchest.utils.UpdateChecker; import de.epiceric.shopchest.utils.UpdateChecker;
import de.epiceric.shopchest.utils.Utils; import de.epiceric.shopchest.utils.Utils;
import de.epiceric.shopchest.utils.ClickType.CreateClickType;
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -262,22 +267,47 @@ class ShopCommandExecutor implements CommandExecutor {
// Check if item in hand // Check if item in hand
if (inHand == null) { if (inHand == null) {
p.sendMessage(LanguageUtils.getMessage(Message.NO_ITEM_IN_HAND));
plugin.debug(p.getName() + " does not have an item in his hand"); plugin.debug(p.getName() + " does not have an item in his hand");
return;
if (!Config.creativeSelectItem) {
p.sendMessage(LanguageUtils.getMessage(Message.NO_ITEM_IN_HAND));
return;
}
ClickType.setPlayerClickType(p, new SelectClickType(p.getGameMode(), amount, buyPrice, sellPrice, shopType));
p.setGameMode(GameMode.CREATIVE);
p.sendMessage(LanguageUtils.getMessage(Message.SELECT_ITEM));
} else {
SelectClickType ct = new SelectClickType(null, amount, buyPrice, sellPrice, shopType);
ct.setItem(inHand);
create2(p, ct);
} }
}
/**
* <b>SHALL ONLY BE CALLED VIA {@link ShopCommand#createShopAfterSelected()}</b>
*/
protected void create2(Player p, SelectClickType selectClickType) {
ItemStack itemStack = selectClickType.getItem();
int amount = selectClickType.getAmount();
double buyPrice = selectClickType.getBuyPrice();
double sellPrice = selectClickType.getSellPrice();
boolean buyEnabled = buyPrice > 0;
boolean sellEnabled = sellPrice > 0;
ShopType shopType = selectClickType.getShopType();
// Check if item on blacklist // Check if item on blacklist
for (String item :Config.blacklist) { for (String item :Config.blacklist) {
ItemStack itemStack = ItemUtils.getItemStack(item); ItemStack is = ItemUtils.getItemStack(item);
if (itemStack == null) { if (is == null) {
plugin.getLogger().warning("Invalid item found in blacklist: " + item); plugin.getLogger().warning("Invalid item found in blacklist: " + item);
plugin.debug("Invalid item in blacklist: " + item); plugin.debug("Invalid item in blacklist: " + item);
continue; continue;
} }
if (itemStack.getType().equals(inHand.getType()) && itemStack.getDurability() == inHand.getDurability()) { if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) {
p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_ITEM)); p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_ITEM));
plugin.debug(p.getName() + "'s item is on the blacklist"); plugin.debug(p.getName() + "'s item is on the blacklist");
return; return;
@ -286,16 +316,16 @@ class ShopCommandExecutor implements CommandExecutor {
// Check if prices lower than minimum price // Check if prices lower than minimum price
for (String key :Config.minimumPrices) { for (String key :Config.minimumPrices) {
ItemStack itemStack = ItemUtils.getItemStack(key); ItemStack is = ItemUtils.getItemStack(key);
double minPrice = plugin.getConfig().getDouble("minimum-prices." + key); double minPrice = plugin.getConfig().getDouble("minimum-prices." + key);
if (itemStack == null) { if (is == null) {
plugin.getLogger().warning("Invalid item found in minimum-prices: " + key); plugin.getLogger().warning("Invalid item found in minimum-prices: " + key);
plugin.debug("Invalid item in minimum-prices: " + key); plugin.debug("Invalid item in minimum-prices: " + key);
continue; continue;
} }
if (itemStack.getType().equals(inHand.getType()) && itemStack.getDurability() == inHand.getDurability()) { if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) {
if (buyEnabled) { if (buyEnabled) {
if ((buyPrice < amount * minPrice) && (buyPrice > 0)) { if ((buyPrice < amount * minPrice) && (buyPrice > 0)) {
p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_LOW, new Replacement(Placeholder.MIN_PRICE, String.valueOf(amount * minPrice)))); p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_LOW, new Replacement(Placeholder.MIN_PRICE, String.valueOf(amount * minPrice))));
@ -316,16 +346,16 @@ class ShopCommandExecutor implements CommandExecutor {
// Check if prices higher than maximum price // Check if prices higher than maximum price
for (String key :Config.maximumPrices) { for (String key :Config.maximumPrices) {
ItemStack itemStack = ItemUtils.getItemStack(key); ItemStack is = ItemUtils.getItemStack(key);
double maxPrice = plugin.getConfig().getDouble("maximum-prices." + key); double maxPrice = plugin.getConfig().getDouble("maximum-prices." + key);
if (itemStack == null) { if (is == null) {
plugin.getLogger().warning("Invalid item found in maximum-prices: " + key); plugin.getLogger().warning("Invalid item found in maximum-prices: " + key);
plugin.debug("Invalid item in maximum-prices: " + key); plugin.debug("Invalid item in maximum-prices: " + key);
continue; continue;
} }
if (itemStack.getType().equals(inHand.getType()) && itemStack.getDurability() == inHand.getDurability()) { if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) {
if (buyEnabled) { if (buyEnabled) {
if ((buyPrice > amount * maxPrice) && (buyPrice > 0)) { if ((buyPrice > amount * maxPrice) && (buyPrice > 0)) {
p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_HIGH, new Replacement(Placeholder.MAX_PRICE, String.valueOf(amount * maxPrice)))); p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_HIGH, new Replacement(Placeholder.MAX_PRICE, String.valueOf(amount * maxPrice))));
@ -355,8 +385,8 @@ class ShopCommandExecutor implements CommandExecutor {
} }
} }
if (Enchantment.DURABILITY.canEnchantItem(inHand)) { if (Enchantment.DURABILITY.canEnchantItem(itemStack)) {
if (inHand.getDurability() > 0 && !Config.allowBrokenItems) { if (itemStack.getDurability() > 0 && !Config.allowBrokenItems) {
p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_BROKEN_ITEM)); p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_BROKEN_ITEM));
plugin.debug(p.getName() + "'s item is broken"); plugin.debug(p.getName() + "'s item is broken");
return; return;
@ -372,12 +402,12 @@ class ShopCommandExecutor implements CommandExecutor {
} }
} }
ShopProduct product = new ShopProduct(inHand, amount); ShopProduct product = new ShopProduct(itemStack, amount);
ShopPreCreateEvent event = new ShopPreCreateEvent(p, new Shop(plugin, p, product, null, buyPrice, sellPrice, shopType)); ShopPreCreateEvent event = new ShopPreCreateEvent(p, new Shop(plugin, p, product, null, buyPrice, sellPrice, shopType));
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) { if (!event.isCancelled()) {
ClickType.setPlayerClickType(p, new ClickType(ClickType.EnumClickType.CREATE, product, buyPrice, sellPrice, shopType)); ClickType.setPlayerClickType(p, new CreateClickType(product, buyPrice, sellPrice, shopType));
plugin.debug(p.getName() + " can now click a chest"); plugin.debug(p.getName() + " can now click a chest");
p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_CREATE)); p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_CREATE));
} else { } else {

View File

@ -270,6 +270,11 @@ public class Config {
**/ **/
public static boolean autoCalculateItemAmount; public static boolean autoCalculateItemAmount;
/**
* Whether players should be able to select an item from the creative inventory
*/
public static boolean creativeSelectItem;
/** /**
* <p>Whether the mouse buttons are inverted</p> * <p>Whether the mouse buttons are inverted</p>
* <b>Default:</b><br> * <b>Default:</b><br>
@ -486,6 +491,7 @@ public class Config {
allowDecimalsInPrice = plugin.getConfig().getBoolean("allow-decimals-in-price"); allowDecimalsInPrice = plugin.getConfig().getBoolean("allow-decimals-in-price");
allowBrokenItems = plugin.getConfig().getBoolean("allow-broken-items"); allowBrokenItems = plugin.getConfig().getBoolean("allow-broken-items");
autoCalculateItemAmount = (allowDecimalsInPrice && plugin.getConfig().getBoolean("auto-calculate-item-amount")); autoCalculateItemAmount = (allowDecimalsInPrice && plugin.getConfig().getBoolean("auto-calculate-item-amount"));
creativeSelectItem = plugin.getConfig().getBoolean("creative-select-item");
blacklist = (plugin.getConfig().getStringList("blacklist") == null) ? new ArrayList<String>() : plugin.getConfig().getStringList("blacklist"); blacklist = (plugin.getConfig().getStringList("blacklist") == null) ? new ArrayList<String>() : plugin.getConfig().getStringList("blacklist");
buyGreaterOrEqualSell = plugin.getConfig().getBoolean("buy-greater-or-equal-sell"); buyGreaterOrEqualSell = plugin.getConfig().getBoolean("buy-greater-or-equal-sell");
hopperProtection = plugin.getConfig().getBoolean("hopper-protection"); hopperProtection = plugin.getConfig().getBoolean("hopper-protection");

View File

@ -2226,6 +2226,9 @@ public class LanguageUtils {
messages.add(new LocalizedMessage(Message.OCCUPIED_SHOP_SLOTS, langConfig.getString("message.occupied-shop-slots", "&6You have &c%AMOUNT%/%LIMIT% &6shop slot/s occupied."))); messages.add(new LocalizedMessage(Message.OCCUPIED_SHOP_SLOTS, langConfig.getString("message.occupied-shop-slots", "&6You have &c%AMOUNT%/%LIMIT% &6shop slot/s occupied.")));
messages.add(new LocalizedMessage(Message.CANNOT_SELL_ITEM, langConfig.getString("message.cannot-sell-item", "&cYou cannot create a shop with this item."))); messages.add(new LocalizedMessage(Message.CANNOT_SELL_ITEM, langConfig.getString("message.cannot-sell-item", "&cYou cannot create a shop with this item.")));
messages.add(new LocalizedMessage(Message.USE_IN_CREATIVE, langConfig.getString("message.use-in-creative", "&cYou cannot use a shop in creative mode."))); messages.add(new LocalizedMessage(Message.USE_IN_CREATIVE, langConfig.getString("message.use-in-creative", "&cYou cannot use a shop in creative mode.")));
messages.add(new LocalizedMessage(Message.SELECT_ITEM, langConfig.getString("message.select-item", "&aOpen your inventory, and drop an item to select it.")));
messages.add(new LocalizedMessage(Message.ITEM_SELECTED, langConfig.getString("message.item-selected", "&aItem has been selected: &6%ITEMNAME%")));
messages.add(new LocalizedMessage(Message.CREATION_CANCELLED, langConfig.getString("message.creation-cancelled", "&cShop creation has been cancelled.")));
messages.add(new LocalizedMessage(Message.UPDATE_AVAILABLE, langConfig.getString("message.update.update-available", "&6&lVersion &c%VERSION% &6of &cShopChest &6is available &chere."))); messages.add(new LocalizedMessage(Message.UPDATE_AVAILABLE, langConfig.getString("message.update.update-available", "&6&lVersion &c%VERSION% &6of &cShopChest &6is available &chere.")));
messages.add(new LocalizedMessage(Message.UPDATE_CLICK_TO_DOWNLOAD, langConfig.getString("message.update.click-to-download", "Click to download"))); messages.add(new LocalizedMessage(Message.UPDATE_CLICK_TO_DOWNLOAD, langConfig.getString("message.update.click-to-download", "Click to download")));
messages.add(new LocalizedMessage(Message.UPDATE_NO_UPDATE, langConfig.getString("message.update.no-update", "&6&lNo new update available."))); messages.add(new LocalizedMessage(Message.UPDATE_NO_UPDATE, langConfig.getString("message.update.no-update", "&6&lNo new update available.")));

View File

@ -56,6 +56,9 @@ public enum Message {
OCCUPIED_SHOP_SLOTS, OCCUPIED_SHOP_SLOTS,
CANNOT_SELL_ITEM, CANNOT_SELL_ITEM,
USE_IN_CREATIVE, USE_IN_CREATIVE,
SELECT_ITEM,
ITEM_SELECTED,
CREATION_CANCELLED,
UPDATE_AVAILABLE, UPDATE_AVAILABLE,
UPDATE_CLICK_TO_DOWNLOAD, UPDATE_CLICK_TO_DOWNLOAD,
UPDATE_NO_UPDATE, UPDATE_NO_UPDATE,

View File

@ -0,0 +1,185 @@
package de.epiceric.shopchest.listeners;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
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.BlockMultiPlaceEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
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.utils.ClickType;
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
public class CreativeModeListener implements Listener {
private ShopChest plugin;
public CreativeModeListener(ShopChest plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryClick(InventoryClickEvent e) {
HumanEntity entity = e.getWhoClicked();
if (!(entity instanceof Player))
return;
Player p = (Player) entity;
ClickType clickType = ClickType.getPlayerClickType(p);
if (clickType instanceof SelectClickType) {
e.setCancelled(true);
if (e.getCursor() == null || e.getCursor().getType() == Material.AIR)
return;
ClickType.removePlayerClickType(p);
((SelectClickType) clickType).setItem(e.getCursor());
p.closeInventory();
p.setGameMode(((SelectClickType) clickType).getGameMode());
p.sendMessage(LanguageUtils.getMessage(Message.ITEM_SELECTED,
new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(e.getCursor()))));
plugin.getShopCommand().createShopAfterSelected(p, (SelectClickType) clickType);
}
}
@EventHandler
public void onPlayerCloseInventory(InventoryCloseEvent e) {
HumanEntity entity = e.getPlayer();
if (!(entity instanceof Player))
return;
Player p = (Player) entity;
ClickType clickType = ClickType.getPlayerClickType(p);
if (!(clickType instanceof SelectClickType))
return;
ClickType.removePlayerClickType(p);
p.setGameMode(((SelectClickType) clickType).getGameMode());
p.sendMessage(LanguageUtils.getMessage(Message.CREATION_CANCELLED));
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
// Reset game mode on quit if SelectClickType is set
Player p = e.getPlayer();
ClickType ct = ClickType.getPlayerClickType(p);
if (ct instanceof SelectClickType) {
p.setGameMode(((SelectClickType) ct).getGameMode());
}
ClickType.removePlayerClickType(p);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryDrag(InventoryDragEvent e) {
// Cancel any inventory drags if SelectClickType is set
HumanEntity entity = e.getWhoClicked();
if (!(entity instanceof Player))
return;
ClickType clickType = ClickType.getPlayerClickType((Player) entity);
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryMove(InventoryMoveItemEvent e) {
// Cancel any inventory movement if SelectClickType is set
if (e.getSource().getHolder() instanceof Player) {
Player p = (Player) e.getSource().getHolder();
ClickType clickType = ClickType.getPlayerClickType(p);
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerPickup(PlayerPickupItemEvent e) {
// Cancel any item pickups if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent e) {
// Cancel any block breaks if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockPlace(BlockPlaceEvent e) {
// Cancel any block places if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockMultiPlace(BlockMultiPlaceEvent e) {
// Cancel any block places if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerInteract(PlayerInteractEvent e) {
// Cancel any interactions if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent e) {
// Cancel any entity interactions if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerDamageEntity(EntityDamageByEntityEvent e) {
// Cancel any entity damaging if SelectClickType is set
Entity entity = e.getDamager();
if (!(entity instanceof Player))
return;
ClickType clickType = ClickType.getPlayerClickType((Player) entity);
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerMove(PlayerMoveEvent e) {
// Cancel any player movement if SelectClickType is set
ClickType clickType = ClickType.getPlayerClickType(e.getPlayer());
if (clickType instanceof SelectClickType)
e.setCancelled(true);
}
}

View File

@ -26,6 +26,7 @@ import de.epiceric.shopchest.utils.ItemUtils;
import de.epiceric.shopchest.utils.Permissions; import de.epiceric.shopchest.utils.Permissions;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
import de.epiceric.shopchest.utils.Utils; import de.epiceric.shopchest.utils.Utils;
import de.epiceric.shopchest.utils.ClickType.CreateClickType;
import fr.xephi.authme.api.v3.AuthMeApi; import fr.xephi.authme.api.v3.AuthMeApi;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse; import net.milkbowl.vault.economy.EconomyResponse;
@ -68,7 +69,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class ShopInteractListener implements Listener { public class ShopInteractListener implements Listener {
private static final Pattern COLOR_CODE_PATTERN = Pattern.compile(".*([§]([a-fA-F0-9]))"); 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]))"); private static final Pattern FORMAT_CODE_PATTERN = Pattern.compile(".*([§]([l-oL-OkK]))");
@ -120,7 +120,7 @@ public class ShopInteractListener implements Listener {
if (e.getAction() != Action.RIGHT_CLICK_BLOCK) if (e.getAction() != Action.RIGHT_CLICK_BLOCK)
return; return;
if (ClickType.getPlayerClickType(p) == null) if (!(ClickType.getPlayerClickType(p) instanceof CreateClickType))
return; return;
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST)
@ -132,17 +132,17 @@ public class ShopInteractListener implements Listener {
if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p)) if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p))
return; return;
if (shopUtils.isShop(b.getLocation())) { if (e.isCancelled() && !p.hasPermission(Permissions.CREATE_PROTECTED)) {
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)); p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED));
plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest"); plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest");
} else if (shopUtils.isShop(b.getLocation())) {
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_ALREADY_SHOP));
plugin.debug("Chest is already a shop");
} else if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { } else if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) {
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED));
plugin.debug("Chest is blocked"); plugin.debug("Chest is blocked");
} else { } else {
ClickType clickType = ClickType.getPlayerClickType(p); CreateClickType clickType = (CreateClickType) ClickType.getPlayerClickType(p);
ShopProduct product = clickType.getProduct(); ShopProduct product = clickType.getProduct();
double buyPrice = clickType.getBuyPrice(); double buyPrice = clickType.getBuyPrice();
double sellPrice = clickType.getSellPrice(); double sellPrice = clickType.getSellPrice();
@ -171,32 +171,35 @@ public class ShopInteractListener implements Listener {
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST)
return; return;
if (ClickType.getPlayerClickType(p) != null) { ClickType clickType = ClickType.getPlayerClickType(p);
if (clickType != null) {
if (e.getAction() != Action.RIGHT_CLICK_BLOCK) if (e.getAction() != Action.RIGHT_CLICK_BLOCK)
return; return;
Shop shop = shopUtils.getShop(b.getLocation()); Shop shop = shopUtils.getShop(b.getLocation());
if (shop == null && ClickType.getPlayerClickType(p).getClickType() != ClickType.EnumClickType.CREATE) { switch (clickType.getClickType()) {
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP)); case CREATE:
plugin.debug("Chest is not a shop"); case SELECT_ITEM:
return; break;
default:
if (shop == null) {
p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP));
plugin.debug("Chest is not a shop");
return;
}
} }
switch (ClickType.getPlayerClickType(p).getClickType()) { switch (clickType.getClickType()) {
case CREATE:
return;
case INFO: case INFO:
info(p, shop); info(p, shop);
break; break;
case REMOVE: case REMOVE:
remove(p, shop); remove(p, shop);
break; break;
case OPEN: case OPEN:
open(p, shop, true); open(p, shop, true);
break; break;
default: return;
} }
e.setCancelled(true); e.setCancelled(true);

View File

@ -3,7 +3,12 @@ package de.epiceric.shopchest.utils;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.shop.ShopProduct; import de.epiceric.shopchest.shop.ShopProduct;
import de.epiceric.shopchest.shop.Shop.ShopType; import de.epiceric.shopchest.shop.Shop.ShopType;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
@ -13,26 +18,27 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class ClickType { public class ClickType {
private static Map<UUID, ClickType> playerClickType = new HashMap<>(); private static Map<UUID, ClickType> playerClickType = new HashMap<>();
private static Map<UUID, BukkitTask> playerTimers = new HashMap<>(); private static Map<UUID, BukkitTask> playerTimers = new HashMap<>();
private EnumClickType enumClickType; private EnumClickType enumClickType;
private ShopProduct product;
private double buyPrice;
private double sellPrice;
private ShopType shopType;
public ClickType(EnumClickType enumClickType) { public ClickType(EnumClickType enumClickType) {
this.enumClickType = enumClickType; this.enumClickType = enumClickType;
} }
public ClickType(EnumClickType enumClickType, ShopProduct product, double buyPrice, double sellPrice, ShopType shopType) { /**
this.enumClickType = enumClickType; * Clear click types, cancel timers, and reset game modes
this.product = product; */
this.sellPrice = sellPrice; public static void clear() {
this.buyPrice = buyPrice; playerClickType.forEach((uuid, ct) -> {
this.shopType = shopType; if (ct instanceof SelectClickType) {
Player p = Bukkit.getPlayer(uuid);
if (p != null)
p.setGameMode(((SelectClickType) ct).getGameMode());
}
});
playerTimers.forEach((uuid, timer) -> timer.cancel());
} }
/** /**
@ -47,12 +53,13 @@ public class ClickType {
/** /**
* Removes the click type from a player and cancels the 15 second timer * Removes the click type from a player and cancels the 15 second timer
*
* @param player Player to remove the click type from * @param player Player to remove the click type from
*/ */
public static void removePlayerClickType(OfflinePlayer player) { public static void removePlayerClickType(OfflinePlayer player) {
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
playerClickType.remove(uuid); playerClickType.remove(uuid);
// If a timer is still running, cancel it // If a timer is still running, cancel it
Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel()); Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel());
playerTimers.remove(uuid); playerTimers.remove(uuid);
@ -71,13 +78,15 @@ public class ClickType {
// If a timer is already running, cancel it // If a timer is already running, cancel it
Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel()); Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel());
// Remove ClickType after 15 seconds if player has not clicked a chest if (clickType.getClickType() != EnumClickType.SELECT_ITEM) {
playerTimers.put(uuid, new BukkitRunnable() { // Remove ClickType after 15 seconds if player has not clicked a chest
@Override playerTimers.put(uuid, new BukkitRunnable() {
public void run() { @Override
playerClickType.remove(uuid); public void run() {
} playerClickType.remove(uuid);
}.runTaskLater(ShopChest.getInstance(), 300)); }
}.runTaskLater(ShopChest.getInstance(), 300));
}
} }
/** /**
@ -87,36 +96,119 @@ public class ClickType {
return enumClickType; return enumClickType;
} }
/**
* @return If {@link #getClickType()} returns {@link EnumClickType#CREATE}, this returns the item, the player has hold in his hands, else <b>null</b>.
*/
public ShopProduct getProduct() {
return product;
}
/**
* @return If {@link #getClickType()} returns {@link EnumClickType#CREATE}, this returns the buy price, the player has entered, else <b>null</b>.
*/
public double getBuyPrice() {
return buyPrice;
}
/**
* @return If {@link #getClickType()} returns {@link EnumClickType#CREATE}, this returns the sell price, the player has entered, else <b>null</b>.
*/
public double getSellPrice() {
return sellPrice;
}
/**
* @return If {@link #getClickType()} returns {@link EnumClickType#CREATE}, this returns the shop type, the player has entered, else <b>null</b>.
*/
public ShopType getShopType() {
return shopType;
}
public enum EnumClickType { public enum EnumClickType {
CREATE, REMOVE, INFO, OPEN CREATE, REMOVE, INFO, OPEN, SELECT_ITEM
}
public static class CreateClickType extends ClickType {
private ShopProduct product;
private double buyPrice;
private double sellPrice;
private ShopType shopType;
public CreateClickType(ShopProduct product, double buyPrice, double sellPrice, ShopType shopType) {
super(EnumClickType.CREATE);
this.product = product;
this.sellPrice = sellPrice;
this.buyPrice = buyPrice;
this.shopType = shopType;
}
/**
* Returns the item, the player has hold in his hands
*/
public ShopProduct getProduct() {
return product;
}
/**
* Returns the buy price, the player has entered
*/
public double getBuyPrice() {
return buyPrice;
}
/**
* Returns the sell price, the player has entered
*/
public double getSellPrice() {
return sellPrice;
}
/**
* Returns the shop type, the player has entered
*/
public ShopType getShopType() {
return shopType;
}
}
public static class SelectClickType extends ClickType {
private ItemStack itemStack;
private GameMode gameMode;
private int amount;
private double buyPrice;
private double sellPrice;
private ShopType shopType;
public SelectClickType(GameMode gameMode, int amount, double buyPrice, double sellPrice, ShopType shopType) {
super(EnumClickType.SELECT_ITEM);
this.gameMode = gameMode;
this.amount = amount;
this.sellPrice = sellPrice;
this.buyPrice = buyPrice;
this.shopType = shopType;
}
/**
* Returns the selected item (or {@code null} if no item has been selected)
*/
public ItemStack getItem() {
return itemStack;
}
/**
* Sets the selected item
* @param itemStack The item to set as selected
*/
public void setItem(ItemStack itemStack) {
this.itemStack = itemStack;
}
/**
* Returns the gamemode, the player was in before entering creative mode
*/
public GameMode getGameMode() {
return gameMode;
}
/**
* Returns the amount, the player has entered
*/
public int getAmount() {
return amount;
}
/**
* Returns the buy price, the player has entered
*/
public double getBuyPrice() {
return buyPrice;
}
/**
* Returns the sell price, the player has entered
*/
public double getSellPrice() {
return sellPrice;
}
/**
* Returns the shop type, the player has entered
*/
public ShopType getShopType() {
return shopType;
}
} }
} }

View File

@ -24,6 +24,10 @@ shop-info-item: "STICK"
# in order to prevent accidental purchases or sells. # in order to prevent accidental purchases or sells.
confirm-shopping: false confirm-shopping: false
# Set whether players should be able to select the shop item from the
# creative inventory if they don't hold an item in their hand.
creative-select-item: true
# Set whether the shop creation price should be refunded # Set whether the shop creation price should be refunded
# when the shop is removed. # when the shop is removed.
# This only applies when the creator of the shop removes it himself # This only applies when the creator of the shop removes it himself

View File

@ -53,6 +53,9 @@ message.shop-limit-reached=&cDu hast dein Limit von &6%LIMIT% &cShop/s erreicht.
message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt. message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt.
message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen. message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen.
message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen. message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen.
message.select-item=&aÖffne dein Inventar und lass ein Item fallen, um es auszuwählen.
message.item-selected=&aItem wurde ausgewählt: &6%ITEMNAME%
message.creation-cancelled=&cShoperstellung wurde abgebrochen.
message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar. message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar.
message.update.click-to-download=Klicke hier zum Herunterladen message.update.click-to-download=Klicke hier zum Herunterladen
message.update.no-update=&6&lKeine neue Aktualisierung verfügbar. message.update.no-update=&6&lKeine neue Aktualisierung verfügbar.

View File

@ -53,6 +53,9 @@ message.shop-limit-reached=&cDu hast dein Limit von &6%LIMIT% &cShop/s erreicht.
message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt. message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt.
message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen. message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen.
message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen. message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen.
message.select-item=&aÖffne dein Inventar und lass ein Item fallen, um es auszuwählen.
message.item-selected=&aItem wurde ausgewählt: &6%ITEMNAME%
message.creation-cancelled=&cShoperstellung wurde abgebrochen.
message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar. message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar.
message.update.click-to-download=Klicke hier zum Herunterladen message.update.click-to-download=Klicke hier zum Herunterladen
message.update.no-update=&6&lKeine neue Aktualisierung verfügbar. message.update.no-update=&6&lKeine neue Aktualisierung verfügbar.

View File

@ -198,6 +198,16 @@ message.cannot-sell-item=&cYou cannot create a shop with this item.
# Set the message when the player tries to use a shop in creative mode. # Set the message when the player tries to use a shop in creative mode.
message.use-in-creative=&cYou cannot use a shop in creative mode. message.use-in-creative=&cYou cannot use a shop in creative mode.
# Set the message when the player has to select an item from the creative menu.
message.select-item=&aOpen your inventory, and drop an item to select it.
# Set the message when the player has selected an item from the creative menu.
# Usable Placeholders: %ITEMNAME%
message.item-selected=&aItem has been selected: &6%ITEMNAME%
# Set the message when the player closes the creative menu to select an item.
message.creation-cancelled=&cShop creation has been cancelled.
# Set the message when an update is available. # Set the message when an update is available.
# Usable Placeholders: %VERSION% # Usable Placeholders: %VERSION%
message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere. message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere.

View File

@ -191,6 +191,16 @@ message.cannot-sell-item=&cYou cannot create a shop with this item.
# Set the message when the player tries to use a shop in creative mode. # Set the message when the player tries to use a shop in creative mode.
message.use-in-creative=&cYou cannot use a shop in creative mode. message.use-in-creative=&cYou cannot use a shop in creative mode.
# Set the message when the player has to select an item from the creative menu.
message.select-item=&aOpen your inventory, and drop an item to select it.
# Set the message when the player has selected an item from the creative menu.
# Usable Placeholders: %ITEMNAME%
message.item-selected=&aItem has been selected: &6%ITEMNAME%
# Set the message when the player closes the creative menu to select an item.
message.creation-cancelled=&cShop creation has been cancelled.
# Set the message when an update is available. # Set the message when an update is available.
# Usable Placeholders: %VERSION% # Usable Placeholders: %VERSION%
message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere. message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere.