diff --git a/src/com/minedhype/ishop/CommandShop.java b/src/com/minedhype/ishop/CommandShop.java index 06f976a..fec4a9b 100644 --- a/src/com/minedhype/ishop/CommandShop.java +++ b/src/com/minedhype/ishop/CommandShop.java @@ -1,12 +1,22 @@ package com.minedhype.ishop; import java.net.URL; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Scanner; import java.util.UUID; +import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI; +import com.bgsoftware.superiorskyblock.api.island.Island; +import com.bgsoftware.superiorskyblock.api.island.IslandPrivilege; +import com.bgsoftware.superiorskyblock.api.wrappers.SuperiorPlayer; import com.minedhype.ishop.inventories.InvCreateRow; import com.minedhype.ishop.inventories.InvShop; +import com.palmergames.bukkit.towny.utils.ShopPlotUtil; +import me.angeschossen.lands.api.flags.type.Flags; +import me.angeschossen.lands.api.land.LandWorld; +import me.ryanhamshire.GriefPrevention.ClaimPermission; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; import net.milkbowl.vault.economy.Economy; @@ -19,31 +29,68 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.inventory.ItemStack; import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.World; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import com.minedhype.ishop.inventories.InvAdminShop; import com.minedhype.ishop.inventories.InvShopList; import com.minedhype.ishop.inventories.InvStock; +import me.ryanhamshire.GriefPrevention.Claim; +import me.ryanhamshire.GriefPrevention.GriefPrevention; public class CommandShop implements CommandExecutor { + + private final Map findCooldown = new HashMap<>(); + static boolean findCommandPublic = iShop.config.getBoolean("publicFindCommand"); + static boolean moveCommandPublic = iShop.config.getBoolean("publicMoveCommand"); + static int findCooldownTime = iShop.config.getInt("findCommandCooldown"); + @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if(EventShop.shuttingDown) + return true; if(sender instanceof ConsoleCommandSender && args.length > 0) { if(args[0].equalsIgnoreCase("reload")) { reloadShop(null); return true; - } - else { - sender.sendMessage(Messages.NOT_A_PLAYER.toString()); + } else if(args[0].equalsIgnoreCase("deleteid") && args[1] != null) { + deleteShopID(null, args[1]); + return true; + } else if(args[0].equalsIgnoreCase("createlocation") && args.length > 5) { + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> createLocation(null, args[1], args[2], args[3], args[4], args[5])); + return true; + } else if(args[0].equalsIgnoreCase("deletelocation") && args.length > 4) { + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> deleteLocation(null, args[1], args[2], args[3], args[4])); + return true; + } else if(args[0].equalsIgnoreCase("convertdatabase")) { + Shop.convertData(); + return true; + } else { + sender.sendMessage(ChatColor.GOLD + "iShop Console Commands:"); + sender.sendMessage(ChatColor.GRAY + label + " createlocation "); + sender.sendMessage(ChatColor.GRAY + label + " convertdatabase"); + sender.sendMessage(ChatColor.GRAY + label + " deletelocation "); + sender.sendMessage(ChatColor.GRAY + label + " deleteid "); + sender.sendMessage(ChatColor.GRAY + label + " reload"); return false; } } if(!(sender instanceof Player)) { - sender.sendMessage(Messages.NOT_A_PLAYER.toString()); + if(sender instanceof ConsoleCommandSender) { + sender.sendMessage(ChatColor.GOLD + "iShop Console Commands:"); + sender.sendMessage(ChatColor.GRAY + label + " createlocation "); + sender.sendMessage(ChatColor.GRAY + label + " convertdatabase"); + sender.sendMessage(ChatColor.GRAY + label + " deletelocation "); + sender.sendMessage(ChatColor.GRAY + label + " deleteid "); + sender.sendMessage(ChatColor.GRAY + label + " reload"); + } + else + sender.sendMessage(Messages.NOT_A_PLAYER.toString()); return false; } Player player = (Player) sender; @@ -51,16 +98,26 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> listSubCmd(player, label)); else if(args[0].equalsIgnoreCase("adminshop")) adminShop(player); + else if(args[0].equalsIgnoreCase("copy") && args.length >= 2) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> copyShop(player, args[1])); else if(args[0].equalsIgnoreCase("count") && args.length >= 2) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> count(player, args[1])); else if(args[0].equalsIgnoreCase("create")) createStore(player); else if(args[0].equalsIgnoreCase("createshop") && args.length >= 2) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> createShop(player, args[1])); + else if(args[0].equalsIgnoreCase("createlocation") && args.length > 5) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> createLocation(player, args[1], args[2], args[3], args[4], args[5])); else if(args[0].equalsIgnoreCase("delete")) deleteShop(player); else if(args[0].equalsIgnoreCase("deleteid") && args.length >= 2) deleteShopID(player, args[1]); + else if(args[0].equalsIgnoreCase("deletelocation") && args.length > 4) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> deleteLocation(player, args[1], args[2], args[3], args[4])); + else if(args[0].equalsIgnoreCase("find") && args.length >= 2) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> find(player, args[1])); + else if(args[0].equalsIgnoreCase("findbook") && args.length >= 2) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> findBook(player, args[1])); else if(args[0].equalsIgnoreCase("list") && args.length == 1) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> listShops(player, null)); else if(args[0].equalsIgnoreCase("list") && args.length >= 2) @@ -73,12 +130,16 @@ else if(args[0].equalsIgnoreCase("managestock") && args.length == 2) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> manageStock(player, args[1], "1")); else if(args[0].equalsIgnoreCase("managestock") && args.length >= 3) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> manageStock(player, args[1], args[2])); + else if(args[0].equalsIgnoreCase("move") && args.length >= 2) + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> moveShop(player, args[1])); else if(args[0].equalsIgnoreCase("out") && args.length == 1) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> outOfStock(player, null)); else if(args[0].equalsIgnoreCase("out") && args.length >= 2) Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> outOfStock(player, args[1])); else if(args[0].equalsIgnoreCase("reload")) reloadShop(player); + else if(args[0].equalsIgnoreCase("removeallshops") && args.length >= 2) + removeAllShops(player, args[1]); else if(args[0].equalsIgnoreCase("shops")) listAllShops(player); else if(args[0].equalsIgnoreCase("sold") && args.length == 1) @@ -99,29 +160,40 @@ else if(args[0].equalsIgnoreCase("view") && args.length >= 2) private void listSubCmd(Player player, String label) { player.sendMessage(ChatColor.GOLD + "iShop Commands:"); + player.sendMessage(ChatColor.GRAY + "/" + label + " copy "); player.sendMessage(ChatColor.GRAY + "/" + label + " count "); player.sendMessage(ChatColor.GRAY + "/" + label + " create"); player.sendMessage(ChatColor.GRAY + "/" + label + " delete"); player.sendMessage(ChatColor.GRAY + "/" + label + " deleteid "); + if(findCommandPublic || player.hasPermission(Permission.SHOP_ADMIN.toString()) || player.hasPermission(Permission.SHOP_FIND.toString())) { + player.sendMessage(ChatColor.GRAY + "/" + label + " find "); + player.sendMessage(ChatColor.GRAY + "/" + label + " findbook "); + } player.sendMessage(ChatColor.GRAY + "/" + label + " list"); - if(iShop.config.getBoolean("publicListCommand") || player.hasPermission(Permission.SHOP_ADMIN.toString())) + if(iShop.config.getBoolean("publicListCommand") || player.hasPermission(Permission.SHOP_ADMIN.toString()) || player.hasPermission(Permission.SHOP_LIST.toString())) player.sendMessage(ChatColor.GRAY + "/" + label + " list "); - if(iShop.config.getBoolean("publicShopListCommand") || player.hasPermission(Permission.SHOP_ADMIN.toString())) - player.sendMessage(ChatColor.GRAY + "/" + label + " shops"); player.sendMessage(ChatColor.GRAY + "/" + label + " manage "); + if(moveCommandPublic || player.hasPermission(Permission.SHOP_ADMIN.toString()) || player.hasPermission(Permission.SHOP_MOVE.toString())) + player.sendMessage(ChatColor.GRAY + "/" + label + " move "); player.sendMessage(ChatColor.GRAY + "/" + label + " out"); if(player.hasPermission(Permission.SHOP_ADMIN.toString())) player.sendMessage(ChatColor.GRAY + "/" + label + " out "); - if(iShop.config.getBoolean("enableShopSoldMessage")); + if(iShop.config.getBoolean("publicShopListCommand") || player.hasPermission(Permission.SHOP_ADMIN.toString()) || player.hasPermission(Permission.SHOP_SHOPS.toString())) + player.sendMessage(ChatColor.GRAY + "/" + label + " shops"); + if(iShop.config.getBoolean("enableShopSoldMessage")) player.sendMessage(ChatColor.GRAY + "/" + label + " sold "); - player.sendMessage(ChatColor.GRAY + "/" + label + " stock "); + if(iShop.config.getBoolean("enableStockCommand") || player.hasPermission(Permission.SHOP_STOCK.toString()) || player.hasPermission(Permission.SHOP_ADMIN.toString())) + player.sendMessage(ChatColor.GRAY + "/" + label + " stock "); player.sendMessage(ChatColor.GRAY + "/" + label + " view "); if(player.hasPermission(Permission.SHOP_ADMIN.toString())) { player.sendMessage(ChatColor.GRAY + "/" + label + " adminshop"); player.sendMessage(ChatColor.GRAY + "/" + label + " createshop "); + player.sendMessage(ChatColor.GRAY + "/" + label + " createlocation "); + player.sendMessage(ChatColor.GRAY + "/" + label + " deletelocation "); player.sendMessage(ChatColor.GRAY + "/" + label + " listadmin"); player.sendMessage(ChatColor.GRAY + "/" + label + " managestock "); player.sendMessage(ChatColor.GRAY + "/" + label + " reload"); + player.sendMessage(ChatColor.GRAY + "/" + label + " removeallshops "); } } @@ -141,7 +213,11 @@ private void count(Player player, String itemName) { } } ItemStack item = new ItemStack(material); - int max = iShop.config.getInt("stockPages"); + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; int itemAmountCount = 0; for(int i=0; i stockStore = StockShop.getStockShopByOwner(player.getUniqueId(),i); @@ -218,6 +294,48 @@ private void createStore(Player player) { player.sendMessage(Messages.WG_REGION.toString()); return; } + boolean allowShopCreateInClaim = false; + if(iShop.gpLoader != null) { + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, false, null); + if(claim == null || claim.checkPermission(player, ClaimPermission.Access, null) == null || claim.checkPermission(player, ClaimPermission.Build, null) == null || claim.checkPermission(player, ClaimPermission.Edit, null) == null || claim.checkPermission(player, ClaimPermission.Manage, null) == null || claim.checkPermission(player, ClaimPermission.Inventory, null) == null) + allowShopCreateInClaim = true; + } + else + allowShopCreateInClaim = true; + if(!allowShopCreateInClaim) { + player.sendMessage(Messages.GP_CLAIM.toString()); + return; + } + boolean allowShopCreateWithinLands = false; + if(iShop.lands != null) { + LandWorld world = iShop.lands.getWorld(player.getWorld()); + if(world != null) + if(world.hasRoleFlag(player.getUniqueId(), block.getLocation(), Flags.BLOCK_PLACE)) + allowShopCreateWithinLands = true; + } + else + allowShopCreateWithinLands = true; + if(!allowShopCreateWithinLands) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + if(iShop.superiorSkyblock2Check) { + Island island = SuperiorSkyblockAPI.getIslandAt(block.getLocation()); + if(island != null) { + IslandPrivilege islandPrivilege = IslandPrivilege.getByName("Build"); + SuperiorPlayer superiorPlayer = SuperiorSkyblockAPI.getPlayer(player.getUniqueId()); + if(!island.hasPermission(superiorPlayer, islandPrivilege)) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + } + if(iShop.townyCheck) { + if(!ShopPlotUtil.doesPlayerHaveAbilityToEditShopPlot(player, block.getLocation())) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } Optional shop = Shop.getShopByLocation(block.getLocation()); if(shop.isPresent()) { player.sendMessage(Messages.EXISTING_SHOP.toString()); @@ -261,14 +379,12 @@ private void createStore(Player player) { return; } } - Shop newShop = Shop.createShop(block.getLocation(), player.getUniqueId()); + Shop.createShop(block.getLocation(), player.getUniqueId()); player.sendMessage(Messages.SHOP_CREATED.toString()); Bukkit.getServer().getScheduler().runTaskLaterAsynchronously(iShop.getPlugin(), () -> { Optional shops = Shop.getShopByLocation(block.getLocation()); Shop.shopList.put(shops.get().shopId(), player.getUniqueId()); }, 10); - InvAdminShop inv = new InvAdminShop(newShop, player); - inv.open(player, newShop.getOwner()); } private void createShop(Player player, String playerShop) { @@ -356,6 +472,59 @@ private void createShop(Player player, String playerShop) { player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); return; } + if(!player.isOp() && !iShop.config.getBoolean("skipPermsCheckForAdminCreateShop")) { + boolean isShopLoc; + if(iShop.wgLoader != null) + isShopLoc = iShop.wgLoader.checkRegion(block); + else + isShopLoc = true; + if(!isShopLoc) { + player.sendMessage(Messages.WG_REGION.toString()); + return; + } + boolean allowShopCreateInClaim = false; + if(iShop.gpLoader != null) { + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, false, null); + if(claim == null || claim.checkPermission(player, ClaimPermission.Access, null) == null || claim.checkPermission(player, ClaimPermission.Build, null) == null || claim.checkPermission(player, ClaimPermission.Edit, null) == null || claim.checkPermission(player, ClaimPermission.Manage, null) == null || claim.checkPermission(player, ClaimPermission.Inventory, null) == null) + allowShopCreateInClaim = true; + } + else + allowShopCreateInClaim = true; + if(!allowShopCreateInClaim) { + player.sendMessage(Messages.GP_CLAIM.toString()); + return; + } + boolean allowShopCreateWithinLands = false; + if(iShop.lands != null) { + LandWorld world = iShop.lands.getWorld(player.getWorld()); + if(world != null) + if(world.hasRoleFlag(player.getUniqueId(), block.getLocation(), Flags.BLOCK_PLACE)) + allowShopCreateWithinLands = true; + } + else + allowShopCreateWithinLands = true; + if(!allowShopCreateWithinLands) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + if(iShop.superiorSkyblock2Check) { + Island island = SuperiorSkyblockAPI.getIslandAt(block.getLocation()); + if(island != null) { + IslandPrivilege islandPrivilege = IslandPrivilege.getByName("Build"); + SuperiorPlayer superiorPlayer = SuperiorSkyblockAPI.getPlayer(player.getUniqueId()); + if(!island.hasPermission(superiorPlayer, islandPrivilege)) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + } + if(iShop.townyCheck) { + if(!ShopPlotUtil.doesPlayerHaveAbilityToEditShopPlot(player, block.getLocation())) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + } Optional shop = Shop.getShopByLocation(block.getLocation()); if(!shop.isPresent()) { Shop.createShop(block.getLocation(), shopOwner); @@ -368,6 +537,321 @@ private void createShop(Player player, String playerShop) { } else { player.sendMessage(Messages.EXISTING_SHOP.toString()); } } + private void copyShop(Player player, String shopId) { + if(iShop.config.getBoolean("usePermissions") && !player.hasPermission(Permission.SHOP_CREATE.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(!iShop.config.getBoolean("enableShopBlock")) { + player.sendMessage(Messages.DISABLED_SHOP_BLOCK.toString()); + return; + } + Block block = player.getTargetBlockExact(5); + if(block == null) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + if(iShop.config.getBoolean("disableShopInWorld")) { + List disabledWorldsList = iShop.config.getStringList("disabledWorldList"); + for(String disabledWorlds:disabledWorldsList) { + if(disabledWorlds != null && block.getWorld().getName().equals(disabledWorlds)) { + player.sendMessage(Messages.SHOP_WORLD_DISABLED.toString()); + return; + } + } + } + String shopBlock = iShop.config.getString("shopBlock"); + Material match = Material.matchMaterial(shopBlock); + if(match == null) { + try { + match = Material.matchMaterial(shopBlock.split("minecraft:")[1].toUpperCase()); + } catch(Exception ignored) { } + if(match == null) + match = Material.BARREL; + } + if(!EventShop.multipleShopBlocks) { + if(!block.getType().equals(match)) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } else { + boolean shopMatch = false; + for(String shopBlocks:EventShop.multipleShopBlock) { + Material shopListBlocks = Material.matchMaterial(shopBlocks); + if(shopListBlocks != null && block.getType().equals(shopListBlocks)) { + shopMatch = true; + break; + } + } + if(!block.getType().equals(match) && !shopMatch) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } + boolean isShopLoc; + if(iShop.wgLoader != null) + isShopLoc = iShop.wgLoader.checkRegion(block); + else + isShopLoc = true; + if(!isShopLoc) { + player.sendMessage(Messages.WG_REGION.toString()); + return; + } + boolean allowShopCreateInClaim = false; + if(iShop.gpLoader != null) { + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, false, null); + if(claim == null || claim.checkPermission(player, ClaimPermission.Access, null) == null || claim.checkPermission(player, ClaimPermission.Build, null) == null || claim.checkPermission(player, ClaimPermission.Edit, null) == null || claim.checkPermission(player, ClaimPermission.Manage, null) == null || claim.checkPermission(player, ClaimPermission.Inventory, null) == null) + allowShopCreateInClaim = true; + } + else + allowShopCreateInClaim = true; + if(!allowShopCreateInClaim) { + player.sendMessage(Messages.GP_CLAIM.toString()); + return; + } + boolean allowShopCreateWithinLands = false; + if(iShop.lands != null) { + LandWorld world = iShop.lands.getWorld(player.getWorld()); + if(world != null) + if(world.hasRoleFlag(player.getUniqueId(), block.getLocation(), Flags.BLOCK_PLACE)) + allowShopCreateWithinLands = true; + } + else + allowShopCreateWithinLands = true; + if(!allowShopCreateWithinLands) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + if(iShop.superiorSkyblock2Check) { + Island island = SuperiorSkyblockAPI.getIslandAt(block.getLocation()); + if(island != null) { + IslandPrivilege islandPrivilege = IslandPrivilege.getByName("Build"); + SuperiorPlayer superiorPlayer = SuperiorSkyblockAPI.getPlayer(player.getUniqueId()); + if(!island.hasPermission(superiorPlayer, islandPrivilege)) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + } + if(iShop.townyCheck) { + if(!ShopPlotUtil.doesPlayerHaveAbilityToEditShopPlot(player, block.getLocation())) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + Optional shop = Shop.getShopByLocation(block.getLocation()); + if(shop.isPresent()) { + player.sendMessage(Messages.EXISTING_SHOP.toString()); + return; + } + boolean limitShops; + int numShops = Shop.getNumShops(player.getUniqueId()); + if(iShop.config.getBoolean("usePermissions")) { + int maxShops = 0; + String permPrefix = Permission.SHOP_LIMIT_PREFIX.toString(); + for(PermissionAttachmentInfo attInfo : player.getEffectivePermissions()) { + String perm = attInfo.getPermission(); + if(perm.startsWith(permPrefix)) { + int num; + try { + num = Integer.parseInt(perm.substring(perm.lastIndexOf(".")+1)); + } catch(Exception e) { num = 0; } + if(num > maxShops) + maxShops = num; + } + } + limitShops = numShops >= maxShops; + } + else { + int numConfig = iShop.config.getInt("defaultShopLimit"); + limitShops = numShops >= numConfig && numConfig >= 0; + } + if(player.hasPermission(Permission.SHOP_LIMIT_BYPASS.toString())) + limitShops = false; + if(limitShops) { + player.sendMessage(Messages.SHOP_MAX.toString()); + return; + } + double cost = iShop.config.getDouble("createCost"); + Optional economy = iShop.getEconomy(); + if(cost > 0 && economy.isPresent()) { + OfflinePlayer offPlayer = Bukkit.getOfflinePlayer(player.getUniqueId()); + EconomyResponse res = economy.get().withdrawPlayer(offPlayer, cost); + if(!res.transactionSuccess()) { + player.sendMessage(Messages.SHOP_CREATE_NO_MONEY.toString()+cost); + return; + } + } + int shopNumber = Integer.parseInt(shopId); + Optional copyShop = Shop.getShopById(shopNumber); + if(!copyShop.isPresent()) { + player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + return; + } + Optional shopCopy = Shop.getShopByLocation(block.getLocation()); + if(!shopCopy.isPresent()) { + Shop.duplicateShop(block.getLocation(),player.getUniqueId(), shopNumber); + player.sendMessage(Messages.SHOP_CREATED.toString()); + Bukkit.getServer().getScheduler().runTaskLaterAsynchronously(iShop.getPlugin(), () -> { + Optional shops = Shop.getShopByLocation(block.getLocation()); + Shop.shopList.put(shops.get().shopId(), player.getUniqueId()); + }, 10); + } else { player.sendMessage(Messages.EXISTING_SHOP.toString()); } + } + + private void createLocation(Player player, String playerShop, String x, String y, String z, String worldString) { + if(player != null && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(!iShop.config.getBoolean("enableShopBlock")) { + if(player != null) + player.sendMessage(Messages.DISABLED_SHOP_BLOCK.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.DISABLED_SHOP_BLOCK.toString()); + return; + } + String world; + if(worldString != null) + world = worldString; + else + world = "world"; + + int xLoc,yLoc,zLoc; + try { + xLoc = Integer.parseInt(x); + yLoc = Integer.parseInt(y); + zLoc = Integer.parseInt(z); + } + catch(Exception e) { + if(player != null) + player.sendMessage(Messages.SHOP_LOCATION_ERROR_NUM.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_LOCATION_ERROR_NUM.toString()); + return; + } + World worldLoc = Bukkit.getWorld(world); + Location blockLoc; + if(worldLoc != null) + blockLoc = new Location(worldLoc, xLoc, yLoc, zLoc); + else { + if(player != null) + player.sendMessage(Messages.SHOP_LOCATION_ERROR_WORLD.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_LOCATION_ERROR_WORLD.toString()); + return; + } + Block block = Bukkit.getWorld(world).getBlockAt(blockLoc); + if(iShop.config.getBoolean("disableShopInWorld")) { + List disabledWorldsList = iShop.config.getStringList("disabledWorldList"); + for(String disabledWorlds:disabledWorldsList) { + if(disabledWorlds != null && block.getWorld().getName().equals(disabledWorlds)) { + if(player != null) + player.sendMessage(Messages.SHOP_WORLD_DISABLED.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_WORLD_DISABLED.toString()); + return; + } + } + } + String shopBlock = iShop.config.getString("shopBlock"); + Material match = Material.matchMaterial(shopBlock); + if(match == null) { + try { + match = Material.matchMaterial(shopBlock.split("minecraft:")[1].toUpperCase()); + } catch(Exception ignored) { } + if(match == null) + match = Material.BARREL; + } + if(!EventShop.multipleShopBlocks) { + if(!block.getType().equals(match)) { + if(player != null) + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } else { + boolean shopMatch = false; + for(String shopBlocks:EventShop.multipleShopBlock) { + Material shopListBlocks = Material.matchMaterial(shopBlocks); + if(shopListBlocks != null && block.getType().equals(shopListBlocks)) { + shopMatch = true; + break; + } + } + if(!block.getType().equals(match) && !shopMatch) { + if(player != null) + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } + UUID shopOwner; + if(playerShop == null) { + if(player != null) + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.NO_PLAYER_FOUND.toString()); + return; + } else { + Player playerInGame = Bukkit.getPlayer(playerShop); + if(playerInGame != null && playerInGame.isOnline()) + shopOwner = playerInGame.getUniqueId(); + else { + try { + shopOwner = getUUID(playerShop); + } catch (Exception e) { + UUID foundPlayerUUID = null; + boolean foundPlayer = false; + for(OfflinePlayer offlinePlayers : Bukkit.getOfflinePlayers()) + if(offlinePlayers.getName().equalsIgnoreCase(playerShop)) { + foundPlayerUUID = offlinePlayers.getUniqueId(); + foundPlayer = true; + break; + } + if(!foundPlayer) { + if(player != null) { + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + } + else + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + return; + } + shopOwner = foundPlayerUUID; + } + } + } + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(shopOwner); + if(offlinePlayer == null || !offlinePlayer.hasPlayedBefore()) { + if(player != null) + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.NO_PLAYER_FOUND.toString()); + return; + } + Optional shop = Shop.getShopByLocation(block.getLocation()); + if(!shop.isPresent()) { + Shop.createShop(block.getLocation(), shopOwner); + if(player != null) + player.sendMessage(Messages.SHOP_CREATED_LOC.toString().replaceAll("%p", playerShop).replaceAll("%w", world).replaceAll("%x", x).replaceAll("%y", y).replaceAll("%z", z)); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_CREATED_LOC.toString().replaceAll("%p", playerShop).replaceAll("%w", world).replaceAll("%x", x).replaceAll("%y", y).replaceAll("%z", z)); + final UUID shopOwnerFinal = shopOwner; + Bukkit.getServer().getScheduler().runTaskLaterAsynchronously(iShop.getPlugin(), () -> { + Optional shops = Shop.getShopByLocation(block.getLocation()); + Shop.shopList.put(shops.get().shopId(), shopOwnerFinal); + }, 10); + } else { + if(player != null) + player.sendMessage(Messages.EXISTING_SHOP.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.EXISTING_SHOP.toString().replaceAll("%p", playerShop)); + } + } + private void adminShop(Player player) { if(!player.hasPermission(Permission.SHOP_ADMIN.toString())) { player.sendMessage(Messages.NO_PERMISSION.toString()); @@ -471,24 +955,33 @@ private void deleteShopID(Player player, String shopId) { sID = Integer.parseInt(shopId); } catch (Exception e) { sID = -1; } if(sID < 0) { - player.sendMessage(Messages.SHOP_ID_INTEGER.toString()); + if(player != null) + player.sendMessage(Messages.SHOP_ID_INTEGER.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_ID_INTEGER.toString()); return; } Optional shop = Shop.getShopById(sID); if(!shop.isPresent()) { - player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + if(player != null) + player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_NOT_FOUND.toString()); return; } - if(!shop.get().isOwner(player.getUniqueId()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(player != null && !shop.get().isOwner(player.getUniqueId()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { player.sendMessage(Messages.SHOP_NO_SELF.toString()); return; } - if(shop.get().isAdmin() && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(shop.get().isAdmin() && player != null && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { player.sendMessage(Messages.NO_PERMISSION.toString()); return; } if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { - player.sendMessage(Messages.SHOP_BUSY.toString()); + if(player != null) + player.sendMessage(Messages.SHOP_BUSY.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_BUSY.toString()); return; } double cost = iShop.config.getDouble("returnAmount"); @@ -499,11 +992,313 @@ private void deleteShopID(Player player, String shopId) { } Shop.shopList.remove(shop.get().shopId()); shop.get().deleteShop(); - player.sendMessage(Messages.SHOP_IDDELETED.toString().replaceAll("%id", shopId)); + if(player != null) + player.sendMessage(Messages.SHOP_IDDELETED.toString().replaceAll("%id", shopId)); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_IDDELETED.toString().replaceAll("%id", shopId)); + } + + private void deleteLocation(Player player, String x, String y, String z, String worldString) { + if(player != null && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + String world; + if(worldString != null) + world = worldString; + else + world = "world"; + + int xLoc,yLoc,zLoc; + try { + xLoc = Integer.parseInt(x); + yLoc = Integer.parseInt(y); + zLoc = Integer.parseInt(z); + } + catch(Exception e) { + if(player != null) + player.sendMessage(Messages.SHOP_LOCATION_ERROR_NUM.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_LOCATION_ERROR_NUM.toString()); + return; + } + World worldLoc = Bukkit.getWorld(world); + Location blockLoc; + if(worldLoc != null) + blockLoc = new Location(worldLoc, xLoc, yLoc, zLoc); + else { + if(player != null) + player.sendMessage(Messages.SHOP_LOCATION_ERROR_WORLD.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_LOCATION_ERROR_WORLD.toString()); + return; + } + + Optional shop = Shop.getShopByLocation(blockLoc); + if(!shop.isPresent()) { + if(player != null) + player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_NOT_FOUND.toString()); + return; + } + if(player != null && !shop.get().isOwner(player.getUniqueId()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.SHOP_NO_SELF.toString()); + return; + } + if(player != null && shop.get().isAdmin() && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { + if(player != null) + player.sendMessage(Messages.SHOP_BUSY.toString()); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_BUSY.toString()); + return; + } + OfflinePlayer offPlayer = Bukkit.getOfflinePlayer(shop.get().getOwner()); + String shopOwner = offPlayer.getName(); + double cost = iShop.config.getDouble("returnAmount"); + Optional economy = iShop.getEconomy(); + if(cost > 0 && economy.isPresent()) + economy.get().depositPlayer(offPlayer, cost); + Shop.shopList.remove(shop.get().shopId()); + shop.get().deleteShop(); + if(player != null) + player.sendMessage(Messages.SHOP_DELETED_LOC.toString().replaceAll("%p", shopOwner).replaceAll("%w", world).replaceAll("%x", x).replaceAll("%y", y).replaceAll("%z", z)); + else + Bukkit.getConsoleSender().sendMessage(Messages.SHOP_DELETED_LOC.toString().replaceAll("%p", shopOwner).replaceAll("%w", world).replaceAll("%x", x).replaceAll("%y", y).replaceAll("%z", z)); + } + + private void find(Player player, String itemName) { + if(!findCommandPublic && !player.hasPermission(Permission.SHOP_FIND.toString()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(findCooldownTime > 0 && !player.hasPermission(Permission.SHOP_ADMIN.toString()) && !player.hasPermission(Permission.SHOP_BYPASS_FIND_CD.toString())) { + if(findCooldown.containsKey(player.getUniqueId())) { + long secondsLeft = (((findCooldown.get(player.getUniqueId()))/1000)+findCooldownTime) - (System.currentTimeMillis()/1000); + if(secondsLeft > 0) { + player.sendMessage(Messages.SHOP_FIND_COOLDOWN.toString().replaceAll("%time", String.valueOf(secondsLeft))); + return; + } + } + findCooldown.put(player.getUniqueId(), System.currentTimeMillis()); + } + Material material = Material.matchMaterial(itemName); + if(material == null) { + try { + material = Material.matchMaterial(itemName.split("minecraft:")[1].toUpperCase()); + } catch(Exception ignored) { } + if(material == null) { + player.sendMessage(Messages.SHOP_FIND_ERROR.toString()); + return; + } + } + if(material.isAir()) { + player.sendMessage(Messages.SHOP_FIND_ERROR.toString()); + return; + } + ItemStack item = new ItemStack(material); + Shop.findItem(player, item, itemName); + } + + private void findBook(Player player, String bookName) { + if(!findCommandPublic && !player.hasPermission(Permission.SHOP_FIND.toString()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(findCooldownTime > 0 && !player.hasPermission(Permission.SHOP_ADMIN.toString()) && !player.hasPermission(Permission.SHOP_BYPASS_FIND_CD.toString())) { + if(findCooldown.containsKey(player.getUniqueId())) { + long secondsLeft = (((findCooldown.get(player.getUniqueId()))/1000)+findCooldownTime) - (System.currentTimeMillis()/1000); + if(secondsLeft > 0) { + player.sendMessage(Messages.SHOP_FIND_COOLDOWN.toString().replaceAll("%time", String.valueOf(secondsLeft))); + return; + } + } + findCooldown.put(player.getUniqueId(), System.currentTimeMillis()); + } + if(!TabComplete.enchantments.contains(bookName)) { + player.sendMessage(Messages.SHOP_FIND_ERROR.toString()); + return; + } + Shop.findBook(player, bookName); + } + + private void moveShop(Player player, String shopId) { + if(!moveCommandPublic && !player.hasPermission(Permission.SHOP_MOVE.toString()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + int sId; + try { + sId = Integer.parseInt(shopId); + } catch (Exception e) { sId = -1; } + if(sId < 1) { + if(player != null) + player.sendMessage(Messages.SHOP_ID_INTEGER.toString()); + return; + } + Block block = player.getTargetBlockExact(5); + if(block == null) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + if(iShop.config.getBoolean("disableShopInWorld")) { + List disabledWorldsList = iShop.config.getStringList("disabledWorldList"); + for(String disabledWorlds:disabledWorldsList) + if(disabledWorlds != null && block.getWorld().getName().equals(disabledWorlds)) { + player.sendMessage(Messages.SHOP_WORLD_DISABLED.toString()); + return; + } + } + String shopBlock = iShop.config.getString("shopBlock"); + Material match = Material.matchMaterial(shopBlock); + if(match == null) { + try { + match = Material.matchMaterial(shopBlock.split("minecraft:")[1].toUpperCase()); + } catch(Exception ignored) { } + if(match == null) + match = Material.BARREL; + } + if(!EventShop.multipleShopBlocks) { + if(!block.getType().equals(match)) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } else { + boolean shopMatch = false; + for(String shopBlocks:EventShop.multipleShopBlock) { + Material shopListBlocks = Material.matchMaterial(shopBlocks); + if(shopListBlocks != null && block.getType().equals(shopListBlocks)) { + shopMatch = true; + break; + } + } + if(!block.getType().equals(match) && !shopMatch) { + player.sendMessage(Messages.TARGET_MISMATCH.toString()); + return; + } + } + if(!player.isOp()) { + boolean isShopLoc; + if(iShop.wgLoader != null) + isShopLoc = iShop.wgLoader.checkRegion(block); + else + isShopLoc = true; + if(!isShopLoc) { + player.sendMessage(Messages.WG_REGION.toString()); + return; + } + boolean allowShopCreateInClaim = false; + if(iShop.gpLoader != null) { + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, false, null); + if(claim == null || claim.checkPermission(player, ClaimPermission.Access, null) == null || claim.checkPermission(player, ClaimPermission.Build, null) == null || claim.checkPermission(player, ClaimPermission.Edit, null) == null || claim.checkPermission(player, ClaimPermission.Manage, null) == null || claim.checkPermission(player, ClaimPermission.Inventory, null) == null) + allowShopCreateInClaim = true; + } else + allowShopCreateInClaim = true; + if(!allowShopCreateInClaim) { + player.sendMessage(Messages.GP_CLAIM.toString()); + return; + } + boolean allowShopCreateWithinLands = false; + if(iShop.lands != null) { + LandWorld world = iShop.lands.getWorld(player.getWorld()); + if(world != null) + if(world.hasRoleFlag(player.getUniqueId(), block.getLocation(), Flags.BLOCK_PLACE)) + allowShopCreateWithinLands = true; + } + else + allowShopCreateWithinLands = true; + if(!allowShopCreateWithinLands) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + if(iShop.superiorSkyblock2Check) { + Island island = SuperiorSkyblockAPI.getIslandAt(block.getLocation()); + if(island != null) { + IslandPrivilege islandPrivilege = IslandPrivilege.getByName("Build"); + SuperiorPlayer superiorPlayer = SuperiorSkyblockAPI.getPlayer(player.getUniqueId()); + if(!island.hasPermission(superiorPlayer, islandPrivilege)) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + } + if(iShop.townyCheck) + if(!ShopPlotUtil.doesPlayerHaveAbilityToEditShopPlot(player, block.getLocation())) { + player.sendMessage(Messages.NO_SHOP_CREATE_PERMISSION.toString()); + return; + } + } + Optional shopLocation = Shop.getShopByLocation(block.getLocation()); + if(shopLocation.isPresent()) { + player.sendMessage(Messages.EXISTING_SHOP.toString()); + return; + } + Optional shop = Shop.getShopById(sId); + if(!shop.isPresent()) { + player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + return; + } + if(!shop.get().isOwner(player.getUniqueId()) && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.SHOP_NO_SELF.toString()); + return; + } + if(shop.get().isAdmin() && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { + player.sendMessage(Messages.SHOP_BUSY.toString()); + return; + } + final Location oldShopBlock = shop.get().getLocation(); + final Location newShopBlock = block.getLocation(); + final int shopID = shop.get().shopId(); + Shop.moveShop(oldShopBlock, newShopBlock, player, shopID); + } + + private void removeAllShops(Player player, String playerName) { + if(!player.hasPermission(Permission.SHOP_ADMIN.toString())) { + player.sendMessage(Messages.NO_PERMISSION.toString()); + return; + } + UUID sOwner; + Player playerInGame = Bukkit.getPlayer(playerName); + if(playerInGame != null && playerInGame.isOnline()) + sOwner = playerInGame.getUniqueId(); + else { + try { + sOwner = getUUID(playerName); + } catch (Exception e) { + UUID foundPlayerUUID = null; + boolean foundPlayer = false; + for(OfflinePlayer offlinePlayers : Bukkit.getOfflinePlayers()) + if(offlinePlayers.getName().equalsIgnoreCase(playerName)) { + foundPlayerUUID = offlinePlayers.getUniqueId(); + foundPlayer = true; + break; + } + if(!foundPlayer) { + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + return; + } + sOwner = foundPlayerUUID; + } + } + if(InvStock.inShopInv.containsValue(sOwner)) { + player.sendMessage(Messages.SHOP_BUSY.toString()); + return; + } + final UUID shopOwner = sOwner; + Bukkit.getServer().getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> Shop.removeAllPlayersShops(player, shopOwner, playerName)); } private void listShops(Player player, String playerName) { - if(playerName != null && !iShop.config.getBoolean("publicListCommand") && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(playerName != null && !iShop.config.getBoolean("publicListCommand") && (!player.hasPermission(Permission.SHOP_ADMIN.toString()) || !player.hasPermission(Permission.SHOP_LIST.toString()))) { player.sendMessage(Messages.NO_PERMISSION.toString()); return; } @@ -512,12 +1307,28 @@ private void listShops(Player player, String playerName) { sOwner = player.getUniqueId(); playerName = player.getDisplayName(); } else { - try { - sOwner = getUUID(playerName); - } catch (Exception e) { - player.sendMessage(Messages.NO_PLAYER_SHOP.toString()); - Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_SHOP); - return; + Player playerInGame = Bukkit.getPlayer(playerName); + if(playerInGame != null && playerInGame.isOnline()) + sOwner = playerInGame.getUniqueId(); + else { + try { + sOwner = getUUID(playerName); + } catch (Exception e) { + UUID foundPlayerUUID = null; + boolean foundPlayer = false; + for(OfflinePlayer offlinePlayers : Bukkit.getOfflinePlayers()) + if(offlinePlayers.getName().equalsIgnoreCase(playerName)) { + foundPlayerUUID = offlinePlayers.getUniqueId(); + foundPlayer = true; + break; + } + if(!foundPlayer) { + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + return; + } + sOwner = foundPlayerUUID; + } } } Shop.getShopList(player, sOwner, playerName); @@ -532,7 +1343,7 @@ private void listAdminShops(Player player) { } private void listAllShops(Player player) { - if(!InvShop.listAllShops && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(!InvShop.listAllShops && (!player.hasPermission(Permission.SHOP_ADMIN.toString()) || !player.hasPermission(Permission.SHOP_SHOPS.toString()))) { player.sendMessage(Messages.SHOP_LIST_DISABLED.toString()); return; } @@ -563,14 +1374,28 @@ private void stockShop(Player player, String page) { return; } openPage--; - int stockPages = iShop.config.getInt("stockPages"); - if(openPage > 0 && openPage > stockPages-1) - openPage = stockPages-1; + int maxStockPages = InvAdminShop.maxPages; + if(InvAdminShop.usePerms) { + String permPrefix = Permission.SHOP_STOCK_PREFIX.toString(); + int maxPermPages = InvAdminShop.permissionMax; + boolean permissionFound = false; + for(int i=maxPermPages; i>0; i--) + if(player.hasPermission(permPrefix + i)) { + maxStockPages = i; + permissionFound = true; + break; + } + if(!permissionFound) + maxStockPages = maxPermPages; + } + if(openPage > 0 && openPage > maxStockPages-1) + openPage = maxStockPages-1; if(InvStock.inShopInv.containsValue(player.getUniqueId())) { player.sendMessage(Messages.SHOP_BUSY.toString()); return; } else { InvStock.inShopInv.put(player, player.getUniqueId()); } InvStock inv = InvStock.getInvStock(player.getUniqueId()); + inv.setMaxPages(maxStockPages); inv.setPag(openPage); inv.open(player); } @@ -607,10 +1432,16 @@ private void reloadShop(Player player) { EventShop.multipleShopBlocks = iShop.config.getBoolean("multipleShopBlocks"); EventShop.multipleStockBlocks = iShop.config.getBoolean("multipleStockBlocks"); InvAdminShop.remoteManage = iShop.config.getBoolean("remoteManage"); + InvAdminShop.maxPages = iShop.config.getInt("stockPages"); + InvAdminShop.permissionMax = iShop.config.getInt("maxStockPages"); InvAdminShop.stockCommandEnabled = iShop.config.getBoolean("enableStockCommand"); InvAdminShop.stockGUIShop = iShop.config.getBoolean("enableStockAccessFromShopGUI"); + InvAdminShop.usePerms = iShop.config.getBoolean("usePermissions"); InvCreateRow.disabledItemList = iShop.config.getStringList("disabledItemsList"); InvCreateRow.itemsDisabled = iShop.config.getBoolean("disabledItems"); + InvCreateRow.preventDupeTrades = iShop.config.getBoolean("preventDuplicates"); + InvCreateRow.preventAllDupeTrades = iShop.config.getBoolean("preventAllDuplicates"); + InvCreateRow.strictStock = iShop.config.getBoolean("strictStock"); InvShop.listAllShops = iShop.config.getBoolean("publicShopListCommand"); Shop.showOwnedShops = iShop.config.getBoolean("publicShopListShowsOwned"); Shop.shopEnabled = iShop.config.getBoolean("enableShopBlock"); @@ -619,8 +1450,12 @@ private void reloadShop(Player player) { Shop.particleEffects = iShop.config.getBoolean("showParticles"); Shop.maxDays = iShop.config.getInt("maxInactiveDays"); Shop.deletePlayerShop = iShop.config.getBoolean("deleteBlock"); + Shop.saveEmptyShops = iShop.config.getBoolean("saveEmptyShops"); Shop.stockMessages = iShop.config.getBoolean("enableShopSoldMessage"); Shop.exemptExpiringList = iShop.config.getStringList("exemptExpiringShops"); + findCommandPublic = iShop.config.getBoolean("publicFindCommand"); + findCooldownTime = iShop.config.getInt("findCommandCooldown"); + moveCommandPublic = iShop.config.getBoolean("publicMoveCommand"); }); } @@ -635,7 +1470,7 @@ private static UUID getUUID(String name) throws Exception { } private static void shopManage(Player player, String shopID) { - if(!InvAdminShop.remoteManage && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(!InvAdminShop.remoteManage && (!player.hasPermission(Permission.SHOP_ADMIN.toString()) || !player.hasPermission(Permission.SHOP_REMOTEMANAGE.toString()))) { player.sendMessage(Messages.SHOP_REMOTE.toString()); return; } @@ -671,7 +1506,7 @@ private static void shopManage(Player player, String shopID) { } private static void viewShop(Player player, String shopId) { - if(!iShop.config.getBoolean("remoteShopping") && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(!iShop.config.getBoolean("remoteShopping") && (!player.hasPermission(Permission.SHOP_ADMIN.toString()) || !player.hasPermission(Permission.SHOP_REMOTESHOPPING.toString()))) { player.sendMessage(Messages.SHOP_NO_REMOTE.toString()); return; } @@ -688,7 +1523,7 @@ private static void viewShop(Player player, String shopId) { player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); return; } - if(shop.get().getOwner().equals(player.getUniqueId()) && !InvAdminShop.remoteManage && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(shop.get().getOwner().equals(player.getUniqueId()) && !InvAdminShop.remoteManage && (!player.hasPermission(Permission.SHOP_ADMIN.toString()) || !player.hasPermission(Permission.SHOP_REMOTEMANAGE.toString()))) { player.sendMessage(Messages.SHOP_REMOTE.toString()); return; } @@ -700,7 +1535,7 @@ private static void viewShop(Player player, String shopId) { player.sendMessage(Messages.SHOP_BUSY.toString()); return; } - if((shop.get().isAdmin() && player.hasPermission(Permission.SHOP_ADMIN.toString())) || shop.get().isOwner(player.getUniqueId())) { + if((shop.get().isAdmin() && (player.hasPermission(Permission.SHOP_ADMIN.toString())) || shop.get().isOwner(player.getUniqueId()))) { InvAdminShop inv = new InvAdminShop(shop.get(), player); inv.open(player, shop.get().getOwner()); } else { @@ -719,12 +1554,28 @@ private void manageStock(Player player, String stockOwner, String page) { player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); return; } else { - try { - sOwner = getUUID(stockOwner); - } catch (Exception e) { - player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); - Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); - return; + Player playerInGame = Bukkit.getPlayer(stockOwner); + if(playerInGame != null && playerInGame.isOnline()) + sOwner = playerInGame.getUniqueId(); + else { + try { + sOwner = getUUID(stockOwner); + } catch (Exception e) { + UUID foundPlayerUUID = null; + boolean foundPlayer = false; + for(OfflinePlayer offlinePlayers : Bukkit.getOfflinePlayers()) + if(offlinePlayers.getName().equalsIgnoreCase(stockOwner)) { + foundPlayerUUID = offlinePlayers.getUniqueId(); + foundPlayer = true; + break; + } + if(!foundPlayer) { + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + return; + } + sOwner = foundPlayerUUID; + } } } OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(sOwner); @@ -740,17 +1591,24 @@ private void manageStock(Player player, String stockOwner, String page) { return; } pageNum--; - int stockPages = iShop.config.getInt("stockPages"); - if(pageNum > 0 && pageNum > stockPages-1) - pageNum = stockPages-1; + int maxStockPages; + if(InvAdminShop.usePerms) + maxStockPages = InvAdminShop.permissionMax; + else + maxStockPages = InvAdminShop.maxPages; + if(pageNum > 0 && pageNum > maxStockPages-1) + pageNum = maxStockPages-1; final int openPage = pageNum; + final int stockPage = maxStockPages; + final UUID shopOwner = sOwner; Bukkit.getScheduler().runTask(iShop.getPlugin(), () -> { - if(InvStock.inShopInv.containsValue(sOwner)) { + if(InvStock.inShopInv.containsValue(shopOwner)) { player.sendMessage(Messages.SHOP_BUSY.toString()); return; } else - InvStock.inShopInv.put(player, sOwner); - InvStock inv = InvStock.getInvStock(sOwner); + InvStock.inShopInv.put(player, shopOwner); + InvStock inv = InvStock.getInvStock(shopOwner); + inv.setMaxPages(stockPage); inv.setPag(openPage); inv.open(player); }); @@ -864,12 +1722,28 @@ private void outOfStock(Player player, String playerName) { sOwner = player.getUniqueId(); playerName = player.getDisplayName(); } else { - try { - sOwner = getUUID(playerName); - } catch (Exception e) { - player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); - Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); - return; + Player playerInGame = Bukkit.getPlayer(playerName); + if(playerInGame != null && playerInGame.isOnline()) + sOwner = playerInGame.getUniqueId(); + else { + try { + sOwner = getUUID(playerName); + } catch (Exception e) { + UUID foundPlayerUUID = null; + boolean foundPlayer = false; + for(OfflinePlayer offlinePlayers : Bukkit.getOfflinePlayers()) + if(offlinePlayers.getName().equalsIgnoreCase(playerName)) { + foundPlayerUUID = offlinePlayers.getUniqueId(); + foundPlayer = true; + break; + } + if(!foundPlayer) { + player.sendMessage(Messages.NO_PLAYER_FOUND.toString()); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] " + Messages.NO_PLAYER_FOUND); + return; + } + sOwner = foundPlayerUUID; + } } } player.sendMessage(Messages.SHOP_LIST_OUT.toString()); diff --git a/src/com/minedhype/ishop/EventShop.java b/src/com/minedhype/ishop/EventShop.java index ceb2a7b..6d41318 100644 --- a/src/com/minedhype/ishop/EventShop.java +++ b/src/com/minedhype/ishop/EventShop.java @@ -41,6 +41,7 @@ public class EventShop implements Listener { public static boolean noShopNoStock = iShop.config.getBoolean("mustOwnShopForStock"); public static boolean placeFrameSign = iShop.config.getBoolean("placeItemFrameSigns"); public static boolean protectShopFromExplosion = iShop.config.getBoolean("protectShopBlocksFromExplosions"); + public static boolean shuttingDown = false; public static int soldMessageDelayTime = iShop.config.getInt("soldNotificationsDelayTime"); public static int stockRangeLimit = iShop.config.getInt("stockRangeLimitFromShop"); public static String shopBlock = iShop.config.getString("shopBlock"); @@ -88,6 +89,8 @@ public void onPlayerInteract(PlayerInteractEvent event) { return; } event.setCancelled(true); + if(shuttingDown) + return; if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { if(event.getHand().equals(EquipmentSlot.HAND)) event.getPlayer().sendMessage(Messages.SHOP_BUSY.toString()); @@ -122,6 +125,8 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) return; } event.setCancelled(true); + if(shuttingDown) + return; if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { if(event.getHand().equals(EquipmentSlot.HAND)) event.getPlayer().sendMessage(Messages.SHOP_BUSY.toString()); @@ -159,6 +164,8 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) return; } event.setCancelled(true); + if(shuttingDown) + return; if(InvStock.inShopInv.containsValue(shop.get().getOwner())) { if(event.getHand().equals(EquipmentSlot.HAND)) event.getPlayer().sendMessage(Messages.SHOP_BUSY.toString()); @@ -186,6 +193,8 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) if(!isShopLoc || event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking()) return; event.setCancelled(true); + if(shuttingDown) + return; if(event.getAction() == Action.LEFT_CLICK_BLOCK) { if(Shop.getNumShops(event.getPlayer().getUniqueId()) < 1 && noShopNoStock) { event.getPlayer().sendMessage(Messages.NO_SHOP_STOCK.toString()); @@ -201,6 +210,21 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) return; } else { InvStock.inShopInv.put(event.getPlayer(), event.getPlayer().getUniqueId()); } InvStock inv = InvStock.getInvStock(event.getPlayer().getUniqueId()); + int maxStockPages = InvAdminShop.maxPages; + if(InvAdminShop.usePerms) { + String permPrefix = Permission.SHOP_STOCK_PREFIX.toString(); + int maxPermPages = InvAdminShop.permissionMax; + boolean permissionFound = false; + for(int i=maxPermPages; i>0; i--) + if(event.getPlayer().hasPermission(permPrefix + i)) { + maxStockPages = i; + permissionFound = true; + break; + } + if(!permissionFound) + maxStockPages = maxPermPages; + } + inv.setMaxPages(maxStockPages); inv.setPag(0); inv.open(event.getPlayer()); } @@ -218,6 +242,8 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) if(!isShopLoc || event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking()) return; event.setCancelled(true); + if(shuttingDown) + return; if(event.getAction() == Action.LEFT_CLICK_BLOCK) { if(Shop.getNumShops(event.getPlayer().getUniqueId()) < 1 && noShopNoStock) { event.getPlayer().sendMessage(Messages.NO_SHOP_STOCK.toString()); @@ -233,6 +259,21 @@ else if(event.getHand().equals(EquipmentSlot.OFF_HAND)) return; } else { InvStock.inShopInv.put(event.getPlayer(), event.getPlayer().getUniqueId()); } InvStock inv = InvStock.getInvStock(event.getPlayer().getUniqueId()); + int maxStockPages = InvAdminShop.maxPages; + if(InvAdminShop.usePerms) { + String permPrefix = Permission.SHOP_STOCK_PREFIX.toString(); + int maxPermPages = InvAdminShop.permissionMax; + boolean permissionFound = false; + for(int i=maxPermPages; i>0; i--) + if(event.getPlayer().hasPermission(permPrefix + i)) { + maxStockPages = i; + permissionFound = true; + break; + } + if(!permissionFound) + maxStockPages = maxPermPages; + } + inv.setMaxPages(maxStockPages); inv.setPag(0); inv.open(event.getPlayer()); } diff --git a/src/com/minedhype/ishop/Messages.java b/src/com/minedhype/ishop/Messages.java index 41641fa..01f50af 100644 --- a/src/com/minedhype/ishop/Messages.java +++ b/src/com/minedhype/ishop/Messages.java @@ -7,7 +7,9 @@ public enum Messages { ADMIN_SHOP_NUMBER("adminShopNumber"), DISABLED_SHOP_BLOCK("disabledShopBlock"), EXISTING_SHOP("existingShop"), + GP_CLAIM("noClaimPermission"), NOT_A_PLAYER("notPlayer"), + NO_SHOP_CREATE_PERMISSION("noPermissionToCreateShop"), NO_PERMISSION("noPermissions"), NO_PLAYER_FOUND("noPlayerFound"), NO_PLAYER_SHOP("noPlayerShop"), @@ -20,9 +22,15 @@ public enum Messages { SHOP_CLICK_MANAGE("clickManage"), SHOP_CLICK_SHOP("clickShop"), SHOP_CREATED("shopCreated"), + SHOP_CREATED_LOC("shopCreatedLoc"), SHOP_CREATE_NO_MONEY("noMoney"), SHOP_DELETED("shopDeleted"), + SHOP_DELETED_LOC("shopDeletedLoc"), SHOP_FAR("outOfStockRange"), + SHOP_FIND("listFind"), + SHOP_FIND_COOLDOWN("cooldownMessageFind"), + SHOP_FIND_ERROR("findError"), + SHOP_FIND_NONE("nolistFind"), SHOP_FOUND("foundShops"), SHOP_IDDELETED("shopIDDeleted"), SHOP_ID_INTEGER("shopIntegerError"), @@ -31,7 +39,10 @@ public enum Messages { SHOP_LIST_DISABLED("shopListDisabled"), SHOP_LIST_OUT("listOutOfStock"), SHOP_LOCATION("location"), + SHOP_LOCATION_ERROR_NUM("shopLocationErrorNum"), + SHOP_LOCATION_ERROR_WORLD("shopLocationErrorWorld"), SHOP_MAX("shopLimit"), + SHOP_MOVED("shopMoved"), SHOP_NOT_FOUND("noShopFound"), SHOP_NOT_OUT("notOutOfStock"), SHOP_NO_ADMINSHOPS_FOUND("noAdminShopsFound"), @@ -44,9 +55,12 @@ public enum Messages { SHOP_NUMBER("shopNumber"), SHOP_OUT("outOfStock"), SHOP_PAGE("page"), + SHOP_PAGE_SKIPAHEAD("pageSkipAhead"), + SHOP_PAGE_SKIPPREV("pageSkipPrev"), SHOP_PURCHASE("buy"), SHOP_RELOAD("reload"), SHOP_REMOTE("noRemoteManage"), + SHOP_REMOVED_ALL_PLAYER("removedAllPlayer"), SHOP_SELL("sell"), SHOP_TITLE_ADMIN_SHOP("adminShop"), SHOP_TITLE_BROADCAST_OFF("broadcastOff"), diff --git a/src/com/minedhype/ishop/Permission.java b/src/com/minedhype/ishop/Permission.java index 1130828..0bc9d78 100644 --- a/src/com/minedhype/ishop/Permission.java +++ b/src/com/minedhype/ishop/Permission.java @@ -2,10 +2,18 @@ public enum Permission { SHOP_ADMIN("ishop.admin"), + SHOP_BYPASS_FIND_CD("ishop.bypassfindcooldown"), SHOP_CREATE("ishop.create"), + SHOP_FIND("ishop.find"), SHOP_LIMIT_BYPASS("ishop.create.limit.bypass"), SHOP_LIMIT_PREFIX("ishop.create.limit."), - SHOP_STOCK("ishop.stock"); + SHOP_LIST("ishop.list"), + SHOP_MOVE("ishop.move"), + SHOP_REMOTEMANAGE("ishop.remotemanage"), + SHOP_REMOTESHOPPING("ishop.remoteshopping"), + SHOP_SHOPS("ishop.shops"), + SHOP_STOCK("ishop.stock"), + SHOP_STOCK_PREFIX("ishop.pages."); private final String perm; Permission(String perms) { diff --git a/src/com/minedhype/ishop/RowStore.java b/src/com/minedhype/ishop/RowStore.java index c2cc624..3cea03a 100644 --- a/src/com/minedhype/ishop/RowStore.java +++ b/src/com/minedhype/ishop/RowStore.java @@ -1,8 +1,9 @@ package com.minedhype.ishop; import java.sql.PreparedStatement; +import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class RowStore { @@ -24,47 +25,36 @@ public RowStore(ItemStack itemOut, ItemStack itemOut2, ItemStack itemIn, ItemSta public void saveData(int idTienda) { PreparedStatement stmt = null; try { - stmt = iShop.getConnection().prepareStatement("INSERT INTO zooMercaTiendasFilas (itemIn, itemIn2, itemOut, itemOut2, idTienda, broadcast) VALUES (?,?,?,?,?,?);"); - YamlConfiguration configIn1 = new YamlConfiguration(); + stmt = iShop.getConnection().prepareStatement("INSERT INTO zooMercaTiendasFilas (itemInNew, itemIn2New, itemOutNew, itemOut2New, idTienda, broadcast) VALUES (?,?,?,?,?,?);"); + ItemStack[] saveAirItem = new ItemStack[]{airItem}; + final Inventory invIn = Bukkit.createInventory(null,9); + final Inventory invIn2 = Bukkit.createInventory(null,9); + final Inventory invOut = Bukkit.createInventory(null,9); + final Inventory invOut2 = Bukkit.createInventory(null,9); if(itemIn != null) { - itemIn.serialize().forEach(configIn1::set); - String itemInRaw = configIn1.saveToString(); - stmt.setString(1, itemInRaw); - } else { - airItem.serialize().forEach(configIn1::set); - String itemInRaw = configIn1.saveToString(); - stmt.setString(1, itemInRaw); - } - YamlConfiguration configIn2 = new YamlConfiguration(); + ItemStack[] item = new ItemStack[]{itemIn}; + invIn.addItem(item[0]); + } else + invIn.addItem(saveAirItem[0]); + stmt.setBytes(1, iShop.encodeByte(invIn.getContents())); if(itemIn2 != null) { - itemIn2.serialize().forEach(configIn2::set); - String itemIn2Raw = configIn2.saveToString(); - stmt.setString(2, itemIn2Raw); - } else { - airItem.serialize().forEach(configIn2::set); - String itemIn2Raw = configIn2.saveToString(); - stmt.setString(2, itemIn2Raw); - } - YamlConfiguration configOut1 = new YamlConfiguration(); + ItemStack[] item = new ItemStack[]{itemIn2}; + invIn2.addItem(item[0]); + } else + invIn2.addItem(saveAirItem[0]); + stmt.setBytes(2, iShop.encodeByte(invIn2.getContents())); if(itemOut != null) { - itemOut.serialize().forEach(configOut1::set); - String itemOutRaw = configOut1.saveToString(); - stmt.setString(3, itemOutRaw); - } else { - airItem.serialize().forEach(configOut1::set); - String itemOutRaw = configOut1.saveToString(); - stmt.setString(3, itemOutRaw); - } - YamlConfiguration configOut2 = new YamlConfiguration(); + ItemStack[] item = new ItemStack[]{itemOut}; + invOut.addItem(item[0]); + } else + invOut.addItem(saveAirItem[0]); + stmt.setBytes(3, iShop.encodeByte(invOut.getContents())); if(itemOut2 != null) { - itemOut2.serialize().forEach(configOut2::set); - String itemOut2Raw = configOut2.saveToString(); - stmt.setString(4, itemOut2Raw); - } else { - airItem.serialize().forEach(configOut2::set); - String itemOut2Raw = configOut2.saveToString(); - stmt.setString(4, itemOut2Raw); - } + ItemStack[] item = new ItemStack[]{itemOut2}; + invOut2.addItem(item[0]); + } else + invOut2.addItem(saveAirItem[0]); + stmt.setBytes(4, iShop.encodeByte(invOut2.getContents())); stmt.setInt(5, idTienda); stmt.setBoolean(6, broadcast); stmt.execute(); @@ -81,15 +71,23 @@ public void toggleBroadcast() { this.broadcast = !this.broadcast; } public ItemStack getItemIn() { + if(itemIn == null) + return airItem; return itemIn; } public ItemStack getItemIn2() { + if(itemIn2 == null) + return airItem; return itemIn2; } public ItemStack getItemOut() { + if(itemOut == null) + return airItem; return itemOut; } public ItemStack getItemOut2() { + if(itemOut2 == null) + return airItem; return itemOut2; } } diff --git a/src/com/minedhype/ishop/Shop.java b/src/com/minedhype/ishop/Shop.java index 9d8170a..dbafa23 100644 --- a/src/com/minedhype/ishop/Shop.java +++ b/src/com/minedhype/ishop/Shop.java @@ -1,5 +1,6 @@ package com.minedhype.ishop; +import java.sql.Blob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; @@ -10,7 +11,9 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import javax.sql.rowset.serial.SerialBlob; import com.minedhype.ishop.inventories.InvAdminShop; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -19,11 +22,14 @@ import org.bukkit.OfflinePlayer; import org.bukkit.Particle; import org.bukkit.World; +import org.bukkit.block.ShulkerBox; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BlockStateMeta; import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.plugin.Plugin; import com.google.gson.JsonArray; @@ -33,10 +39,13 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent.Action; import net.md_5.bungee.api.chat.TextComponent; +import net.milkbowl.vault.economy.Economy; +import static com.minedhype.ishop.iShop.decodeByte; public class Shop { public static boolean deletePlayerShop = iShop.config.getBoolean("deleteBlock"); public static boolean particleEffects = iShop.config.getBoolean("showParticles"); + public static boolean saveEmptyShops = iShop.config.getBoolean("saveEmptyShops"); public static boolean shopOutStock = iShop.config.getBoolean("enableOutOfStockMessages"); public static boolean shopEnabled = iShop.config.getBoolean("enableShopBlock"); public static boolean showOwnedShops = iShop.config.getBoolean("publicShopListShowsOwned"); @@ -44,6 +53,7 @@ public class Shop { public static boolean stockMessages = iShop.config.getBoolean("enableShopSoldMessage"); public static boolean stockMessagesSaveAll = iShop.config.getBoolean("enableSavingAllShopSoldMessages"); public static List exemptExpiringList = iShop.config.getStringList("exemptExpiringShops"); + public static Particle shopParticles = Particle.valueOf(iShop.config.getString("shopParticles").toUpperCase()); public static int maxDays = iShop.config.getInt("maxInactiveDays"); public static final ConcurrentHashMap shopList = new ConcurrentHashMap<>(); public static final ConcurrentHashMap> shopMessages = new ConcurrentHashMap<>(); @@ -96,6 +106,23 @@ private Shop(int idTienda, UUID owner, Location loc, boolean admin) { public static boolean checkShopDistanceFromStockBlock(Location stockLocation, UUID shopOwner) { return shops.parallelStream().filter(s -> !s.admin && s.isOwner(shopOwner)).anyMatch(s -> s.getLocation().getWorld().equals(stockLocation.getWorld()) && s.location.distanceSquared(stockLocation) <= EventShop.stockRangeLimit*EventShop.stockRangeLimit); } public static int getNumShops(UUID owner) { return (int) shops.parallelStream().filter(t -> !t.admin && t.owner.equals(owner)).count(); } + public static boolean strictStockShopCheck(ItemStack item, UUID uuid) { + AtomicBoolean restricted = new AtomicBoolean(true); + shops.parallelStream().filter(s -> !s.admin && s.isOwner(uuid)).forEach(s -> { + if(restricted.get()) { + for(int i=0; i<5; i++) { + if(restricted.get()) { + Optional row = s.getRow(i); + if(row.isPresent()) + if(row.get().getItemOut().isSimilar(item) || row.get().getItemOut2().isSimilar(item)) + restricted.set(false); + } + } + } + }); + return restricted.get(); + } + public static void getPlayersShopList() { if(iShop.config.getBoolean("adminShopPublic")) shops.parallelStream().forEach(s -> shopList.putIfAbsent(s.idTienda, s.owner)); @@ -103,18 +130,204 @@ public static void getPlayersShopList() { shops.parallelStream().filter(s -> !s.admin).forEach(s -> shopList.putIfAbsent(s.idTienda, s.owner)); } + public static void findItem(Player player, ItemStack item, String itemName) { + player.sendMessage(Messages.SHOP_FIND.toString().replaceAll("%item", itemName.toLowerCase())); + AtomicBoolean foundItem = new AtomicBoolean(false); + shops.parallelStream().forEach(s -> { + AtomicBoolean foundItemInShop = new AtomicBoolean(false); + for(int i=0; i<5; i++) { + Optional row = s.getRow(i); + if(row.isPresent() && !foundItemInShop.get()) { + boolean itemMatch = row.get().getItemOut().isSimilar(item); + boolean itemMatch2 = row.get().getItemOut2().isSimilar(item); + if(((itemMatch && itemMatch2) && Utils.hasDoubleItemStock(s, row.get().getItemOut(), row.get().getItemOut2())) || ((itemMatch && !itemMatch2) && Utils.hasStock(s, row.get().getItemOut())) || ((!itemMatch && itemMatch2) && Utils.hasStock(s, row.get().getItemOut2()))) { + foundItem.set(true); + foundItemInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + if(row.get().getItemOut().getType().toString().contains("SHULKER_BOX") && row.get().getItemOut().getItemMeta() instanceof BlockStateMeta && Utils.hasStock(s, row.get().getItemOut())) { + BlockStateMeta itemMeta = (BlockStateMeta) row.get().getItemOut().getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) itemMeta.getBlockState(); + if(shulkerBox.getInventory().contains(item.getType())) + for(ItemStack itemSearch:shulkerBox.getInventory().getContents()) { + if(itemSearch.isSimilar(item)) { + foundItem.set(true); + foundItemInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + if(row.get().getItemOut2().getType().toString().contains("SHULKER_BOX") && row.get().getItemOut2().getItemMeta() instanceof BlockStateMeta && Utils.hasStock(s, row.get().getItemOut2())) { + BlockStateMeta itemMeta = (BlockStateMeta) row.get().getItemOut2().getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) itemMeta.getBlockState(); + if(shulkerBox.getInventory().contains(item.getType())) + for(ItemStack itemSearch:shulkerBox.getInventory().getContents()) { + if(itemSearch.isSimilar(item)) { + foundItem.set(true); + foundItemInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + } + } + }); + if(!foundItem.get()) + player.sendMessage(Messages.SHOP_FIND_NONE.toString()); + } + public static void findBook(Player player, String bookName) { + player.sendMessage(Messages.SHOP_FIND.toString().replaceAll("%item", bookName.toLowerCase())); + AtomicBoolean foundItem = new AtomicBoolean(false); + shops.parallelStream().forEach(s -> { + AtomicBoolean foundBookInShop = new AtomicBoolean(false); + for(int i=0; i<5; i++) { + Optional row = s.getRow(i); + if(!row.isPresent()) + continue; + if(!foundBookInShop.get() && (row.get().getItemOut().getType().equals(Material.ENCHANTED_BOOK) || row.get().getItemOut2().getType().equals(Material.ENCHANTED_BOOK))) { + if(row.get().getItemOut().equals(row.get().getItemOut2()) && row.get().getItemOut().getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) row.get().getItemOut().getItemMeta(); + if(meta.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasEnchantment(s, bookName, true)) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + else { + if(row.get().getItemOut().getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) row.get().getItemOut().getItemMeta(); + if(meta.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasEnchantment(s, bookName, false) || !Utils.hasStock(s, row.get().getItemOut2())) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + if(row.get().getItemOut2().getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta2 = (EnchantmentStorageMeta) row.get().getItemOut2().getItemMeta(); + if(meta2.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasEnchantment(s, bookName, false) || !Utils.hasStock(s, row.get().getItemOut())) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + } + if(!foundBookInShop.get() && (row.get().getItemOut().getType().toString().contains("SHULKER_BOX") && row.get().getItemOut2().getType().toString().contains("SHULKER_BOX")) && (row.get().getItemOut().getItemMeta() instanceof BlockStateMeta && row.get().getItemOut2().getItemMeta() instanceof BlockStateMeta) && row.get().getItemOut().equals(row.get().getItemOut2())) { + BlockStateMeta itemMeta = (BlockStateMeta) row.get().getItemOut().getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) itemMeta.getBlockState(); + if(shulkerBox.getInventory().contains(Material.ENCHANTED_BOOK)) { + for(ItemStack item:shulkerBox.getInventory().getContents()) { + if(item != null && item.getType().equals(Material.ENCHANTED_BOOK) && item.hasItemMeta() && item.getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta(); + if(meta.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasDoubleItemStock(s, row.get().getItemOut(), row.get().getItemOut2())) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + } + } + else { + if(!foundBookInShop.get() && row.get().getItemOut().getType().toString().contains("SHULKER_BOX") && row.get().getItemOut().getItemMeta() instanceof BlockStateMeta) { + BlockStateMeta itemMeta = (BlockStateMeta) row.get().getItemOut().getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) itemMeta.getBlockState(); + if(shulkerBox.getInventory().contains(Material.ENCHANTED_BOOK)) { + for(ItemStack item:shulkerBox.getInventory().getContents()) { + if(item != null && item.getType().equals(Material.ENCHANTED_BOOK) && item.hasItemMeta() && item.getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta(); + if(meta.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasStock(s, row.get().getItemOut())) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + } + } + if(!foundBookInShop.get() && row.get().getItemOut2().getType().toString().contains("SHULKER_BOX") && row.get().getItemOut2().getItemMeta() instanceof BlockStateMeta) { + BlockStateMeta itemMeta = (BlockStateMeta) row.get().getItemOut2().getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) itemMeta.getBlockState(); + if(shulkerBox.getInventory().contains(Material.ENCHANTED_BOOK)) { + for(ItemStack item:shulkerBox.getInventory().getContents()) { + if(item != null && item.getType().equals(Material.ENCHANTED_BOOK) && item.hasItemMeta() && item.getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta(); + if(meta.getStoredEnchants().toString().contains(bookName)) { + if(!Utils.hasStock(s, row.get().getItemOut2())) + break; + foundItem.set(true); + foundBookInShop.set(true); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); + break; + } + } + } + } + } + } + } + }); + if(!foundItem.get()) + player.sendMessage(Messages.SHOP_FIND_NONE.toString()); + } + + public static void removeAllPlayersShops(Player player, UUID sOwner, String pOwner) { + int deletedCount = 0; + List deleteShops = new ArrayList<>(); + for(Shop shop:shops) + if(!shop.admin && shop.isOwner(sOwner)) { + deleteShops.add(shop); + deletedCount++; + } + for(Shop shop:deleteShops) { + shopList.remove(shop.shopId()); + shop.deleteShop(); + } + Optional economy = iShop.getEconomy(); + if(economy.isPresent()) { + double cost = iShop.config.getDouble("returnAmount"); + if(deletedCount > 0 && cost > 0) { + OfflinePlayer offPlayer = Bukkit.getOfflinePlayer(sOwner); + double totalCost = cost * deletedCount; + economy.get().depositPlayer(offPlayer, totalCost); + } + } + if(deletedCount > 0) + player.sendMessage(Messages.SHOP_REMOVED_ALL_PLAYER.toString().replaceAll("%p", pOwner).replaceAll("%shops", String.valueOf(deletedCount))); + else + player.sendMessage(Messages.SHOP_NOT_FOUND.toString()); + } + public static void getShopList(Player player, UUID sOwner, String pOwner) { player.sendMessage(Messages.SHOP_FOUND.toString().replaceAll("%p", pOwner).replaceAll("%shops", String.valueOf(getNumShops(sOwner)))); shops.parallelStream().filter(s -> !s.admin && s.isOwner(sOwner)).forEach(s -> { if(s.isOwner(player.getUniqueId()) && InvAdminShop.remoteManage) { - String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)) + ChatColor.GREEN + s.location.getBlockX() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockY() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockZ() + ChatColor.GOLD + " in " + ChatColor.GREEN + s.location.getWorld().getName(); + String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName()); TextComponent manageMsg = new TextComponent(manageMessage); TextComponent manageText = new TextComponent(ChatColor.DARK_GRAY + " [" + Messages.SHOP_CLICK_MANAGE + ChatColor.DARK_GRAY + "]"); manageText.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/shop manage " + s.idTienda)); manageMsg.addExtra(manageText); player.spigot().sendMessage(manageMsg); } else if(player.hasPermission(Permission.SHOP_ADMIN.toString())) { - String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)) + ChatColor.GREEN + s.location.getBlockX() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockY() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockZ() + ChatColor.GOLD + " in " + ChatColor.GREEN + s.location.getWorld().getName(); + String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName()); TextComponent manageMsg = new TextComponent(manageMessage); TextComponent manageText = new TextComponent(ChatColor.DARK_GRAY + " [" + Messages.SHOP_CLICK_MANAGE + ChatColor.DARK_GRAY + "]"); manageText.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/shop manage " + s.idTienda)); @@ -129,14 +342,14 @@ public static void getShopList(Player player, UUID sOwner, String pOwner) { } else player.spigot().sendMessage(manageMsg); } else if(iShop.config.getBoolean("remoteShopping") && !s.isOwner(player.getUniqueId())) { - String shopMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)) + ChatColor.GREEN + s.location.getBlockX() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockY() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockZ() + ChatColor.GOLD + " in " + ChatColor.GREEN + s.location.getWorld().getName(); + String shopMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName()); TextComponent shopMsg = new TextComponent(shopMessage); TextComponent shopText = new TextComponent(ChatColor.DARK_GRAY + " [" + Messages.SHOP_CLICK_SHOP + ChatColor.DARK_GRAY + "]"); shopText.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/shop view " + s.idTienda)); shopMsg.addExtra(shopText); player.spigot().sendMessage(shopMsg); } else - player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)) + ChatColor.GREEN + s.location.getBlockX() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockY() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockZ() + ChatColor.GOLD + " in " + ChatColor.GREEN + s.location.getWorld().getName()); + player.sendMessage(Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName())); }); } @@ -144,7 +357,7 @@ public static void getAdminShopList(Player player) { player.sendMessage(Messages.SHOP_LIST_ADMINSHOPS.toString()); AtomicInteger shopCount = new AtomicInteger(0); shops.parallelStream().filter(s -> s.admin).forEach(s -> { - String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)) + ChatColor.GREEN + s.location.getBlockX() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockY() + ChatColor.GOLD + " / " + ChatColor.GREEN + s.location.getBlockZ() + ChatColor.GOLD + " in " + ChatColor.GREEN + s.location.getWorld().getName(); + String manageMessage = Messages.SHOP_LOCATION.toString().replaceAll("%id", String.valueOf(s.idTienda)).replaceAll("%x", String.valueOf(s.location.getBlockX())).replaceAll("%y", String.valueOf(s.location.getBlockY())).replaceAll("%z", String.valueOf(s.location.getBlockZ())).replaceAll("%world", s.location.getWorld().getName()); TextComponent manageMsg = new TextComponent(manageMessage); TextComponent manageText = new TextComponent(ChatColor.DARK_GRAY + " [" + Messages.SHOP_CLICK_MANAGE + ChatColor.DARK_GRAY + "]"); manageText.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/shop manage " + s.idTienda)); @@ -391,6 +604,20 @@ public static Shop createShop(Location loc, UUID owner, boolean admin) { return shop; } + public static Shop duplicateShop(Location loc, UUID owner, int shopId) { + Shop shop = new Shop(-1, owner, loc, false); + shops.add(shop); + Optional stockShop = StockShop.getStockShopByOwner(owner, 0); + if(!stockShop.isPresent()) + new StockShop(owner, 0); + Optional copyShop = Shop.getShopById(shopId); + for(int i=0;i<5;i++) { + if(copyShop.get().getRows()[i] != null) + shop.getRows()[i] = copyShop.get().getRows()[i]; + } + return shop; + } + public static void tickShops() { if(!shopEnabled) return; @@ -400,7 +627,11 @@ public static void tickShops() { double x = shop.location.getBlockX() + 0.5; double y = shop.location.getBlockY() + 1.25; double z = shop.location.getBlockZ() + 0.5; - shop.location.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, x, y, z, 10, 0.1, 0.1, 0.1); + try { + shop.location.getWorld().spawnParticle(shopParticles, x, y, z, 10, 0.1, 0.1, 0.1); + } catch(Exception e) { + shop.location.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, x, y, z, 10, 0.1, 0.1, 0.1); + } } } } @@ -424,8 +655,104 @@ public static void loadData() { PreparedStatement loadShops = null; try { - loadStocks = iShop.getConnection().prepareStatement("SELECT owner, items, pag FROM zooMercaStocks;"); + loadStocks = iShop.getConnection().prepareStatement("SELECT owner, itemsNew, pag FROM zooMercaStocks;"); ResultSet dataStocks = loadStocks.executeQuery(); + while(dataStocks.next()) { + String ownerRaw = dataStocks.getString(1); + UUID owner = UUID.fromString(ownerRaw); + int pag = dataStocks.getInt(3); + try { + Blob blob = new SerialBlob(dataStocks.getBytes(2)); + StockShop stock = new StockShop(owner, pag); + stock.getInventory().setContents(decodeByte(blob.getBinaryStream())); + } catch (Exception ignored) { } + } + loadShops = iShop.getConnection().prepareStatement("SELECT location, owner, itemInNew, itemIn2New, itemOutNew, itemOut2New, idTienda, admin, broadcast FROM zooMercaTiendasFilas LEFT JOIN zooMercaTiendas ON id = idTienda ORDER BY idTienda;"); + ResultSet dataStore = loadShops.executeQuery(); + while(dataStore.next()) { + if(dataStore.getString(1) == null) { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Error: Skipped loading a shop with null location found in database! Make backups!"); + continue; + } + String[] locationRaw = dataStore.getString(1).split(";"); + int x = Integer.parseInt(locationRaw[0]); + int y = Integer.parseInt(locationRaw[1]); + int z = Integer.parseInt(locationRaw[2]); + World world = Bukkit.getWorld(locationRaw[3]); + if(world == null) { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Error: Skipped loading a shop with null world found in database! Make backups!"); + continue; + } + Location location = new Location(world, x, y, z); + Optional shop = Shop.getShopByLocation(location); + if(!shop.isPresent()) { + String ownerRaw = dataStore.getString(2); + UUID owner = UUID.fromString(ownerRaw); + int idTienda = dataStore.getInt(7); + boolean admin = dataStore.getBoolean(8); + shops.add(new Shop(idTienda, owner, location, admin)); + shop = Shop.getShopByLocation(location); + } + RowStore[] rows = shop.get().getRows(); + int index = 0; + for(int len=rows.length; index= rows.length) + continue; + boolean broadcast = dataStore.getBoolean(9); + ItemStack airItem = new ItemStack(Material.AIR, 0); + final Inventory invIn = Bukkit.createInventory(null,9); + final Inventory invIn2 = Bukkit.createInventory(null,9); + final Inventory invOut = Bukkit.createInventory(null,9); + final Inventory invOut2 = Bukkit.createInventory(null,9); + try { + Blob blob = new SerialBlob(dataStore.getBytes(3)); + invIn.setContents(decodeByte(blob.getBinaryStream())); + } + catch(Exception e) { invIn.addItem(airItem); } + try { + Blob blob = new SerialBlob(dataStore.getBytes(4)); + invIn2.setContents(decodeByte(blob.getBinaryStream())); + } + catch(Exception e) { invIn2.addItem(airItem); } + try { + Blob blob = new SerialBlob(dataStore.getBytes(5)); + invOut.setContents(decodeByte(blob.getBinaryStream())); + } + catch(Exception e) { invOut.addItem(airItem); } + try { + Blob blob = new SerialBlob(dataStore.getBytes(6)); + invOut2.setContents(decodeByte(blob.getBinaryStream())); + } + catch(Exception e) { invOut2.addItem(airItem); } + rows[index] = new RowStore(invOut.getItem(0), invOut2.getItem(0), invIn.getItem(0), invIn2.getItem(0), broadcast); + } + } catch(Exception e) { + e.printStackTrace(); + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Failed to load database properly! Shutting down to prevent data corruption."); + Bukkit.shutdown(); + } finally { + try { + if(loadStocks != null) + loadStocks.close(); + if(loadRows != null) + loadRows.close(); + if(loadShops != null) + loadShops.close(); + } catch (Exception e) { e.printStackTrace(); } + } + } + + public static void convertData() { + boolean failedToLoad = false; + PreparedStatement loadOldShops = null; + PreparedStatement loadOldStock = null; + try { + loadOldStock = iShop.getConnection().prepareStatement("SELECT owner, items, pag FROM zooMercaStocks;"); + ResultSet dataStocks = loadOldStock.executeQuery(); while(dataStocks.next()) { String ownerRaw = dataStocks.getString(1); UUID owner = UUID.fromString(ownerRaw); @@ -445,16 +772,22 @@ public static void loadData() { StockShop stock = new StockShop(owner, pag); stock.getInventory().setContents(itemsList.toArray(new ItemStack[0])); } - loadShops = iShop.getConnection().prepareStatement("SELECT location, owner, itemIn, itemIn2, itemOut, itemOut2, idTienda, admin, broadcast FROM zooMercaTiendasFilas LEFT JOIN zooMercaTiendas ON id = idTienda ORDER BY idTienda;"); - ResultSet dataStore = loadShops.executeQuery(); + loadOldShops = iShop.getConnection().prepareStatement("SELECT location, owner, itemIn, itemIn2, itemOut, itemOut2, idTienda, admin, broadcast FROM zooMercaTiendasFilas LEFT JOIN zooMercaTiendas ON id = idTienda ORDER BY idTienda;"); + ResultSet dataStore = loadOldShops.executeQuery(); while(dataStore.next()) { + if(dataStore.getString(1) == null) { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Error: Skipped loading a shop with null location found in database! Make backups!"); + continue; + } String[] locationRaw = dataStore.getString(1).split(";"); int x = Integer.parseInt(locationRaw[0]); int y = Integer.parseInt(locationRaw[1]); int z = Integer.parseInt(locationRaw[2]); World world = Bukkit.getWorld(locationRaw[3]); - if(world == null) + if(world == null) { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Error: Skipped loading a shop with null world found in database! Make backups!"); continue; + } Location location = new Location(world, x, y, z); Optional shop = Shop.getShopByLocation(location); if(!shop.isPresent()) { @@ -469,7 +802,7 @@ public static void loadData() { int index = 0; for(int len=rows.length; index= rows.length) @@ -487,7 +820,7 @@ public static void loadData() { configIn2.loadFromString(itemInstack2Raw); configOut1.loadFromString(itemOutstack1Raw); configOut2.loadFromString(itemOutstack2Raw); - } catch (InvalidConfigurationException e) { e.printStackTrace(); } + } catch (Exception e) { e.printStackTrace(); } Map itemInRaw = configIn1.getValues(true); ItemStack itemIn = ItemStack.deserialize(itemInRaw); Map itemIn2Raw = configIn2.getValues(true); @@ -499,24 +832,28 @@ public static void loadData() { boolean broadcast = dataStore.getBoolean(9); rows[index] = new RowStore(itemOut, itemOut2, itemIn, itemIn2, broadcast); } - } catch(Exception e) { e.printStackTrace(); - Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Failed to load database properly! Shutting down to prevent data corruption."); - Bukkit.shutdown(); - } finally { + Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[iShop] Failed to convert/load database, keep multiple back-ups for safety!"); + failedToLoad = true; + } finally{ try { - if(loadStocks != null) - loadStocks.close(); - if(loadRows != null) - loadRows.close(); - if(loadShops != null) - loadShops.close(); - } catch (Exception e) { e.printStackTrace(); } + if(loadOldShops != null) + loadOldShops.close(); + if(loadOldStock != null) + loadOldStock.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + if(!failedToLoad) { + iShop.dropOldColumns(); + Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN + "[iShop] Successfully converted database!"); + Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN + "[iShop] We STRONGLY recommend restarting your server now to prevent data corruption!"); } } - public static void saveData() { + public static void saveData(boolean shutDown) { StockShop.saveData(); PreparedStatement stmt = null; try { @@ -529,8 +866,18 @@ public static void saveData() { stmt.close(); } catch (Exception e) { e.printStackTrace(); } } - for(Shop shop : shops) - shop.saveDataShop(); + if(shutDown && saveEmptyShops) { + for(Shop shop : shops) + if(shop.saveDataShopEmpty()) { + ItemStack air = new ItemStack(Material.AIR, 0); + shop.getRows()[0] = new RowStore(air, air, air, air, false); + shop.saveEmptyShops(); + } + } + else { + for(Shop shop : shops) + shop.saveDataShop(); + } } public boolean hasItems() { @@ -546,6 +893,30 @@ private void saveDataShop() { row.saveData(idTienda); } + private boolean saveDataShopEmpty() { + boolean isEmpty = true; + for(RowStore row : rows) + if(row != null) { + row.saveData(idTienda); + if(isEmpty) + isEmpty = false; + } + return isEmpty; + } + + private void saveEmptyShops() { + RowStore row = rows[0]; + row.saveData(idTienda); + } + + public static void removeEmptyShopTrade() { + for(Shop shop : shops) { + Optional row = shop.getRow(0); + if(row.get().getItemIn().getType().isAir() && row.get().getItemIn2().getType().isAir() && row.get().getItemOut().getType().isAir() && row.get().getItemOut2().getType().isAir()) + shop.delete(0); + } + } + public void buy(Player player, int index) { Optional row = getRow(index); if(!row.isPresent()) @@ -724,7 +1095,11 @@ public boolean hasExpired() { public void giveItem(ItemStack item) { ItemStack copy = item.clone(); - int max = iShop.config.getInt("stockPages"); + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; for(int i=0; i stock = StockShop.getStockShopByOwner(this.owner, i); if(!stock.isPresent()) @@ -740,7 +1115,11 @@ public void giveItem(ItemStack item) { public void takeItem(ItemStack item) { ItemStack copy = item.clone(); - int max = iShop.config.getInt("stockPages"); + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; for(int i=0; i stock = StockShop.getStockShopByOwner(this.owner, i); if(!stock.isPresent()) @@ -754,7 +1133,7 @@ public void takeItem(ItemStack item) { InvStock.getInvStock(this.owner).refreshItems(); } - public void delete(Player player, int index) { + public void delete(int index) { rows[index] = null; } public void deleteShop() { @@ -788,6 +1167,34 @@ public void deleteShop(boolean removalOfArray) { }); } + public static void moveShop(Location oldLoc, Location newLoc, Player player, int shopID) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + PreparedStatement stmt = null; + try { + stmt = iShop.getConnection().prepareStatement("UPDATE zooMercaTiendas SET location = ? WHERE location = ?;"); + String oldLocationRaw = oldLoc.getBlockX()+";"+oldLoc.getBlockY()+";"+oldLoc.getBlockZ()+";"+oldLoc.getWorld().getName(); + String newLocationRaw = newLoc.getBlockX()+";"+newLoc.getBlockY()+";"+newLoc.getBlockZ()+";"+newLoc.getWorld().getName(); + stmt.setString(1, newLocationRaw); + stmt.setString(2, oldLocationRaw); + stmt.executeUpdate(); + Optional newShopLoc = Shop.getShopById(shopID); + newShopLoc.get().location.setX(newLoc.getX()); + newShopLoc.get().location.setY(newLoc.getY()); + newShopLoc.get().location.setZ(newLoc.getZ()); + newShopLoc.get().location.setWorld(newLoc.getWorld()); + } catch (Exception e) { e.printStackTrace(); } + finally { + try { + if(stmt != null) + stmt.close(); + } catch (Exception e) { e.printStackTrace(); } + } + player.sendMessage(Messages.SHOP_MOVED.toString().replaceAll("%id", String.valueOf(shopID))); + }); + if(deletePlayerShop) + Bukkit.getScheduler().runTask(iShop.getPlugin(), () -> oldLoc.getBlock().setType(Material.AIR)); + } + public void sendShopMessages(String i1, String i2, String o1, String o2, int inA1, int inA2, int outA1, int outA2, UUID shopOwner, Player player, boolean isAdminShop, boolean rowBroadcast) { OfflinePlayer ownerPlayer = Bukkit.getOfflinePlayer(shopOwner); if(!isAdminShop) { @@ -1069,6 +1476,57 @@ public void outOfStockItem(Player ownerPlayer, String itemString) { } } + public static boolean hasDuplicateTrades(ItemStack out1, ItemStack out2, ItemStack in1, ItemStack in2, int shopId) { + Optional shop = getShopById(shopId); + for(RowStore row:shop.get().getRows()) { + if(row != null) { + boolean row1, row2, row3, row4; + if(row.getItemIn().equals(in1) || (row.getItemIn().getType().isAir() && in1.getType().isAir())) + row1 = true; + else continue; + if(row.getItemIn2().equals(in2) || (row.getItemIn2().getType().isAir() && in2.getType().isAir())) + row2 = true; + else continue; + if(row.getItemOut().equals(out1) || (row.getItemOut().getType().isAir() && out1.getType().isAir())) + row3 = true; + else continue; + if(row.getItemOut2().equals(out2) || (row.getItemOut2().getType().isAir() && out2.getType().isAir())) + row4 = true; + else continue; + if(row1 && row2 && row3 && row4) + return true; + } + } + return false; + } + + public static boolean hasAnyDuplicateTrades(ItemStack out1, ItemStack out2, ItemStack in1, ItemStack in2, UUID shopOwner) { + for(Shop shop:shops) { + if(shop.isOwner(shopOwner) && !shop.isAdmin()) { + for(RowStore row:shop.getRows()) { + if(row != null) { + boolean row1, row2, row3, row4; + if(row.getItemIn().equals(in1) || (row.getItemIn().getType().isAir() && in1.getType().isAir())) + row1 = true; + else continue; + if(row.getItemIn2().equals(in2) || (row.getItemIn2().getType().isAir() && in2.getType().isAir())) + row2 = true; + else continue; + if(row.getItemOut().equals(out1) || (row.getItemOut().getType().isAir() && out1.getType().isAir())) + row3 = true; + else continue; + if(row.getItemOut2().equals(out2) || (row.getItemOut2().getType().isAir() && out2.getType().isAir())) + row4 = true; + else continue; + if(row1 && row2 && row3 && row4) + return true; + } + } + } + } + return false; + } + public Optional getRow(int index) { if(index < 0 || index > 4) return Optional.empty(); diff --git a/src/com/minedhype/ishop/StockShop.java b/src/com/minedhype/ishop/StockShop.java index 5a63e69..014804d 100644 --- a/src/com/minedhype/ishop/StockShop.java +++ b/src/com/minedhype/ishop/StockShop.java @@ -8,11 +8,7 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.Inventory; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import org.bukkit.inventory.ItemStack; public class StockShop { private static final List stocks = new ArrayList<>(); @@ -54,19 +50,9 @@ public static void saveData() { private void saveStockData() { PreparedStatement stmt = null; try { - stmt = iShop.getConnection().prepareStatement("INSERT INTO zooMercaStocks (owner, items, pag) VALUES (?,?,?);"); - JsonArray items = new JsonArray(); - for(ItemStack item : inventory.getContents()) { - if(item == null) - continue; - YamlConfiguration config = new YamlConfiguration(); - item.serialize().forEach(config::set); - String itemRaw = config.saveToString(); - items.add(itemRaw); - } - String itemsJson = (new Gson()).toJson(items); + stmt = iShop.getConnection().prepareStatement("INSERT INTO zooMercaStocks (owner, itemsNew, pag) VALUES (?,?,?);"); stmt.setString(1, owner.toString()); - stmt.setString(2, itemsJson); + stmt.setBytes(2,iShop.encodeByte(inventory.getContents())); stmt.setInt(3, pag); stmt.execute(); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/com/minedhype/ishop/TabComplete.java b/src/com/minedhype/ishop/TabComplete.java new file mode 100644 index 0000000..9b7688b --- /dev/null +++ b/src/com/minedhype/ishop/TabComplete.java @@ -0,0 +1,37 @@ +package com.minedhype.ishop; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.util.StringUtil; + +public class TabComplete implements TabCompleter { + + private static final List items = Arrays.stream(Material.values()).filter(Material::isItem).map(material -> material.getKey().getKey()).toList(); + private static final List shopCommands = Arrays.asList("adminshop","copy","count","create","createshop","createlocation","delete","deleteid","deletelocation","find","findbook","list","listadmin","manage","managestock","move","out","reload","removeallshops","shops","sold","stock","view"); + public static final List enchantments = Arrays.asList("aqua_affinity","bane_of_arthropods","binding_curse","blast_protection","breach","channeling","curse_of_binding","curse_of_vanishing","density","depth_strider","efficiency","feather_falling","fire_aspect","fire_protection","flame","fortune","frost_walker","impaling","infinity","knockback","looting","loyalty","luck_of_the_sea","lure","mending","multishot","piercing","power","projectile_protection","protection","punch","quick_charge","respiration","riptide","sharpness","silk_touch","smite","soul_speed","sweeping_edge","swift_sneak","thorns","unbreaking","vanishing_curse","wind_burst"); + + @Override + public List onTabComplete(CommandSender sender, Command cmd, String label, String[] args) { + if(args[0].equalsIgnoreCase("find") || args[0].equalsIgnoreCase("count")) { + if(args.length == 2) + return StringUtil.copyPartialMatches(args[1].toLowerCase(), items, new ArrayList<>()); + return Collections.emptyList(); + } + else if(args[0].equalsIgnoreCase("findbook")) { + if(args.length == 2) + return StringUtil.copyPartialMatches(args[1].toUpperCase(), enchantments, new ArrayList<>()); + return Collections.emptyList(); + } + else { + if(args.length < 2) + return StringUtil.copyPartialMatches(args[0].toLowerCase(), shopCommands, new ArrayList<>()); + return Collections.emptyList(); + } + } +} \ No newline at end of file diff --git a/src/com/minedhype/ishop/Utils.java b/src/com/minedhype/ishop/Utils.java index 1935905..221263d 100644 --- a/src/com/minedhype/ishop/Utils.java +++ b/src/com/minedhype/ishop/Utils.java @@ -4,18 +4,28 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import com.minedhype.ishop.inventories.InvAdminShop; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; public class Utils { public static boolean hasStock(Player player, ItemStack item) { if(item == null || item.getType().equals(Material.AIR)) return true; - return player.getInventory().containsAtLeast(item, item.getAmount()); + if(item.hasItemMeta()) { + ItemStack itemClone = item.clone(); + return (player.getInventory().containsAtLeast(item, item.getAmount()) || player.getInventory().containsAtLeast(itemClone, itemClone.getAmount())); + } else + return player.getInventory().containsAtLeast(item, item.getAmount()); } public static boolean hasStock(Shop shop, ItemStack item) { if(shop.isAdmin() || item == null || item.getType().equals(Material.AIR)) return true; - int max = iShop.config.getInt("stockPages"); + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; int amount = item.getAmount(); int itemAmountCount = 0; for(int i=0; i= amount) return true; } @@ -40,7 +64,21 @@ public static boolean hasDoubleItemStock(Player player, ItemStack item, ItemStac if((item == null && item2 == null) || (item.getType().equals(Material.AIR) && item2.getType().equals(Material.AIR))) return true; int bothAmounts = item.getAmount() + item2.getAmount(); - return player.getInventory().containsAtLeast(item, bothAmounts); + if(!item.hasItemMeta() && !item2.hasItemMeta()) + return player.getInventory().containsAtLeast(item, bothAmounts); + else { + boolean hasItems = false; + boolean hasItems2 = false; + if(item.hasItemMeta()) { + ItemStack itemClone = item.clone(); + hasItems = player.getInventory().containsAtLeast(itemClone, bothAmounts); + } + if(item2.hasItemMeta()) { + ItemStack item2Clone = item2.clone(); + hasItems2 = player.getInventory().containsAtLeast(item2Clone, bothAmounts); + } + return (player.getInventory().containsAtLeast(item, bothAmounts) || player.getInventory().containsAtLeast(item2, bothAmounts) || hasItems || hasItems2); + } } public static boolean hasDoubleItemStock(Shop shop, ItemStack item, ItemStack item2) { @@ -50,23 +88,39 @@ public static boolean hasDoubleItemStock(Shop shop, ItemStack item, ItemStack it int item2Amount = 0; int item1Total = item.getAmount(); int item2Total = item2.getAmount(); - int max = iShop.config.getInt("stockPages"); + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; for(int i=0; i stockStore = StockShop.getStockShopByOwner(shop.getOwner(), i); if(!stockStore.isPresent()) continue; if(stockStore.get().getInventory().contains(item.getType()) || stockStore.get().getInventory().contains(item2.getType())) { - for(int j=0; j item1Total && item.isSimilar(item2)) { - int difference = item1Amount - item1Total; - item2Amount += difference; - } + if(!item.hasItemMeta() && !item2.hasItemMeta()) { + if(item1Amount < item1Total && stockStore.get().getInventory().getItem(j).isSimilar(item)) { + item1Amount += stockStore.get().getInventory().getItem(j).getAmount(); + if(item1Amount > item1Total && item.isSimilar(item2)) { + int difference = item1Amount - item1Total; + item2Amount += difference; + } + } else if(item2Amount < item2Total && stockStore.get().getInventory().getItem(j).isSimilar(item2)) + item2Amount += stockStore.get().getInventory().getItem(j).getAmount(); + } else { + ItemStack itemClone = item.clone(); + ItemStack item2Clone = item2.clone(); + if(item1Amount < item1Total && (stockStore.get().getInventory().getItem(j).isSimilar(item) || stockStore.get().getInventory().getItem(j).isSimilar(itemClone))) { + item1Amount += stockStore.get().getInventory().getItem(j).getAmount(); + if(item1Amount > item1Total && (item.isSimilar(item2) || item.isSimilar(item2Clone) || itemClone.isSimilar(item2) || itemClone.isSimilar(item2Clone))) { + int difference = item1Amount - item1Total; + item2Amount += difference; + } + } else if(item2Amount < item2Total && (stockStore.get().getInventory().getItem(j).isSimilar(item2) || stockStore.get().getInventory().getItem(j).isSimilar(item2Clone))) + item2Amount += stockStore.get().getInventory().getItem(j).getAmount(); } - else if(item2Amount < item2Total && stockStore.get().getInventory().getItem(j).isSimilar(item2)) - item2Amount += stockStore.get().getInventory().getItem(j).getAmount(); } if(item1Amount >= item1Total && item2Amount >= item2Total) return true; @@ -75,4 +129,37 @@ else if(item2Amount < item2Total && stockStore.get().getInventory().getItem(j).i } return false; } + + public static boolean hasEnchantment(Shop shop, String bookName, boolean doubleBook) { + if(shop.isAdmin()) + return true; + int max; + if(InvAdminShop.usePerms) + max = InvAdminShop.permissionMax; + else + max = InvAdminShop.maxPages; + int count = 0; + for(int i=0; i stockStore = StockShop.getStockShopByOwner(shop.getOwner(), i); + if(!stockStore.isPresent()) + continue; + if(stockStore.get().getInventory().contains(Material.ENCHANTED_BOOK)) { + for(int j=0; j1) + return true; + } + else + return true; + } + } + } + } + } + return false; + } } diff --git a/src/com/minedhype/ishop/iShop.java b/src/com/minedhype/ishop/iShop.java index fc49b47..616eff5 100644 --- a/src/com/minedhype/ishop/iShop.java +++ b/src/com/minedhype/ishop/iShop.java @@ -1,7 +1,9 @@ package com.minedhype.ishop; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -12,21 +14,31 @@ import java.util.Optional; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; import com.minedhype.ishop.gui.GUIEvent; import com.minedhype.ishop.MetricsLite; import net.milkbowl.vault.economy.Economy; import org.bukkit.scheduler.BukkitTask; +import me.ryanhamshire.GriefPrevention.GriefPrevention; +import me.angeschossen.lands.api.LandsIntegration; public class iShop extends JavaPlugin { File configFile; public static FileConfiguration config; public static WorldGuardLoader wgLoader = null; + public static GriefPrevention gpLoader = null; + public static LandsIntegration lands = null; + public static boolean superiorSkyblock2Check; + public static boolean townyCheck; private static BukkitTask expiredTask, saveTask, tickTask; private static Connection connection = null; private static Economy economy = null; @@ -34,9 +46,25 @@ public class iShop extends JavaPlugin { @Override public void onLoad() { + Plugin gpCheck = Bukkit.getPluginManager().getPlugin("GriefPrevention"); + if(gpCheck != null) + gpLoader = (GriefPrevention)gpCheck; Plugin wgCheck = Bukkit.getPluginManager().getPlugin("WorldGuard"); if(wgCheck != null) wgLoader = new WorldGuardLoader(); + Plugin landsCheck = Bukkit.getPluginManager().getPlugin("Lands"); + if(landsCheck != null) + lands = LandsIntegration.of(iShop.getPlugin()); + Plugin superiorSkyblock2Enabled = Bukkit.getPluginManager().getPlugin("SuperiorSkyblock2"); + if(superiorSkyblock2Enabled != null) + superiorSkyblock2Check = true; + else + superiorSkyblock2Check = false; + Plugin townyEnabled = Bukkit.getPluginManager().getPlugin("Towny"); + if(townyEnabled != null) + townyCheck = true; + else + townyCheck = false; } @Override @@ -55,7 +83,13 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new EventShop(), this); getServer().getPluginManager().registerEvents(new GUIEvent(), this); getCommand("ishop").setExecutor(new CommandShop()); + getCommand("ishop").setTabCompleter(new TabComplete()); + try { + connection = DriverManager.getConnection(chainConnect); + this.createTables(); + } catch(Exception e) { e.printStackTrace(); } int delayTime; + int saveDatabaseTime; try { delayTime = config.getInt("shopsDatabaseLoadDelay"); } catch(Exception e) { delayTime = 0; } @@ -63,17 +97,28 @@ public void onEnable() { delayTime = 1; else delayTime*=20; + try { + saveDatabaseTime = config.getInt("saveDatabase"); + } catch(Exception e) { saveDatabaseTime = 15; } + if(saveDatabaseTime < 5) + saveDatabaseTime = 5; + (saveDatabaseTime)*=60; + (saveDatabaseTime)*=20; Bukkit.getScheduler().runTaskLater(this, () -> { try { - connection = DriverManager.getConnection(chainConnect); - this.createTables(); Shop.loadData(); } catch(Exception e) { e.printStackTrace(); } }, delayTime); - expiredTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, Shop::expiredShops, delayTime+20, 20000); - saveTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, Shop::saveData, delayTime+1200, 6000); - tickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, Shop::tickShops, delayTime+150, 50); - Bukkit.getScheduler().runTaskLaterAsynchronously(this, Shop::getPlayersShopList, delayTime+100); + expiredTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, Shop::expiredShops, delayTime+9, 20000); + saveTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> { + try { + Shop.saveData(false); + } catch (Exception e) { Bukkit.getConsoleSender().sendMessage(ChatColor.YELLOW + "[iShop] Warning: Tried saving to database while being modified at the same time. Saving will continue and try again later, but will also save to database safely upon server shutdown."); } + }, delayTime+1200, saveDatabaseTime); + if(Shop.shopEnabled && Shop.particleEffects) + tickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this, Shop::tickShops, delayTime+250, 50); + Bukkit.getScheduler().runTaskLaterAsynchronously(this, Shop::getPlayersShopList, delayTime+160); + Bukkit.getScheduler().runTaskLaterAsynchronously(this, Shop::removeEmptyShopTrade, delayTime+100); MetricsLite metrics = new MetricsLite(this, 9189); new UpdateChecker(this, 84555).getVersion(version -> { if(!this.getDescription().getVersion().equalsIgnoreCase(version)) @@ -83,17 +128,39 @@ public void onEnable() { @Override public void onDisable() { - tickTask.cancel(); - expiredTask.cancel(); + EventShop.shuttingDown = true; + for(Player player:Bukkit.getServer().getOnlinePlayers()) + player.closeInventory(); + if(Bukkit.getScheduler().isCurrentlyRunning(tickTask.getTaskId())) { + while(Bukkit.getScheduler().isCurrentlyRunning(tickTask.getTaskId())) + ; + tickTask.cancel(); + } + else + tickTask.cancel(); if(Bukkit.getScheduler().isCurrentlyRunning(saveTask.getTaskId())) { while(Bukkit.getScheduler().isCurrentlyRunning(saveTask.getTaskId())) ; saveTask.cancel(); } - else { + else saveTask.cancel(); - Shop.saveData(); + if(Bukkit.getScheduler().isCurrentlyRunning(expiredTask.getTaskId())) { + while(Bukkit.getScheduler().isCurrentlyRunning(expiredTask.getTaskId())) + ; + expiredTask.cancel(); } + else + expiredTask.cancel(); + if(!tickTask.isCancelled()) + tickTask.cancel(); + if(!saveTask.isCancelled()) + saveTask.cancel(); + if(!expiredTask.isCancelled()) + expiredTask.cancel(); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + "[iShop] Safely saving shops & stock items to database, please wait & do not kill server process..."); + Shop.saveData(true); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + "[iShop] Saving complete!"); if(connection != null) { try { connection.close(); @@ -108,8 +175,8 @@ private void createTables() { try { stmts = new PreparedStatement[] { connection.prepareStatement("CREATE TABLE IF NOT EXISTS zooMercaTiendas(id INTEGER PRIMARY KEY autoincrement, location varchar(64), owner varchar(64));"), - connection.prepareStatement("CREATE TABLE IF NOT EXISTS zooMercaTiendasFilas(itemIn text, itemOut text, idTienda INTEGER);"), - connection.prepareStatement("CREATE TABLE IF NOT EXISTS zooMercaStocks(owner varchar(64), items JSON);") + connection.prepareStatement("CREATE TABLE IF NOT EXISTS zooMercaTiendasFilas(itemInNew blob, itemIn2New blob, itemOutNew blob, itemOut2New blob, idTienda INTEGER);"), + connection.prepareStatement("CREATE TABLE IF NOT EXISTS zooMercaStocks(owner varchar(64), itemsNew blob);") }; } catch(Exception e) { e.printStackTrace(); } for(PreparedStatement stmt : stmts) { @@ -120,20 +187,77 @@ private void createTables() { } List stmtsPatches = new ArrayList<>(); try { - stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemIn2 text NULL DEFAULT 'v: 2580\ntype: AIR\namount: 0' ")); - stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemOut2 text NULL DEFAULT 'v: 2580\ntype: AIR\namount: 0' ")); - stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN broadcast BOOLEAN DEFAULT 0")); - stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaStocks ADD COLUMN pag INTEGER DEFAULT 0")); + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemInNew blob;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemIn2New blob;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemOutNew blob;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN itemOut2New blob;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas ADD COLUMN broadcast BOOLEAN DEFAULT 0;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaStocks ADD COLUMN pag INTEGER DEFAULT 0;")); + } catch(Exception ignored) { } + try { + stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaStocks ADD COLUMN itemsNew blob;")); + } catch(Exception ignored) { } + try { stmtsPatches.add(connection.prepareStatement("ALTER TABLE zooMercaTiendas ADD COLUMN admin BOOLEAN DEFAULT FALSE;")); } catch(Exception ignored) { } for(PreparedStatement stmtsPatch : stmtsPatches) { try { stmtsPatch.execute(); stmtsPatch.close(); - } catch (Exception ignored) { } + } catch(Exception ignored) { } + } + } + + public static void dropOldColumns() { + PreparedStatement[] stmts = new PreparedStatement[] { }; + try { + stmts = new PreparedStatement[] { + connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas DROP COLUMN itemIn;"), + connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas DROP COLUMN itemIn2;"), + connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas DROP COLUMN itemOut;"), + connection.prepareStatement("ALTER TABLE zooMercaTiendasFilas DROP COLUMN itemOut2;"), + connection.prepareStatement("ALTER TABLE zooMercaStocks DROP COLUMN items;") + }; + } catch(Exception e) { e.printStackTrace(); } + for(PreparedStatement stmt : stmts) { + try { + stmt.execute(); + stmt.close(); + } catch(Exception e) { e.printStackTrace(); } } } + public static ItemStack[] decodeByte(InputStream inputStream) throws IOException, ClassNotFoundException { + if(inputStream == null || inputStream.available() == 0) + return new ItemStack[0]; + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + ItemStack[] items = new ItemStack[dataInput.readInt()]; + for(int i=0; i exemptExpiredShops = Arrays.asList("00000000-0000-0000-0000-000000000000"); config.set("exemptExpiringShops", exemptExpiredShops); config.set("outsideRegion", "&cCannot create shop outside of ishop region!"); - config.set("configVersion", "3.1"); - config.save(configFile); case "3.1": + config.set("strictStock", false); + case "3.2": + config.set("noClaimPermission", "&cYou do not have permission in this claim to create a shop!"); + config.set("pageSkipAhead", "5 Pages >>"); + config.set("pageSkipPrev", "<< 5 Pages"); + case "3.3": + config.set("maxStockPages", 10); + config.set("removedAllPlayer", "&6Removed&c %shops &6shop(s) for player:&c %p"); + case "3.4": + config.set("shopCreatedLoc", "&7Shop has been &aCREATED&7 for&a %p &7at &a%x &7/&a %y &7/&a %z &7in &a%w&7!"); + config.set("shopDeletedLoc", "&7Shop has been &cDELETED&7 for&a %p &7at &a%x &7/&a %y &7/&a %z &7in &a%w&7!"); + config.set("shopLocationErrorNum", "&cLocation coordinates must be a positive or negative number!"); + config.set("shopLocationErrorWorld", "&cLocation coordinates must be in a valid world!"); + case "3.5": + config.set("preventDuplicates", true); + config.set("preventAllDuplicates", false); + config.set("saveEmptyShops", true); + case "3.6": + config.set("saveDatabase", 15); + case "3.7": + config.set("skipPermsCheckForAdminCreateShop", true); + config.set("noPermissionToCreateShop", "&cYou do not have permission to create a shop at this location!"); + case "3.8": + config.set("publicFindCommand", true); + config.set("findCommandCooldown", 5); + config.set("publicMoveCommand", true); + config.set("cooldownMessageFind","&6You must wait &c%time second(s) &6before using find command again!"); + config.set("findError", "&cGiven item to search shops for does not exist!"); + config.set("listFind", "&6Listing all found shop(s) trading &a%item&6:"); + config.set("nolistFind", "&cNo shop(s) have been found!"); + config.set("shopMoved", "&6Shop &a#%id &6has been moved to new targeted location!"); + case "3.9": + config.set("location", "&6Shop&a %id &6location XYZ:&a %x &6/&a %y &6/&a %z &6in&a %world"); + case "3.10": + config.set("shopParticles", "villager_happy"); + config.set("configVersion", "3.11"); + config.save(configFile); + case "3.11": break; } } catch(IOException | InvalidConfigurationException e) { e.printStackTrace(); } diff --git a/src/com/minedhype/ishop/inventories/InvAdminShop.java b/src/com/minedhype/ishop/inventories/InvAdminShop.java index 3caa95a..615a98c 100644 --- a/src/com/minedhype/ishop/inventories/InvAdminShop.java +++ b/src/com/minedhype/ishop/inventories/InvAdminShop.java @@ -3,6 +3,7 @@ import java.util.Optional; import com.minedhype.ishop.iShop; import com.minedhype.ishop.Messages; +import com.minedhype.ishop.Permission; import com.minedhype.ishop.RowStore; import com.minedhype.ishop.Shop; import com.minedhype.ishop.Utils; @@ -17,6 +18,9 @@ public class InvAdminShop extends GUI { public static boolean remoteManage = iShop.config.getBoolean("remoteManage"); public static boolean stockGUIShop = iShop.config.getBoolean("enableStockAccessFromShopGUI"); public static boolean stockCommandEnabled = iShop.config.getBoolean("enableStockCommand"); + public static boolean usePerms = iShop.config.getBoolean("usePermissions"); + public static int maxPages = iShop.config.getInt("stockPages"); + public static int permissionMax = iShop.config.getInt("maxStockPages"); private final Shop shop; public InvAdminShop(Shop shop, Player player) { @@ -76,7 +80,7 @@ private void updateItems(Player player) { final int index = y-1; if(row.isPresent()) { placeItem(y*9+x, GUI.createItem(Material.TNT, ChatColor.BOLD+ Messages.SHOP_TITLE_DELETE.toString()), p -> { - shop.delete(p, index); + shop.delete(index); InvAdminShop inv = new InvAdminShop(shop, p.getPlayer()); inv.open(p); }); @@ -91,6 +95,21 @@ private void updateItems(Player player) { placeItem(y * 9 + x, GUI.createItem(Material.CHEST, Messages.SHOP_TITLE_STOCK.toString()), p -> { p.closeInventory(); InvStock inv = InvStock.getInvStock(player.getUniqueId()); + int maxStockPages = maxPages; + if(usePerms) { + String permPrefix = Permission.SHOP_STOCK_PREFIX.toString(); + int maxPermPages = InvAdminShop.permissionMax; + boolean permissionFound = false; + for(int i=maxPermPages; i>0; i--) + if(player.hasPermission(permPrefix + i)) { + maxStockPages = i; + permissionFound = true; + break; + } + if(!permissionFound) + maxStockPages = maxPermPages; + } + inv.setMaxPages(maxStockPages); inv.setPag(0); InvStock.inShopInv.put(player, player.getUniqueId()); inv.open(player); diff --git a/src/com/minedhype/ishop/inventories/InvCreateRow.java b/src/com/minedhype/ishop/inventories/InvCreateRow.java index 4b6c647..e6db1b6 100644 --- a/src/com/minedhype/ishop/inventories/InvCreateRow.java +++ b/src/com/minedhype/ishop/inventories/InvCreateRow.java @@ -9,8 +9,9 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import com.minedhype.ishop.RowStore; import com.minedhype.ishop.Messages; +import com.minedhype.ishop.Permission; +import com.minedhype.ishop.RowStore; import com.minedhype.ishop.Shop; import com.minedhype.ishop.iShop; import com.minedhype.ishop.gui.GUI; @@ -25,6 +26,9 @@ public class InvCreateRow extends GUI { private ItemStack itemOut2; private final ItemStack airItem = new ItemStack(Material.AIR, 0); public static Boolean itemsDisabled = iShop.config.getBoolean("disabledItems"); + public static Boolean preventDupeTrades = iShop.config.getBoolean("preventDuplicates"); + public static Boolean preventAllDupeTrades = iShop.config.getBoolean("preventAllDuplicates"); + public static Boolean strictStock = iShop.config.getBoolean("strictStock"); public static List disabledItemList = iShop.config.getStringList("disabledItemsList"); public InvCreateRow(Shop shop, int index) { @@ -53,14 +57,24 @@ else if(i == 13) { return; if((itemOut == airItem && itemOut2 == airItem) || (itemIn == airItem && itemIn2 == airItem)) return; + ItemStack in1 = itemIn.clone(); + ItemStack in2 = itemIn2.clone(); + ItemStack out1 = itemOut.clone(); + ItemStack out2 = itemOut2.clone(); + if(!p.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(preventAllDupeTrades) { + if(Shop.hasAnyDuplicateTrades(out1, out2, in1, in2, p.getUniqueId())) + return; + } + else if(preventDupeTrades) { + if(Shop.hasDuplicateTrades(out1, out2, in1, in2, shop.shopId())) + return; + } + } if(itemsDisabled) { for(String itemsList:disabledItemList) { Material disabledItemsList = Material.matchMaterial(itemsList); if(disabledItemsList != null) { - ItemStack in1 = itemIn.clone(); - ItemStack in2 = itemIn2.clone(); - ItemStack out1 = itemOut.clone(); - ItemStack out2 = itemOut2.clone(); if(in1.getType().equals(disabledItemsList) || in2.getType().equals(disabledItemsList) || out1.getType().equals(disabledItemsList) || out2.getType().equals(disabledItemsList)) return; if(in1.getType().toString().contains("SHULKER_BOX") && in1.getItemMeta() instanceof BlockStateMeta) { @@ -130,7 +144,7 @@ else if(out2.getType().equals(Material.BUNDLE)) { } } } - shop.getRows()[index] = new RowStore(itemOut, itemOut2, itemIn, itemIn2, false); + shop.getRows()[index] = new RowStore(out1, out2, in1, in2, false); InvAdminShop inv = new InvAdminShop(shop, p.getPlayer()); inv.open(p); }); @@ -158,7 +172,7 @@ public void onClick(InventoryClickEvent event) { if(inv.getType().equals(InventoryType.CHEST) && event.getView().getTitle().contains(Messages.SHOP_TITLE_CREATESHOP.toString())) { event.setCancelled(true); if(event.getRawSlot() == 10 || event.getRawSlot() == 11 || event.getRawSlot() == 15 || event.getRawSlot() == 16) { - ItemStack item = event.getCursor().clone(); + ItemStack item = event.getCursor().clone(); if(event.getClick().isRightClick()) item.setAmount(1); placeItem(event.getRawSlot(), item); diff --git a/src/com/minedhype/ishop/inventories/InvShopList.java b/src/com/minedhype/ishop/inventories/InvShopList.java index de5d53c..bcac599 100644 --- a/src/com/minedhype/ishop/inventories/InvShopList.java +++ b/src/com/minedhype/ishop/inventories/InvShopList.java @@ -77,9 +77,14 @@ private static void getShopList(UUID uuid) { ItemStack item = new ItemStack(playerHead); SkullMeta skullMeta = (SkullMeta) item.getItemMeta(); OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(Shop.shopList.get(id)); - skullMeta.setOwningPlayer(offlinePlayer); + boolean playerNotFound = false; + try { + skullMeta.setOwningPlayer(offlinePlayer); } + catch(Exception e) { playerNotFound = true; } if(Shop.getShopById(id).get().isAdmin()) skullMeta.setDisplayName(Messages.ADMIN_SHOP_NUMBER.toString().replaceAll("%id", id.toString())); + else if(playerNotFound) + skullMeta.setDisplayName(Messages.SHOP_NUMBER.toString().replaceAll("%player", "Unknown Player").replaceAll("%id", id.toString())); else skullMeta.setDisplayName(Messages.SHOP_NUMBER.toString().replaceAll("%player", offlinePlayer.getName()).replaceAll("%id", id.toString())); List skullLore = new ArrayList<>(); @@ -105,7 +110,7 @@ public void open(Player player) { shopslist.clear(); final UUID playerUUID = player.getUniqueId(); final Player openPlayer = player; - Bukkit.getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> { + Bukkit.getScheduler().runTaskAsynchronously(iShop.getPlugin(), () -> { getShopList(playerUUID); Bukkit.getScheduler().runTask(iShop.getPlugin(), () -> { PlayerShopList(); diff --git a/src/com/minedhype/ishop/inventories/InvStock.java b/src/com/minedhype/ishop/inventories/InvStock.java index f386104..9ae2937 100644 --- a/src/com/minedhype/ishop/inventories/InvStock.java +++ b/src/com/minedhype/ishop/inventories/InvStock.java @@ -5,6 +5,11 @@ import java.util.Optional; import java.util.UUID; import java.util.HashMap; +import com.minedhype.ishop.Messages; +import com.minedhype.ishop.Permission; +import com.minedhype.ishop.Shop; +import com.minedhype.ishop.StockShop; +import com.minedhype.ishop.gui.GUI; import org.bukkit.Material; import org.bukkit.block.ShulkerBox; import org.bukkit.entity.Player; @@ -12,10 +17,6 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import com.minedhype.ishop.Messages; -import com.minedhype.ishop.StockShop; -import com.minedhype.ishop.iShop; -import com.minedhype.ishop.gui.GUI; import org.bukkit.inventory.meta.BlockStateMeta; import org.bukkit.inventory.meta.BundleMeta; @@ -26,6 +27,8 @@ public class InvStock extends GUI { private final ItemStack airItem = new ItemStack(Material.AIR, 0); private final UUID owner; private int pag; + private int stockPages; + private Player player; private InvStock(UUID owner) { super(54, Messages.SHOP_TITLE_STOCK.toString()); @@ -41,51 +44,59 @@ public void onClick(InventoryClickEvent event) { super.onClick(event); if(event.getRawSlot() >= 45 && event.getRawSlot() < 54) return; - if(InvCreateRow.itemsDisabled && event.getRawSlot() >= 54) { - ItemStack item = event.getCurrentItem(); - ItemStack item2 = event.getCursor(); - for(String itemsList:InvCreateRow.disabledItemList) { - Material disabledItemsList = Material.matchMaterial(itemsList); - if(item == null) - item = airItem; - if(item2 == null) - item2 = airItem; - if(disabledItemsList != null) { - if(!item.isSimilar(airItem)) { - if(item.getType().equals(disabledItemsList)) - return; - if(item.getType().toString().contains("SHULKER_BOX") && item.getItemMeta() instanceof BlockStateMeta) { - BlockStateMeta itemMeta1 = (BlockStateMeta) item.getItemMeta(); - ShulkerBox shulkerBox1 = (ShulkerBox) itemMeta1.getBlockState(); - if(shulkerBox1.getInventory().contains(disabledItemsList)) + if(event.getRawSlot() >= 54 && !player.hasPermission(Permission.SHOP_ADMIN.toString())) { + if(InvCreateRow.strictStock) { + ItemStack item = event.getCurrentItem(); + ItemStack item2 = event.getCursor(); + if(Shop.strictStockShopCheck(item, owner) || Shop.strictStockShopCheck(item2, owner)) + return; + } + if(InvCreateRow.itemsDisabled) { + ItemStack item = event.getCurrentItem(); + ItemStack item2 = event.getCursor(); + for(String itemsList:InvCreateRow.disabledItemList) { + Material disabledItemsList = Material.matchMaterial(itemsList); + if(item == null) + item = airItem; + if(item2 == null) + item2 = airItem; + if(disabledItemsList != null) { + if(!item.isSimilar(airItem)) { + if(item.getType().equals(disabledItemsList)) return; - } else if(item.getType().equals(Material.BUNDLE)) { - BundleMeta bundleIn1 = (BundleMeta) item.getItemMeta(); - if(bundleIn1.hasItems()) { - ItemStack itemDisabledOut = new ItemStack(disabledItemsList); - List bundleIn1Items = bundleIn1.getItems(); - for(ItemStack bundleList : bundleIn1Items) - if(bundleList.isSimilar(itemDisabledOut)) - return; + if(item.getType().toString().contains("SHULKER_BOX") && item.getItemMeta() instanceof BlockStateMeta) { + BlockStateMeta itemMeta1 = (BlockStateMeta) item.getItemMeta(); + ShulkerBox shulkerBox1 = (ShulkerBox) itemMeta1.getBlockState(); + if(shulkerBox1.getInventory().contains(disabledItemsList)) + return; + } else if(item.getType().equals(Material.BUNDLE)) { + BundleMeta bundleIn1 = (BundleMeta) item.getItemMeta(); + if(bundleIn1.hasItems()) { + ItemStack itemDisabledOut = new ItemStack(disabledItemsList); + List bundleIn1Items = bundleIn1.getItems(); + for(ItemStack bundleList : bundleIn1Items) + if(bundleList.isSimilar(itemDisabledOut)) + return; + } } } - } - if(!item2.isSimilar(airItem)) { - if(item2.getType().equals(disabledItemsList)) - return; - if(item2.getType().toString().contains("SHULKER_BOX") && item2.getItemMeta() instanceof BlockStateMeta) { - BlockStateMeta itemMeta2 = (BlockStateMeta) item2.getItemMeta(); - ShulkerBox shulkerBox2 = (ShulkerBox) itemMeta2.getBlockState(); - if(shulkerBox2.getInventory().contains(disabledItemsList)) + if(!item2.isSimilar(airItem)) { + if(item2.getType().equals(disabledItemsList)) return; - } else if(item2.getType().equals(Material.BUNDLE)) { - BundleMeta bundleIn2 = (BundleMeta) item2.getItemMeta(); - if(bundleIn2.hasItems()) { - ItemStack itemDisabledOut = new ItemStack(disabledItemsList); - List bundleIn2Items = bundleIn2.getItems(); - for(ItemStack bundleList : bundleIn2Items) - if(bundleList.isSimilar(itemDisabledOut)) - return; + if(item2.getType().toString().contains("SHULKER_BOX") && item2.getItemMeta() instanceof BlockStateMeta) { + BlockStateMeta itemMeta2 = (BlockStateMeta) item2.getItemMeta(); + ShulkerBox shulkerBox2 = (ShulkerBox) itemMeta2.getBlockState(); + if(shulkerBox2.getInventory().contains(disabledItemsList)) + return; + } else if(item2.getType().equals(Material.BUNDLE)) { + BundleMeta bundleIn2 = (BundleMeta) item2.getItemMeta(); + if(bundleIn2.hasItems()) { + ItemStack itemDisabledOut = new ItemStack(disabledItemsList); + List bundleIn2Items = bundleIn2.getItems(); + for(ItemStack bundleList : bundleIn2Items) + if(bundleList.isSimilar(itemDisabledOut)) + return; + } } } } @@ -102,12 +113,15 @@ public void refreshItems() { Inventory inv = stock.getInventory(); for(int i=0; i<45; i++) placeItem(i, inv.getItem(i)); - for(int i=45; i<54; i++) { - if(i == 47 && pag > 0) + if(i == 46 && pag > 4 && stockPages >= 10) + placeItem(i, GUI.createItem(Material.SPECTRAL_ARROW, Messages.SHOP_PAGE_SKIPPREV.toString()), p -> openPage(p, pag-5)); + else if(i == 47 && pag > 0) placeItem(i, GUI.createItem(Material.ARROW, Messages.SHOP_PAGE + " " + (pag)), p -> openPage(p, pag-1)); - else if(i == 51 && pag < iShop.config.getInt("stockPages")-1) + else if(i == 51 && pag < stockPages-1) placeItem(i, GUI.createItem(Material.ARROW, Messages.SHOP_PAGE + " " + (pag+2)), p -> openPage(p, pag+1)); + else if(i == 52 && pag < stockPages-5 && stockPages >= 10) + placeItem(i, GUI.createItem(Material.SPECTRAL_ARROW, Messages.SHOP_PAGE_SKIPAHEAD.toString()), p -> openPage(p, pag+5)); else placeItem(i, GUI.createItem(Material.BLACK_STAINED_GLASS_PANE, "")); } @@ -123,6 +137,7 @@ private void openPage(Player player, int pag) { @Override public void open(Player player) { + this.player = player; refreshItems(); super.open(player); } @@ -139,4 +154,7 @@ public void onClose(InventoryCloseEvent event) { public void setPag(int pag) { this.pag = pag; } + public void setMaxPages(int maxPages) { + this.stockPages = maxPages; + } } diff --git a/src/resources/config.yml b/src/resources/config.yml index f2366d2..cdd2bf8 100644 --- a/src/resources/config.yml +++ b/src/resources/config.yml @@ -53,9 +53,12 @@ enableStockAccessFromShopGUI: true # Players with ishop.stock permission will bypass if disabled enableStockCommand: true -# Number of pages to have in the stock GUI +# Number of default stock pages to have in the stock GUI stockPages: 5 +# Maximum number of stock pages to have in the stock GUI if usePermissions is set to true +maxStockPages: 10 + # Enable sending of messages when players have purchased or sold item(s) from shops enableShopNotifications: true @@ -102,7 +105,7 @@ maxInactiveDays: 0 exemptExpiringShops: - 00000000-0000-0000-0000-000000000000 -# Delete block that the shop is located at when deleting a shop +# Remove block that the shop is located at when deleting or moving a shop deleteBlock: false # Show particle effects on active shop blocks @@ -157,6 +160,36 @@ stockRangeLimitFromShop: 0 # Set to true if you would like '/shop stock' command range limit to be enforced using stockRangeLimitFromShop distance stockRangeLimitUsingCommand: false +# This will only allow items that are in active shop trades to be added and stored in stock inventory +strictStock: false + +# Prevent players from creating duplicate item trades within each shop they own +preventDuplicates: true + +# Prevent players from creating duplicate item trades from any shop they own +preventAllDuplicates: false + +# Save shops with no trades to database on server shutdown +saveEmptyShops: true + +# Save shops and stock to database interval in minutes. Database will auto save upon server shutdown. Default is every 15 minutes +saveDatabase: 15 + +# When a player with iShop.admin permission uses command createshop and is not a server operator, skip checking for permission within GriefPrevention, Lands, SuperiorSkyblock2, Towny, and WorldGuard +skipPermsCheckForAdminCreateShop: true + +# Allow everyone to use "/shop find " command to search all player shops that are selling given item +publicFindCommand: true + +# Time in seconds players must wait to use find command again. Set to 0 to disable +findCommandCooldown: 5 + +# Allow everyone to use '/shop move' command to move their shops to a new location +publicMoveCommand: true + +# Change the particle effect (requires server restart) for shops to any Enum Constant Particle found at https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html +shopParticles: "villager_happy" + # Customizable Messages adminShop: "Admin Shop #%id" adminShopDisabled: "&cAdmin shops have been disabled!" @@ -172,7 +205,7 @@ deleteTitle: "DELETE" disabledShopBlock: "&cCannot create shop location when shop blocks are disabled!" existingShop: "&cCannot create shop where existing shop is already located!" foundShops: "&6Found&a %shops &6shop(s) for player:&a %p" -location: "&6Shop&a %id &6location XYZ: " +location: "&6Shop&a %id &6location XYZ:&a %x &6/&a %y &6/&a %z &6in&a %world" noItems: "&cYou do not have enough item(s) to buy from this shop!" noMoney: "&cYou do not have enough money to create a shop! You need at least &o$" noPermissions: "&cYou do not have permission for this command!" @@ -233,6 +266,19 @@ countAmount: "&aTotal amount of %item found: %amount" countEmpty: "&cCannot find any %item in stock inventory!" countError: "&cGiven item to search stock for does not exist!" outsideRegion: "&cCannot create shop outside of ishop region!" - +noClaimPermission: "&cYou do not have permission in this claim to create a shop!" +pageSkipAhead: "5 Pages >>" +pageSkipPrev: "<< 5 Pages" +removedAllPlayer: "&6Removed&c %shops &6shop(s) for player:&c %p" +shopCreatedLoc: "&7Shop has been &aCREATED&7 for&a %p &7at &a%x &7/&a %y &7/&a %z &7in &a%w&7!" +shopDeletedLoc: "&7Shop has been &cDELETED&7 for&a %p &7at &a%x &7/&a %y &7/&a %z &7in &a%w&7!" +shopLocationErrorNum: "&cLocation coordinates must be a positive or negative number!" +shopLocationErrorWorld: "&cLocation coordinates must be in a valid world!" +noPermissionToCreateShop: "&cYou do not have permission to create a shop at this location!" +cooldownMessageFind: "&6You must wait &c%time second(s) &6before using find command again!" +findError: "&cGiven item to search shops for does not exist!" +listFind: "&6Listing all found shop(s) trading &a%item&6:" +nolistFind: "&cNo shop(s) have been found!" +shopMoved: "&6Shop &a#%id &6has been moved to new targeted location!" # Do not edit this! -configVersion: 3.1 \ No newline at end of file +configVersion: 3.11 \ No newline at end of file diff --git a/src/resources/plugin.yml b/src/resources/plugin.yml index a503688..873950d 100644 --- a/src/resources/plugin.yml +++ b/src/resources/plugin.yml @@ -5,7 +5,7 @@ author: Beez0r website: https://minedhype.com version: "${project.version}" api-version: "1.17" -softdepend: [Vault, WorldGuard] +softdepend: [GriefPrevention, Lands, SuperiorSkyblock2, Towny, Vault, WorldGuard] commands: ishop: description: "/shop"