mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-12-23 01:21:47 +00:00
Improve performance while updating shops
Inspired from the fork of @gonzalociocca but not exactly the same Closes #39
This commit is contained in:
parent
e08b09fe3f
commit
f6f8d93b85
@ -5,6 +5,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import de.epiceric.shopchest.config.Config;
|
||||
import de.epiceric.shopchest.config.Regex;
|
||||
import de.epiceric.shopchest.event.ShopReloadEvent;
|
||||
import de.epiceric.shopchest.event.ShopUpdateEvent;
|
||||
import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.language.LocalizedMessage;
|
||||
import de.epiceric.shopchest.listeners.*;
|
||||
@ -26,6 +27,8 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -46,6 +49,7 @@ public class ShopChest extends JavaPlugin {
|
||||
private FileWriter fw;
|
||||
private WorldGuardPlugin worldGuard;
|
||||
private Towny towny;
|
||||
private ShopUpdater updater;
|
||||
|
||||
/**
|
||||
* @return An instance of ShopChest
|
||||
@ -304,7 +308,7 @@ public class ShopChest extends JavaPlugin {
|
||||
}
|
||||
|
||||
debug("Registering listeners...");
|
||||
getServer().getPluginManager().registerEvents(new HologramUpdateListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new ShopUpdateListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new ShopItemListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new NotifyUpdateOnJoinListener(this), this);
|
||||
@ -317,12 +321,20 @@ public class ShopChest extends JavaPlugin {
|
||||
getServer().getPluginManager().registerEvents(new WorldGuardListener(this), this);
|
||||
|
||||
initializeShops();
|
||||
|
||||
updater = new ShopUpdater(this);
|
||||
updater.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
debug("Disabling ShopChest...");
|
||||
|
||||
if (updater != null) {
|
||||
debug("Stopping updater");
|
||||
updater.cancel();
|
||||
}
|
||||
|
||||
if (database != null) {
|
||||
for (Shop shop : shopUtils.getShops()) {
|
||||
shopUtils.removeShop(shop, false);
|
||||
@ -383,6 +395,13 @@ public class ShopChest extends JavaPlugin {
|
||||
debug("Initialized " + count + " Shops");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link ShopUpdater} that schedules hologram and item updates
|
||||
*/
|
||||
public ShopUpdater getUpdater() {
|
||||
return updater;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the plugin 'Towny' is enabled
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.epiceric.shopchest.config;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.event.ShopUpdateEvent;
|
||||
import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.sql.Database;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
@ -20,6 +21,9 @@ public class Config {
|
||||
|
||||
private LanguageConfiguration langConfig;
|
||||
|
||||
/** The quality of hologram and item updating (performance saving, or better quality) **/
|
||||
public ShopUpdateEvent.UpdateQuality update_quality;
|
||||
|
||||
/** The default value for the custom WorldGuard flag 'create-shop' **/
|
||||
public boolean wg_allow_create_shop_default;
|
||||
|
||||
@ -299,6 +303,7 @@ public class Config {
|
||||
* Reload the configuration values from config.yml
|
||||
*/
|
||||
public void reload(boolean firstLoad, boolean langReload, boolean showMessages) {
|
||||
update_quality = ShopUpdateEvent.UpdateQuality.valueOf(plugin.getConfig().getString("update-quality"));
|
||||
wg_allow_create_shop_default = plugin.getConfig().getBoolean("worldguard-default-flag-values.create-shop");
|
||||
wg_allow_use_admin_shop_default = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-admin-shop");
|
||||
wg_allow_use_shop_default = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-shop");
|
||||
|
@ -0,0 +1,41 @@
|
||||
package de.epiceric.shopchest.event;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class ShopUpdateEvent extends Event {
|
||||
|
||||
public enum UpdateQuality {
|
||||
SLOWEST(31L),
|
||||
SLOWER(24L),
|
||||
SLOW(17L),
|
||||
NORMAL(10L),
|
||||
FAST(7L),
|
||||
FASTER(4L),
|
||||
FASTEST(1L);
|
||||
|
||||
private long time;
|
||||
|
||||
UpdateQuality(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
public ShopUpdateEvent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package de.epiceric.shopchest.listeners;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.shop.Shop;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public class HologramUpdateListener implements Listener {
|
||||
|
||||
private ShopChest plugin;
|
||||
|
||||
public HologramUpdateListener(ShopChest plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
updateHolograms(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerMove(PlayerMoveEvent e) {
|
||||
if (!plugin.getShopChestConfig().enable_quality_mode &&
|
||||
e.getFrom().getBlockX() == e.getTo().getBlockX() &&
|
||||
e.getFrom().getBlockY() == e.getTo().getBlockY() &&
|
||||
e.getFrom().getBlockZ() == e.getTo().getBlockZ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateHolograms(e.getPlayer());
|
||||
}
|
||||
|
||||
private void updateHolograms(Player p) {
|
||||
Location playerLocation = p.getLocation();
|
||||
double hologramDistanceSquared = Math.pow(plugin.getShopChestConfig().maximal_distance, 2);
|
||||
|
||||
for (Shop shop : plugin.getShopUtils().getShops()) {
|
||||
Block b = shop.getLocation().getBlock();
|
||||
|
||||
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) {
|
||||
plugin.getShopUtils().removeShop(shop, plugin.getShopChestConfig().remove_shop_on_error);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shop.getHologram() == null) continue;
|
||||
|
||||
Location shopLocation = shop.getLocation();
|
||||
|
||||
if (playerLocation.getWorld().getName().equals(shopLocation.getWorld().getName())) {
|
||||
if (playerLocation.distanceSquared(shop.getHologram().getLocation()) <= hologramDistanceSquared) {
|
||||
if (!shop.getHologram().isVisible(p)) {
|
||||
shop.getHologram().showPlayer(p);
|
||||
}
|
||||
} else {
|
||||
if (shop.getHologram().isVisible(p)) {
|
||||
shop.getHologram().hidePlayer(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -374,7 +374,7 @@ public class ShopInteractListener implements Listener {
|
||||
if (hologram != null) {
|
||||
Block b = null;
|
||||
for (Shop shop : plugin.getShopUtils().getShops()) {
|
||||
if (shop.getHologram().equals(hologram)) {
|
||||
if (shop.getHologram() != null && shop.getHologram().equals(hologram)) {
|
||||
b = shop.getLocation().getBlock();
|
||||
}
|
||||
}
|
||||
@ -407,7 +407,7 @@ public class ShopInteractListener implements Listener {
|
||||
if (hologram != null) {
|
||||
Block b = null;
|
||||
for (Shop shop : plugin.getShopUtils().getShops()) {
|
||||
if (shop.getHologram().equals(hologram)) {
|
||||
if (shop.getHologram() != null && shop.getHologram().equals(hologram)) {
|
||||
b = shop.getLocation().getBlock();
|
||||
}
|
||||
}
|
||||
|
@ -28,43 +28,6 @@ public class ShopItemListener implements Listener {
|
||||
this.shopUtils = plugin.getShopUtils();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerMove(PlayerMoveEvent e) {
|
||||
if (e.getFrom().getBlockX() == e.getTo().getBlockX()
|
||||
&& e.getFrom().getBlockZ() == e.getTo().getBlockZ()
|
||||
&& e.getFrom().getBlockY() == e.getTo().getBlockY()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateShopItemVisibility(e.getPlayer(), true, false);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerTeleport(final PlayerTeleportEvent e) {
|
||||
if (e.getFrom().getWorld().equals(e.getTo().getWorld())) {
|
||||
if (e.getFrom().distanceSquared(e.getTo()) > 22500) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateShopItemVisibility(e.getPlayer(), true, true, e.getTo());
|
||||
}
|
||||
}, 20L);
|
||||
return;
|
||||
}
|
||||
updateShopItemVisibility(e.getPlayer(), true, false, e.getTo());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
updateShopItemVisibility(e.getPlayer(), true, true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
updateShopItemVisibility(e.getPlayer(), false, false);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLeave(PlayerQuitEvent e) {
|
||||
for (Shop shop : plugin.getShopUtils().getShops()) {
|
||||
@ -74,28 +37,6 @@ public class ShopItemListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShopItemVisibility(Player p, boolean hideIfAway, boolean reset) {
|
||||
updateShopItemVisibility(p, hideIfAway, reset, p.getLocation());
|
||||
}
|
||||
|
||||
private void updateShopItemVisibility(Player p, boolean hideIfAway, boolean reset, Location playerLocation) {
|
||||
double itemDistanceSquared = plugin.getShopChestConfig().maximal_item_distance;
|
||||
itemDistanceSquared *= itemDistanceSquared;
|
||||
World w = playerLocation.getWorld();
|
||||
|
||||
for (Shop shop : shopUtils.getShops()) {
|
||||
Location shopLocation = shop.getLocation();
|
||||
if (w.equals(shopLocation.getWorld()) && shopLocation.distanceSquared(playerLocation) <= itemDistanceSquared) {
|
||||
if (shop.getItem() != null) {
|
||||
if (reset) shop.getItem().resetForPlayer(p);
|
||||
else shop.getItem().setVisible(p, true);
|
||||
}
|
||||
} else if (hideIfAway) {
|
||||
if (shop.getItem() != null) shop.getItem().setVisible(p, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onBlockPlace(BlockPlaceEvent e) {
|
||||
Block b = e.getBlockPlaced();
|
||||
|
@ -0,0 +1,25 @@
|
||||
package de.epiceric.shopchest.listeners;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.event.ShopUpdateEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class ShopUpdateListener implements Listener {
|
||||
|
||||
private ShopChest plugin;
|
||||
|
||||
public ShopUpdateListener(ShopChest plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShopUpdate(ShopUpdateEvent e) {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
plugin.getShopUtils().updateShops(p, p.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java
Normal file
45
src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.epiceric.shopchest.utils;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.event.ShopUpdateEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class ShopUpdater extends Thread {
|
||||
|
||||
private boolean running;
|
||||
private long maxDelta;
|
||||
private long lastTime;
|
||||
|
||||
public ShopUpdater(ShopChest plugin) {
|
||||
setMaxDelta(plugin.getShopChestConfig().update_quality.getTime());
|
||||
}
|
||||
|
||||
public synchronized void setMaxDelta(long maxDelta) {
|
||||
this.maxDelta = maxDelta * 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
super.start();
|
||||
running = true;
|
||||
lastTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public synchronized void cancel() {
|
||||
running = false;
|
||||
super.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(running) {
|
||||
long timeNow = System.currentTimeMillis();
|
||||
long timeElapsed = timeNow - lastTime;
|
||||
|
||||
if (timeElapsed >= maxDelta) {
|
||||
Bukkit.getPluginManager().callEvent(new ShopUpdateEvent());
|
||||
lastTime = timeNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,11 @@ package de.epiceric.shopchest.utils;
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.config.Config;
|
||||
import de.epiceric.shopchest.shop.Shop;
|
||||
import de.epiceric.shopchest.sql.Database;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.DoubleChest;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -188,7 +190,10 @@ public class ShopUtils {
|
||||
|
||||
plugin.getShopDatabase().connect();
|
||||
|
||||
if (reloadConfig) plugin.getShopChestConfig().reload(false, true, showConsoleMessages);
|
||||
if (reloadConfig) {
|
||||
plugin.getShopChestConfig().reload(false, true, showConsoleMessages);
|
||||
plugin.getUpdater().setMaxDelta(plugin.getShopChestConfig().update_quality.getTime());
|
||||
}
|
||||
|
||||
for (Shop shop : getShops()) {
|
||||
removeShop(shop, false);
|
||||
@ -215,4 +220,55 @@ public class ShopUtils {
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update hologram and item of all shops for a player
|
||||
* @param player Player to show the updates
|
||||
* @param location Location of the player
|
||||
*/
|
||||
public void updateShops(Player player, Location location) {
|
||||
for (Shop shop : getShops()) {
|
||||
updateShop(shop, player, location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update hologram and item of the shop for a player
|
||||
* @param shop Shop to update
|
||||
* @param player Player to show the update
|
||||
* @param location Location of the player
|
||||
*/
|
||||
public void updateShop(Shop shop, Player player, Location location) {
|
||||
double holoDistSqr = Math.pow(plugin.getShopChestConfig().maximal_distance, 2);
|
||||
double itemDistSqr = Math.pow(plugin.getShopChestConfig().maximal_item_distance, 2);
|
||||
|
||||
if (location.getWorld().getName().equals(shop.getLocation().getWorld().getName())) {
|
||||
double distSqr = shop.getLocation().distanceSquared(location);
|
||||
|
||||
if (distSqr <= holoDistSqr) {
|
||||
if (shop.getHologram() != null) {
|
||||
Block b = shop.getLocation().getBlock();
|
||||
|
||||
if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) {
|
||||
plugin.getShopUtils().removeShop(shop, plugin.getShopChestConfig().remove_shop_on_error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shop.getHologram().isVisible(player)) {
|
||||
shop.getHologram().showPlayer(player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (shop.getHologram().isVisible(player)) shop.getHologram().hidePlayer(player);
|
||||
}
|
||||
|
||||
if (distSqr <= itemDistSqr) {
|
||||
if (shop.getItem() != null) {
|
||||
shop.getItem().setVisible(player, true);
|
||||
}
|
||||
} else {
|
||||
if (shop.getItem() != null) shop.getItem().setVisible(player, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ language-file: "en_US"
|
||||
# Set whether the floating shop items on top of the chest should be shown
|
||||
show-shop-items: true
|
||||
|
||||
# Set whether quality-mode should be enabled.
|
||||
# Showing and hiding holograms will look better,
|
||||
# but TPS will probably decrease.
|
||||
# Not recommended on servers with low performance
|
||||
# or on servers with a lot of shops!
|
||||
enable-quality-mode: false
|
||||
# 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 whether interaction with the hologram should be enabled.
|
||||
# If set to true, a player can do the exact same thing with the
|
||||
|
Loading…
Reference in New Issue
Block a user