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.
This commit is contained in:
Eric 2018-08-01 13:35:42 +02:00
parent 78384ebc7b
commit 3678738048
5 changed files with 59 additions and 39 deletions

View File

@ -54,6 +54,10 @@ import java.io.PrintWriter;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; 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 { public class ShopChest extends JavaPlugin {
@ -78,6 +82,7 @@ public class ShopChest extends JavaPlugin {
private GriefPrevention griefPrevention; private GriefPrevention griefPrevention;
private AreaShop areaShop; private AreaShop areaShop;
private ShopUpdater updater; private ShopUpdater updater;
private ExecutorService shopCreationThreadPool;
/** /**
* @return An instance of ShopChest * @return An instance of ShopChest
@ -186,6 +191,8 @@ public class ShopChest extends JavaPlugin {
shopUtils = new ShopUtils(this); shopUtils = new ShopUtils(this);
shopCommand = new ShopCommand(this); shopCommand = new ShopCommand(this);
shopCreationThreadPool = new ThreadPoolExecutor(0, 8,
5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
registerListeners(); registerListeners();
initializeShops(); initializeShops();
@ -203,6 +210,10 @@ public class ShopChest extends JavaPlugin {
updater.stop(); updater.stop();
} }
if (shopCreationThreadPool != null) {
shopCreationThreadPool.shutdown();
}
if (database != null) { if (database != null) {
for (Shop shop : shopUtils.getShopsCopy()) { for (Shop shop : shopUtils.getShopsCopy()) {
shopUtils.removeShop(shop, false); 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() { public HologramFormat getHologramFormat() {
return hologramFormat; return hologramFormat;
} }

View File

@ -73,9 +73,6 @@ public class ChestProtectListener implements Listener {
public void onResult(Void result) { public void onResult(Void result) {
newShop.create(true); newShop.create(true);
shopUtils.addShop(newShop, true); shopUtils.addShop(newShop, true);
for (Player player : shop.getLocation().getWorld().getPlayers()) {
shopUtils.updateShops(player, true);
}
} }
}); });
} else { } else {
@ -271,9 +268,6 @@ public class ChestProtectListener implements Listener {
newShop.create(true); newShop.create(true);
shopUtils.addShop(newShop, true); shopUtils.addShop(newShop, true);
plugin.debug(String.format("%s extended %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); 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 { } else {

View File

@ -769,11 +769,6 @@ public class ShopInteractListener implements Listener {
} else { } else {
executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_CREATED, placeholder)); 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);
}
} }
/** /**

View File

@ -19,8 +19,10 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.Chest; import org.bukkit.block.Chest;
import org.bukkit.block.DoubleChest; import org.bukkit.block.DoubleChest;
import org.bukkit.block.data.Directional; import org.bukkit.block.data.Directional;
import org.bukkit.entity.Player;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*; import java.util.*;
@ -42,6 +44,7 @@ public class Shop {
private boolean created; private boolean created;
private int id; private int id;
private Hologram hologram; private Hologram hologram;
private Location holoLocation;
private ShopItem item; private ShopItem item;
public Shop(int id, ShopChest plugin, OfflinePlayer vendor, ItemStack product, Location location, double buyPrice, double sellPrice, ShopType shopType) { 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(); Block b = location.getBlock();
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) { 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); plugin.getShopUtils().removeShop(this, Config.removeShopOnError);
if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage());
plugin.debug("Failed to create shop (#" + id + ")"); plugin.debug("Failed to create shop (#" + id + ")");
plugin.debug(ex); plugin.debug(ex);
return false; return false;
} else if ((b.getRelative(BlockFace.UP).getType() != Material.AIR) && Config.showShopItems) { } 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); plugin.getShopUtils().removeShop(this, Config.removeShopOnError);
if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage());
plugin.debug("Failed to create shop (#" + id + ")"); plugin.debug("Failed to create shop (#" + id + ")");
@ -109,8 +114,17 @@ public class Shop {
return false; return false;
} }
if (hologram == null || !hologram.exists()) createHologram(); plugin.getShopCreationThreadPool().execute(() -> {
if (item == null) createItem(); 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; created = true;
return true; return true;
@ -147,7 +161,7 @@ public class Shop {
Location itemLocation; Location itemLocation;
ItemStack itemStack; 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 = product.clone();
itemStack.setAmount(1); itemStack.setAmount(1);
@ -189,9 +203,14 @@ public class Shop {
} }
String[] holoText = getHologramText(); 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) { private Location getHologramLocation(boolean doubleChest, Chest[] chests, BlockFace face) {
Block b = location.getBlock(); World w = location.getWorld();
Location holoLocation; int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
World w = b.getWorld(); Location holoLocation = new Location(w, x, y, z);
int x = b.getX();
int y = b.getY();
int z = b.getZ();
double subtractY = 0.6; double deltaY = -0.6;
if (Config.hologramFixedBottom) subtractY = 0.85; if (Config.hologramFixedBottom) deltaY = -0.85;
if (doubleChest) { if (doubleChest) {
Chest c1 = Utils.getMajorVersion() >= 13 && (face == BlockFace.NORTH || face == BlockFace.EAST) ? chests[1] : chests[0]; 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]; 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()) { 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()) { } else if (c1.getZ() != c2.getZ()) {
holoLocation = new Location(w, x + 0.5, y - subtractY, z); holoLocation.add(0.5, deltaY, 0);
} else { } else {
holoLocation = new Location(w, x + 0.5, y - subtractY, z + 0.5); holoLocation.add(0.5, deltaY, 0.5);
} }
} else { } else {
if (c1.getX() != c2.getX()) { 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()) { } else if (c1.getZ() != c2.getZ()) {
holoLocation = new Location(w, x + 0.5, y - subtractY, z + 1); holoLocation.add(0.5, deltaY, 1);
} else { } else {
holoLocation = new Location(w, x + 0.5, y - subtractY, z + 0.5); holoLocation.add(0.5, deltaY, 0.5);
} }
} }
} else { } 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); holoLocation.add(0, Config.hologramLift, 0);

View File

@ -3,7 +3,6 @@ package de.epiceric.shopchest.utils;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config; import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.block.Chest; 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()); if (callback != null) callback.callSyncResult(result.size());
} }