From 367873804818edb1199f3e34136f34ff43f83bb8 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 1 Aug 2018 13:35:42 +0200 Subject: [PATCH] Async shop creation (again) This time, a thread pool with a maximum pool size of 8 threads is used to execute the slow methods of shop creation. --- .../java/de/epiceric/shopchest/ShopChest.java | 18 ++++++ .../listeners/ChestProtectListener.java | 6 -- .../listeners/ShopInteractListener.java | 5 -- .../java/de/epiceric/shopchest/shop/Shop.java | 64 ++++++++++++------- .../epiceric/shopchest/utils/ShopUtils.java | 5 -- 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/main/java/de/epiceric/shopchest/ShopChest.java b/src/main/java/de/epiceric/shopchest/ShopChest.java index e490c6c..f2f2292 100644 --- a/src/main/java/de/epiceric/shopchest/ShopChest.java +++ b/src/main/java/de/epiceric/shopchest/ShopChest.java @@ -54,6 +54,10 @@ import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; public class ShopChest extends JavaPlugin { @@ -78,6 +82,7 @@ public class ShopChest extends JavaPlugin { private GriefPrevention griefPrevention; private AreaShop areaShop; private ShopUpdater updater; + private ExecutorService shopCreationThreadPool; /** * @return An instance of ShopChest @@ -186,6 +191,8 @@ public class ShopChest extends JavaPlugin { shopUtils = new ShopUtils(this); shopCommand = new ShopCommand(this); + shopCreationThreadPool = new ThreadPoolExecutor(0, 8, + 5L, TimeUnit.SECONDS, new LinkedBlockingQueue()); registerListeners(); initializeShops(); @@ -203,6 +210,10 @@ public class ShopChest extends JavaPlugin { updater.stop(); } + if (shopCreationThreadPool != null) { + shopCreationThreadPool.shutdown(); + } + if (database != null) { for (Shop shop : shopUtils.getShopsCopy()) { shopUtils.removeShop(shop, false); @@ -418,6 +429,13 @@ public class ShopChest extends JavaPlugin { } } + /** + * @return A thread pool for executing shop creation tasks + */ + public ExecutorService getShopCreationThreadPool() { + return shopCreationThreadPool; + } + public HologramFormat getHologramFormat() { return hologramFormat; } diff --git a/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java b/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java index 8c77064..e4a57d7 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java @@ -73,9 +73,6 @@ public class ChestProtectListener implements Listener { public void onResult(Void result) { newShop.create(true); shopUtils.addShop(newShop, true); - for (Player player : shop.getLocation().getWorld().getPlayers()) { - shopUtils.updateShops(player, true); - } } }); } else { @@ -271,9 +268,6 @@ public class ChestProtectListener implements Listener { newShop.create(true); shopUtils.addShop(newShop, true); plugin.debug(String.format("%s extended %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); - for (Player player : shop.getLocation().getWorld().getPlayers()) { - shopUtils.updateShops(player, true); - } } }); } else { diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java index f9eda64..8bc653c 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java @@ -769,11 +769,6 @@ public class ShopInteractListener implements Listener { } else { executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_CREATED, placeholder)); } - - // next update will display the new shop - for (Player player : location.getWorld().getPlayers()) { - plugin.getShopUtils().resetPlayerLocation(player); - } } /** diff --git a/src/main/java/de/epiceric/shopchest/shop/Shop.java b/src/main/java/de/epiceric/shopchest/shop/Shop.java index 4280c57..523ed44 100644 --- a/src/main/java/de/epiceric/shopchest/shop/Shop.java +++ b/src/main/java/de/epiceric/shopchest/shop/Shop.java @@ -19,8 +19,10 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.DoubleChest; import org.bukkit.block.data.Directional; +import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; import java.util.*; @@ -42,6 +44,7 @@ public class Shop { private boolean created; private int id; private Hologram hologram; + private Location holoLocation; private ShopItem item; public Shop(int id, ShopChest plugin, OfflinePlayer vendor, ItemStack product, Location location, double buyPrice, double sellPrice, ShopType shopType) { @@ -94,14 +97,16 @@ public class Shop { Block b = location.getBlock(); if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) { - ChestNotFoundException ex = new ChestNotFoundException(String.format("No Chest found in world '%s' at location: %d; %d; %d", b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); + ChestNotFoundException ex = new ChestNotFoundException(String.format("No Chest found in world '%s' at location: %d; %d; %d", + b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); plugin.getShopUtils().removeShop(this, Config.removeShopOnError); if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); plugin.debug("Failed to create shop (#" + id + ")"); plugin.debug(ex); return false; } else if ((b.getRelative(BlockFace.UP).getType() != Material.AIR) && Config.showShopItems) { - NotEnoughSpaceException ex = new NotEnoughSpaceException(String.format("No space above chest in world '%s' at location: %d; %d; %d", b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); + NotEnoughSpaceException ex = new NotEnoughSpaceException(String.format("No space above chest in world '%s' at location: %d; %d; %d", + b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); plugin.getShopUtils().removeShop(this, Config.removeShopOnError); if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); plugin.debug("Failed to create shop (#" + id + ")"); @@ -109,8 +114,17 @@ public class Shop { return false; } - if (hologram == null || !hologram.exists()) createHologram(); - if (item == null) createItem(); + plugin.getShopCreationThreadPool().execute(() -> { + if (hologram == null || !hologram.exists()) createHologram(); + if (item == null) createItem(); + + // Update shops for players in the same world after creation has finished + plugin.getUpdater().beforeNext(() -> { + for (Player player : location.getWorld().getPlayers()) { + plugin.getShopUtils().resetPlayerLocation(player); + } + }); + }); created = true; return true; @@ -147,7 +161,7 @@ public class Shop { Location itemLocation; ItemStack itemStack; - itemLocation = new Location(location.getWorld(), hologram.getLocation().getX(), location.getY() + 0.9, hologram.getLocation().getZ()); + itemLocation = new Location(location.getWorld(), holoLocation.getX(), location.getY() + 0.9, holoLocation.getZ()); itemStack = product.clone(); itemStack.setAmount(1); @@ -189,9 +203,14 @@ public class Shop { } String[] holoText = getHologramText(); - Location holoLocation = getHologramLocation(doubleChest, chests, face); + holoLocation = getHologramLocation(doubleChest, chests, face); - hologram = new Hologram(plugin, holoText, holoLocation); + new BukkitRunnable(){ + @Override + public void run() { + hologram = new Hologram(plugin, holoText, holoLocation); + } + }.runTask(plugin); } /** @@ -279,41 +298,40 @@ public class Shop { } private Location getHologramLocation(boolean doubleChest, Chest[] chests, BlockFace face) { - Block b = location.getBlock(); - Location holoLocation; + World w = location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); - World w = b.getWorld(); - int x = b.getX(); - int y = b.getY(); - int z = b.getZ(); + Location holoLocation = new Location(w, x, y, z); - double subtractY = 0.6; + double deltaY = -0.6; - if (Config.hologramFixedBottom) subtractY = 0.85; + if (Config.hologramFixedBottom) deltaY = -0.85; if (doubleChest) { Chest c1 = Utils.getMajorVersion() >= 13 && (face == BlockFace.NORTH || face == BlockFace.EAST) ? chests[1] : chests[0]; Chest c2 = Utils.getMajorVersion() >= 13 && (face == BlockFace.NORTH || face == BlockFace.EAST) ? chests[0] : chests[1]; - if (b.getLocation().equals(c1.getLocation())) { + if (holoLocation.equals(c1.getLocation())) { if (c1.getX() != c2.getX()) { - holoLocation = new Location(w, x, y - subtractY, z + 0.5); + holoLocation.add(0, deltaY, 0.5); } else if (c1.getZ() != c2.getZ()) { - holoLocation = new Location(w, x + 0.5, y - subtractY, z); + holoLocation.add(0.5, deltaY, 0); } else { - holoLocation = new Location(w, x + 0.5, y - subtractY, z + 0.5); + holoLocation.add(0.5, deltaY, 0.5); } } else { if (c1.getX() != c2.getX()) { - holoLocation = new Location(w, x + 1, y - subtractY, z + 0.5); + holoLocation.add(1, deltaY, 0.5); } else if (c1.getZ() != c2.getZ()) { - holoLocation = new Location(w, x + 0.5, y - subtractY, z + 1); + holoLocation.add(0.5, deltaY, 1); } else { - holoLocation = new Location(w, x + 0.5, y - subtractY, z + 0.5); + holoLocation.add(0.5, deltaY, 0.5); } } } else { - holoLocation = new Location(w, x + 0.5, y - subtractY, z + 0.5); + holoLocation.add(0.5, deltaY, 0.5); } holoLocation.add(0, Config.hologramLift, 0); diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java index ffffc19..d3be65a 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java @@ -3,7 +3,6 @@ package de.epiceric.shopchest.utils; import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.config.Config; import de.epiceric.shopchest.shop.Shop; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.block.Chest; @@ -251,10 +250,6 @@ public class ShopUtils { } } - for (Player player : Bukkit.getOnlinePlayers()) { - updateShops(player, true); - } - if (callback != null) callback.callSyncResult(result.size()); }