Change shop updater logic

I'm not sure if this better or worse, but it's worth a try.
This commit is contained in:
Eric 2018-07-29 21:52:54 +02:00
parent 0a06a69e65
commit 5c2c3169b6
4 changed files with 68 additions and 137 deletions

View File

@ -4,7 +4,6 @@ import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.language.LanguageUtils; import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.sql.Database; import de.epiceric.shopchest.sql.Database;
import de.epiceric.shopchest.utils.ItemUtils; import de.epiceric.shopchest.utils.ItemUtils;
import de.epiceric.shopchest.utils.ShopUpdater;
import de.epiceric.shopchest.utils.Utils; import de.epiceric.shopchest.utils.Utils;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
@ -22,11 +21,6 @@ import java.util.Set;
public class Config { public class Config {
/**
* The quality of hologram and item updating (performance saving, or better quality)
**/
public static ShopUpdater.UpdateQuality updateQuality;
/** /**
* The item with which a player can click a shop to retrieve information * The item with which a player can click a shop to retrieve information
**/ **/
@ -460,7 +454,6 @@ public class Config {
public void reload(boolean firstLoad, boolean langReload, boolean showMessages) { public void reload(boolean firstLoad, boolean langReload, boolean showMessages) {
plugin.reloadConfig(); plugin.reloadConfig();
updateQuality = ShopUpdater.UpdateQuality.valueOf(plugin.getConfig().getString("update-quality"));
shopInfoItem = ItemUtils.getItemStack(plugin.getConfig().getString("shop-info-item")); shopInfoItem = ItemUtils.getItemStack(plugin.getConfig().getString("shop-info-item"));
wgAllowCreateShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.create-shop"); wgAllowCreateShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.create-shop");
wgAllowUseAdminShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-admin-shop"); wgAllowUseAdminShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-admin-shop");

View File

@ -1,40 +1,18 @@
package de.epiceric.shopchest.utils; package de.epiceric.shopchest.utils;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class ShopUpdater { public class ShopUpdater {
public enum UpdateQuality {
SLOWEST(31L),
SLOWER(24L),
SLOW(17L),
NORMAL(10L),
FAST(7L),
FASTER(4L),
FASTEST(1L);
private final long interval;
UpdateQuality(long interval) {
this.interval = interval;
}
public long getInterval() {
return interval;
}
}
private final ShopChest plugin; private final ShopChest plugin;
private final Queue<Runnable> beforeNext = new ConcurrentLinkedQueue<>(); private final Queue<Runnable> beforeNext = new ConcurrentLinkedQueue<>();
private volatile BukkitTask running; private volatile Thread thread;
public ShopUpdater(ShopChest plugin) { public ShopUpdater(ShopChest plugin) {
this.plugin = plugin; this.plugin = plugin;
@ -45,8 +23,19 @@ public class ShopUpdater {
*/ */
public void start() { public void start() {
if (!isRunning()) { if (!isRunning()) {
long interval = Config.updateQuality.getInterval(); thread = new Thread(() -> {
running = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new ShopUpdaterTask(), interval, interval); while (!Thread.interrupted()) {
for (Runnable runnable : beforeNext) {
runnable.run();
}
beforeNext.clear();
for (Player p : Bukkit.getOnlinePlayers()) {
plugin.getShopUtils().updateShops(p);
}
}
}, "Shop Updater");
thread.start();
} }
} }
@ -62,9 +51,9 @@ public class ShopUpdater {
* Stop task properly * Stop task properly
*/ */
public void stop() { public void stop() {
if (running != null) { if (thread != null) {
running.cancel(); thread.interrupt();
running = null; thread = null;
} }
} }
@ -72,7 +61,7 @@ public class ShopUpdater {
* @return whether task is running or not * @return whether task is running or not
*/ */
public boolean isRunning() { public boolean isRunning() {
return running != null; return thread != null;
} }
/** /**
@ -83,21 +72,4 @@ public class ShopUpdater {
public void beforeNext(Runnable runnable) { public void beforeNext(Runnable runnable) {
beforeNext.add(runnable); beforeNext.add(runnable);
} }
private class ShopUpdaterTask implements Runnable {
@Override
public void run() {
if (!beforeNext.isEmpty()) {
for (Runnable runnable : beforeNext) {
runnable.run();
}
beforeNext.clear();
}
for (Player p : Bukkit.getOnlinePlayers()) {
plugin.getShopUtils().updateShops(p);
}
}
}
} }

View File

@ -307,105 +307,78 @@ public class ShopUtils {
playerLocation.remove(player.getUniqueId()); playerLocation.remove(player.getUniqueId());
} }
private static final double TARGET_THRESHOLD = 1;
private void updateVisibleShops(Player player) { private void updateVisibleShops(Player player) {
double itemDistSquared = Math.pow(Config.maximalItemDistance, 2); double itemDistSquared = Math.pow(Config.maximalItemDistance, 2);
double hologramDistSquared = Math.pow(Config.maximalDistance, 2); boolean firstShopInSight = Config.onlyShowFirstShopInSight;
double maxDist = Config.maximalDistance;
boolean firstShopInSight =Config.onlyShowFirstShopInSight; List<Shop> shopsInSight = new ArrayList<>();
double nearestDistSquared = Double.MAX_VALUE;
// used if onlyShowFirstShopInSight
List<Shop> otherShopsInSight = firstShopInSight ? new ArrayList<Shop>() : null;
double nearestDistance = 0;
Shop nearestShop = null; Shop nearestShop = null;
Location pLoc = player.getEyeLocation(); Location pLoc = player.getEyeLocation();
double pX = pLoc.getX();
double pY = pLoc.getY();
double pZ = pLoc.getZ();
Vector pDir = pLoc.getDirection(); Vector pDir = pLoc.getDirection();
double dirLength = pDir.length();
// Display holograms based on sight
for (double i = 0; i <= maxDist; i++) {
Location loc = pLoc.clone();
Vector dir = pDir.clone();
double factor = Math.min(i, maxDist);
loc.add(dir.multiply(factor));
Location locBelow = loc.clone().subtract(0, 1, 0);
// Check block below as player may look at hologram
Shop shop = getShop(loc);
if (shop == null) {
shop = getShop(locBelow);
}
if (shop != null && shop.hasHologram()) {
shopsInSight.add(shop);
double distSquared = pLoc.distanceSquared(loc);
if (distSquared < nearestDistSquared) {
nearestDistSquared = distSquared;
nearestShop = shop;
}
}
}
for (Shop shop : getShops()) { for (Shop shop : getShops()) {
Location shopLocation = shop.getLocation(); if (firstShopInSight) {
if (!shop.equals(nearestShop) && shop.hasHologram()) {
if (shopLocation.getWorld().getName().equals(player.getWorld().getName())) { shop.getHologram().hidePlayer(player);
double distanceSquared = shop.getLocation().distanceSquared(player.getLocation()); }
} else {
if (!shopsInSight.contains(shop)) {
shop.getHologram().hidePlayer(player);
}
}
// Display item based on distance // Display item based on distance
Location shopLocation = shop.getLocation();
if (shopLocation.getWorld().getName().equals(player.getWorld().getName())) {
double distSquared = shop.getLocation().distanceSquared(player.getLocation());
if (shop.hasItem()) { if (shop.hasItem()) {
if (distanceSquared <= itemDistSquared) { if (distSquared <= itemDistSquared) {
shop.getItem().showPlayer(player); shop.getItem().showPlayer(player);
} else { } else {
shop.getItem().hidePlayer(player); shop.getItem().hidePlayer(player);
} }
} }
// Display hologram based on sight
if (shop.hasHologram()) {
if (distanceSquared < hologramDistSquared) {
Location holoLocation = shop.getHologram().getLocation();
double x = holoLocation.getX() - pX;
double y = shopLocation.getY() - pY + 1.15; // chest block + item offset
double z = holoLocation.getZ() - pZ;
// See: org.bukkit.util.Vector#angle(Vector)
double angle = FastMath.acos(
(x * pDir.getX() + y * pDir.getY() + z * pDir.getZ())
/ (FastMath.sqrt(x * x + y * y + z * z) * dirLength)
);
double distance = FastMath.sqrt(distanceSquared);
// Check if is targeted
if (angle * distance < TARGET_THRESHOLD) {
// Display even if not the nearest
if (!firstShopInSight) {
shop.getHologram().showPlayer(player);
continue;
}
if (nearestShop == null) {
// nearestShop is null
// => we guess this one will be the nearest
nearestShop = shop;
nearestDistance = distance;
continue;
} else if (distance < nearestDistance) {
// nearestShop is NOT null && this shop is nearest
// => we'll hide nearestShop, and guess this one will be the nearest
otherShopsInSight.add(nearestShop);
nearestShop = shop;
nearestDistance = distance;
continue;
} else if (nearestShop.getLocation().equals(shop.getLocation())) {
// shops are the same (double chest)
// => skip since it's already been handled
continue;
}
// else: hologram is farther than nearest, so we hide it
} }
} }
// If not in sight if (nearestShop != null) {
shop.getHologram().hidePlayer(player);
}
}
}
if (firstShopInSight) {
// we hide other shop as we wan't to display only the first
for (Shop shop : otherShopsInSight) {
// we already checked hasHologram() before adding it
shop.getHologram().hidePlayer(player);
}
}
if (nearestShop != null && nearestShop.hasHologram()) {
nearestShop.getHologram().showPlayer(player); nearestShop.getHologram().showPlayer(player);
} }
if (!firstShopInSight) {
for (Shop otherShop : shopsInSight) {
otherShop.getHologram().showPlayer(player);
}
}
} }
private void updateNearestShops(Player p) { private void updateNearestShops(Player p) {

View File

@ -16,13 +16,6 @@ language-file: "en_US"
# Set whether the floating shop items on top of the chest should be shown # Set whether the floating shop items on top of the chest should be shown
show-shop-items: true show-shop-items: true
# Set the quality (speed) for hologram and item updating.
# Valid values are (from slowest to fastest):
# 'SLOWEST', 'SLOWER', 'SLOW', 'NORMAL', 'FAST', 'FASTER', 'FASTEST'
# The faster the value, the more performance will be used, which
# may lead to TPS loss.
update-quality: NORMAL
# Set the item with which a player can click a shop to retrieve information. # Set the item with which a player can click a shop to retrieve information.
# You can set this to an empty string to disable this feature. # You can set this to an empty string to disable this feature.
shop-info-item: "STICK" shop-info-item: "STICK"