From 67f12872a9d83245a2af8e10907afb410a8b7a88 Mon Sep 17 00:00:00 2001 From: MineTheCube Date: Tue, 25 Jul 2017 02:18:05 +0200 Subject: [PATCH 1/4] Performance improvements & shop updater refactor --- .../java/de/epiceric/shopchest/ShopChest.java | 9 +-- .../shopchest/listeners/ShopItemListener.java | 8 +- .../listeners/ShopUpdateListener.java | 71 ----------------- .../de/epiceric/shopchest/nms/Hologram.java | 63 ++++++++------- .../de/epiceric/shopchest/shop/ShopItem.java | 19 +++-- .../epiceric/shopchest/utils/ShopUpdater.java | 77 +++++++++++-------- .../epiceric/shopchest/utils/ShopUtils.java | 42 +++++----- src/main/resources/plugin.yml | 2 +- 8 files changed, 122 insertions(+), 169 deletions(-) diff --git a/src/main/java/de/epiceric/shopchest/ShopChest.java b/src/main/java/de/epiceric/shopchest/ShopChest.java index bce5fa7..210c4db 100644 --- a/src/main/java/de/epiceric/shopchest/ShopChest.java +++ b/src/main/java/de/epiceric/shopchest/ShopChest.java @@ -185,7 +185,7 @@ public class ShopChest extends JavaPlugin { if (updater != null) { debug("Stopping updater"); - updater.cancel(); + updater.stop(); } if (database != null) { @@ -433,13 +433,6 @@ public class ShopChest extends JavaPlugin { return updater; } - /** - * Set the {@link ShopUpdater} that schedules hologram and item updates - */ - public void setUpdater(ShopUpdater updater) { - this.updater = updater; - } - /** * @return Whether the plugin 'AreaShop' is enabled */ diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java index 46b0ee9..016bc1f 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java @@ -4,9 +4,7 @@ import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.utils.ShopUtils; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; @@ -15,7 +13,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.*; -import org.bukkit.event.player.*; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.world.StructureGrowEvent; public class ShopItemListener implements Listener { @@ -34,6 +33,9 @@ public class ShopItemListener implements Listener { if (shop.getItem() != null) { shop.getItem().setVisible(e.getPlayer(), false); } + if (shop.getHologram() != null) { + shop.getHologram().hidePlayer(e.getPlayer()); + } } } diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java index 224269b..ec03010 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java @@ -1,19 +1,10 @@ package de.epiceric.shopchest.listeners; import de.epiceric.shopchest.ShopChest; -import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.utils.Callback; -import de.epiceric.shopchest.utils.ShopUpdater; -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.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.scheduler.BukkitRunnable; public class ShopUpdateListener implements Listener { @@ -23,48 +14,6 @@ public class ShopUpdateListener implements Listener { this.plugin = plugin; } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerTeleport(final PlayerTeleportEvent e) { - // Wait till the chunk should have loaded on the client - new BukkitRunnable() { - @Override - public void run() { - hideShops(e.getPlayer(), true); - plugin.getShopUtils().updateShops(e.getPlayer(), true); - } - }.runTaskLater(plugin, 15L); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerJoin(PlayerJoinEvent e) { - restartShopUpdater(e.getPlayer()); - } - - // The Bukkit::getOnlinePlayers() list does not include players that - // are currently respawning or chaning worlds, so when only one player is - // online and is currently respawning, the updater will think that no player - // is online, so it will stop. To prevent that, a delay of 1 tick is needed. - - @EventHandler - public void onPlayerChangedWorld(final PlayerChangedWorldEvent e) { - new BukkitRunnable() { - @Override - public void run() { - restartShopUpdater(e.getPlayer()); - } - }.runTaskLater(plugin, 1L); - } - - @EventHandler - public void onPlayerRespawn(final PlayerRespawnEvent e) { - new BukkitRunnable() { - @Override - public void run() { - restartShopUpdater(e.getPlayer()); - } - }.runTaskLater(plugin, 1L); - } - @EventHandler public void onWorldLoad(WorldLoadEvent e) { final String worldName = e.getWorld().getName(); @@ -81,24 +30,4 @@ public class ShopUpdateListener implements Listener { } }); } - - private void restartShopUpdater(Player p) { - if (!plugin.getUpdater().isRunning()) { - plugin.setUpdater(new ShopUpdater(plugin)); - plugin.getUpdater().start(); - } - - hideShops(p, false); - } - - private void hideShops(Player p, boolean onlyItem) { - for (Shop shop : plugin.getShopUtils().getShops()) { - if (!onlyItem) { - if (shop.getHologram() != null) shop.getHologram().hidePlayer(p); - } - - if (shop.getItem() != null) shop.getItem().setVisible(p, false); - } - } - } diff --git a/src/main/java/de/epiceric/shopchest/nms/Hologram.java b/src/main/java/de/epiceric/shopchest/nms/Hologram.java index 5458bb9..233a401 100644 --- a/src/main/java/de/epiceric/shopchest/nms/Hologram.java +++ b/src/main/java/de/epiceric/shopchest/nms/Hologram.java @@ -2,14 +2,14 @@ package de.epiceric.shopchest.nms; import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.config.Config; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class Hologram { @@ -19,7 +19,7 @@ public class Hologram { private List wrappers = new ArrayList<>(); private ArmorStandWrapper interactArmorStandWrapper; private Location location; - private List visible = new ArrayList<>(); + private Set visibility = new HashSet<>(); private ShopChest plugin; private Config config; @@ -66,8 +66,11 @@ public class Hologram { wrappers.add(line, wrapper); if (forceUpdateLine) { - for (Player player : visible) { - wrapper.setVisible(player, true); + for (UUID uuid : visibility) { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + wrapper.setVisible(player, true); + } } } } @@ -148,40 +151,44 @@ public class Hologram { * @param p Player to which the hologram should be shown */ public void showPlayer(final Player p) { - new BukkitRunnable() { - @Override - public void run() { - for (ArmorStandWrapper wrapper : wrappers) { - wrapper.setVisible(p, true); - } + if (!isVisible(p)) { + new BukkitRunnable() { + @Override + public void run() { + for (ArmorStandWrapper wrapper : wrappers) { + wrapper.setVisible(p, true); + } - if (interactArmorStandWrapper != null) { - interactArmorStandWrapper.setVisible(p, true); + if (interactArmorStandWrapper != null) { + interactArmorStandWrapper.setVisible(p, true); + } } - } - }.runTaskAsynchronously(plugin); + }.runTaskAsynchronously(plugin); - visible.add(p); + visibility.add(p.getUniqueId()); + } } /** * @param p Player from which the hologram should be hidden */ public void hidePlayer(final Player p) { - new BukkitRunnable() { - @Override - public void run() { - for (ArmorStandWrapper wrapper : wrappers) { - wrapper.setVisible(p, false); - } + if (isVisible(p)) { + new BukkitRunnable() { + @Override + public void run() { + for (ArmorStandWrapper wrapper : wrappers) { + wrapper.setVisible(p, false); + } - if (interactArmorStandWrapper != null) { - interactArmorStandWrapper.setVisible(p, false); + if (interactArmorStandWrapper != null) { + interactArmorStandWrapper.setVisible(p, false); + } } - } - }.runTaskAsynchronously(plugin); + }.runTaskAsynchronously(plugin); - visible.remove(p); + visibility.remove(p.getUniqueId()); + } } /** @@ -189,7 +196,7 @@ public class Hologram { * @return Whether the hologram is visible to the player */ public boolean isVisible(Player p) { - return visible.contains(p); + return visibility.contains(p.getUniqueId()); } /** diff --git a/src/main/java/de/epiceric/shopchest/shop/ShopItem.java b/src/main/java/de/epiceric/shopchest/shop/ShopItem.java index 7599eb8..a972b31 100644 --- a/src/main/java/de/epiceric/shopchest/shop/ShopItem.java +++ b/src/main/java/de/epiceric/shopchest/shop/ShopItem.java @@ -2,6 +2,7 @@ package de.epiceric.shopchest.shop; import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.utils.Utils; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -9,13 +10,14 @@ import org.bukkit.inventory.ItemStack; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Map; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; public class ShopItem { private ShopChest plugin; - private Map visible = new HashMap<>(); + private Set visibility = new HashSet<>(); private ItemStack itemStack; private Location location; @@ -88,8 +90,9 @@ public class ShopItem { } public void remove() { - for (Player p : visible.keySet()) { - if (isVisible(p)) setVisible(p, false); + for (UUID uuid : visibility) { + Player p = Bukkit.getPlayer(uuid); + if (p != null) setVisible(p, false); } } @@ -103,7 +106,7 @@ public class ShopItem { } public boolean isVisible(Player p) { - return visible.get(p) == null ? false : visible.get(p); + return visibility.contains(p.getUniqueId()); } public void setVisible(final Player p, boolean visible) { @@ -114,6 +117,7 @@ public class ShopItem { for (Object packet : this.creationPackets) { Utils.sendPacket(plugin, packet, p); } + visibility.add(p.getUniqueId()); } else { try { if (p.isOnline()) { @@ -125,9 +129,8 @@ public class ShopItem { plugin.debug("Failed to destroy shop item with reflection"); plugin.debug(e); } + visibility.remove(p.getUniqueId()); } - - this.visible.put(p, visible); } diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java b/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java index 52ea673..9461867 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java @@ -3,11 +3,9 @@ package de.epiceric.shopchest.utils; import de.epiceric.shopchest.ShopChest; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; -import java.util.Collection; - -public class ShopUpdater extends BukkitRunnable { +public class ShopUpdater { public enum UpdateQuality { SLOWEST(31L), @@ -18,7 +16,7 @@ public class ShopUpdater extends BukkitRunnable { FASTER(4L), FASTEST(1L); - private long interval; + private final long interval; UpdateQuality(long interval) { this.interval = interval; @@ -29,47 +27,64 @@ public class ShopUpdater extends BukkitRunnable { } } - private ShopChest plugin; + private final ShopChest plugin; - private boolean running; - private long interval; + private long interval = UpdateQuality.NORMAL.getInterval(); + + private volatile BukkitTask running; public ShopUpdater(ShopChest plugin) { this.plugin = plugin; - setInterval(plugin.getShopChestConfig().update_quality.getInterval()); } - public synchronized void setInterval(long interval) { - this.interval = interval; - } - - public synchronized void start() { - super.runTaskTimerAsynchronously(plugin, interval, interval); - running = true; - } - - @Override - public synchronized void cancel() { - if (running) { - running = false; - super.cancel(); + /** + * Start task, except if it is already + */ + public void start() { + if (!isRunning()) { + interval = plugin.getShopChestConfig().update_quality.getInterval(); + running = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new ShopUpdaterTask(plugin), interval, interval); } } + /** + * Stop any running task then start it again + */ + public void restart() { + stop(); + start(); + } + + /** + * Stop task properly + */ + public void stop() { + if (running != null) { + running.cancel(); + running = null; + } + } + + /** + * @return whether task is running or not + */ public boolean isRunning() { - return running; + return running != null; } - @Override - public void run() { - Collection players = Bukkit.getOnlinePlayers(); + private static class ShopUpdaterTask implements Runnable { - if (players.isEmpty()) { - cancel(); + private final ShopChest plugin; + + private ShopUpdaterTask(ShopChest plugin) { + this.plugin = plugin; } - for (Player p : players) { - plugin.getShopUtils().updateShops(p); + @Override + public void run() { + for (Player p : Bukkit.getOnlinePlayers()) { + plugin.getShopUtils().updateShops(p); + } } } } diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java index 4fb4e8a..4e97196 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java @@ -218,10 +218,7 @@ public class ShopUtils { if (reloadConfig) { plugin.getShopChestConfig().reload(false, true, showConsoleMessages); plugin.getHologramFormat().reload(); - plugin.getUpdater().cancel(); - - plugin.setUpdater(new ShopUpdater(plugin)); - plugin.getUpdater().start(); + plugin.getUpdater().restart(); } plugin.getShopDatabase().connect(new Callback(plugin) { @@ -314,9 +311,7 @@ public class ShopUtils { } } } else { - for (Shop shop : getShops()) { - updateShop(shop, player); - } + updateNearestShops(player); } playerLocation.put(player, player.getLocation()); @@ -370,27 +365,36 @@ public class ShopUtils { double holoDistSqr = Math.pow(plugin.getShopChestConfig().maximal_distance, 2); double itemDistSqr = Math.pow(plugin.getShopChestConfig().maximal_item_distance, 2); + updateShop(shop, player, holoDistSqr, itemDistSqr); + } + + private void updateNearestShops(Player p) { + double holoDistSqr = Math.pow(plugin.getShopChestConfig().maximal_distance, 2); + double itemDistSqr = Math.pow(plugin.getShopChestConfig().maximal_item_distance, 2); + + for (Shop shop : getShops()) { + updateShop(shop, p, holoDistSqr, itemDistSqr); + } + } + + private void updateShop(Shop shop, Player player, double holoDistSqr, double itemDistSqr) { if (player.getLocation().getWorld().getName().equals(shop.getLocation().getWorld().getName())) { double distSqr = shop.getLocation().distanceSquared(player.getLocation()); - if (distSqr <= holoDistSqr) { - if (shop.getHologram() != null) { - if (!shop.getHologram().isVisible(player)) { - shop.getHologram().showPlayer(player); - } - } - } else { - if (shop.getHologram() != null) { + if (shop.getHologram() != null) { + if (distSqr <= holoDistSqr) { + shop.getHologram().showPlayer(player); + } else { shop.getHologram().hidePlayer(player); } } - if (distSqr <= itemDistSqr) { - if (shop.getItem() != null) { + if (shop.getItem() != null) { + if (distSqr <= itemDistSqr) { shop.getItem().setVisible(player, true); + } else { + shop.getItem().setVisible(player, false); } - } else { - if (shop.getItem() != null) shop.getItem().setVisible(player, false); } } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 626e294..2f9bac0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,7 +6,7 @@ version: ${project.version} author: EpicEric website: ${project.url} description: Create your own nice-looking chest shops and sell your stuff to other players! -softdepend: [WorldGuard, Towny, AuthMe, PlotSquared, uSkyBlock, ASkyBlock, IslandWorld, GriefPrevention, AreaShop] +softdepend: [WorldGuard, Towny, AuthMe, PlotSquared, uSkyBlock, ASkyBlock, IslandWorld, GriefPrevention, AreaShop, Multiverse-Core, MultiWorld] depend: [Vault] permissions: From 08b298922e75fb61cc32db7cb69c1d281a6e5125 Mon Sep 17 00:00:00 2001 From: MineTheCube Date: Thu, 27 Jul 2017 01:02:21 +0200 Subject: [PATCH 2/4] Re-add teleport listener and few minor changes --- .../listeners/ShopUpdateListener.java | 41 +++++++++++++++++++ .../de/epiceric/shopchest/nms/Hologram.java | 23 +++++------ .../de/epiceric/shopchest/shop/ShopItem.java | 11 ++--- .../epiceric/shopchest/utils/ShopUpdater.java | 32 ++++++++++----- .../epiceric/shopchest/utils/ShopUtils.java | 18 ++++---- 5 files changed, 87 insertions(+), 38 deletions(-) diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java index ec03010..5639d3f 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java @@ -1,10 +1,16 @@ package de.epiceric.shopchest.listeners; import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.utils.Callback; +import org.bukkit.Location; +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.PlayerTeleportEvent; import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.scheduler.BukkitRunnable; public class ShopUpdateListener implements Listener { @@ -14,6 +20,41 @@ public class ShopUpdateListener implements Listener { this.plugin = plugin; } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerTeleport(PlayerTeleportEvent e) { + Location from = e.getFrom(); + Location to = e.getTo(); + final Player p = e.getPlayer(); + + // Wait till the chunk should have loaded on the client + // Update IF worlds are different OR chunks are different (as many teleports are in same chunk) + if (!from.getWorld().equals(to.getWorld()) + || from.getChunk().getX() != to.getChunk().getX() + || from.getChunk().getZ() != to.getChunk().getZ()) { + // Wait for 15 ticks before we actually put it in the queue + new BukkitRunnable() { + @Override + public void run() { + plugin.getUpdater().beforeNext(new Runnable() { + @Override + public void run() { + if (p.isOnline()) { + for (Shop shop : plugin.getShopUtils().getShops()) { + if (shop.getItem() != null) { + shop.getItem().setVisible(p, false); + } + if (shop.getHologram() != null) { + shop.getHologram().hidePlayer(p); + } + } + } + } + }); + } + }.runTaskLater(plugin, 15L); + } + } + @EventHandler public void onWorldLoad(WorldLoadEvent e) { final String worldName = e.getWorld().getName(); diff --git a/src/main/java/de/epiceric/shopchest/nms/Hologram.java b/src/main/java/de/epiceric/shopchest/nms/Hologram.java index 233a401..a4dd3c0 100644 --- a/src/main/java/de/epiceric/shopchest/nms/Hologram.java +++ b/src/main/java/de/epiceric/shopchest/nms/Hologram.java @@ -10,18 +10,20 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public class Hologram { private static List holograms = new ArrayList<>(); + private final Set visibility = Collections.newSetFromMap(new ConcurrentHashMap()); + private final List wrappers = new ArrayList<>(); + private final Location location; + private final ShopChest plugin; + private final Config config; + private boolean exists = false; - private List wrappers = new ArrayList<>(); private ArmorStandWrapper interactArmorStandWrapper; - private Location location; - private Set visibility = new HashSet<>(); - private ShopChest plugin; - private Config config; public Hologram(ShopChest plugin, String[] lines, Location location) { this.plugin = plugin; @@ -254,7 +256,9 @@ public class Hologram { */ public static Hologram getHologram(ArmorStand armorStand) { for (Hologram hologram : holograms) { - if (hologram.contains(armorStand)) return hologram; + if (hologram.contains(armorStand)) { + return hologram; + } } return null; @@ -265,12 +269,7 @@ public class Hologram { * @return Whether the armor stand is part of a hologram */ public static boolean isPartOfHologram(ArmorStand armorStand) { - for (Hologram hologram : holograms) { - if (hologram.contains(armorStand)) { - return true; - } - } - return false; + return getHologram(armorStand) != null; } } diff --git a/src/main/java/de/epiceric/shopchest/shop/ShopItem.java b/src/main/java/de/epiceric/shopchest/shop/ShopItem.java index a972b31..add75dc 100644 --- a/src/main/java/de/epiceric/shopchest/shop/ShopItem.java +++ b/src/main/java/de/epiceric/shopchest/shop/ShopItem.java @@ -10,16 +10,17 @@ import org.bukkit.inventory.ItemStack; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -import java.util.HashSet; +import java.util.Collections; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class ShopItem { - private ShopChest plugin; - private Set visibility = new HashSet<>(); - private ItemStack itemStack; - private Location location; + private final ShopChest plugin; + private final Set visibility = Collections.newSetFromMap(new ConcurrentHashMap()); + private final ItemStack itemStack; + private final Location location; private Object entityItem; private int entityId; diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java b/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java index 9461867..14e542a 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java @@ -5,6 +5,9 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + public class ShopUpdater { public enum UpdateQuality { @@ -28,8 +31,7 @@ public class ShopUpdater { } private final ShopChest plugin; - - private long interval = UpdateQuality.NORMAL.getInterval(); + private final Queue beforeNext = new ConcurrentLinkedQueue<>(); private volatile BukkitTask running; @@ -42,8 +44,8 @@ public class ShopUpdater { */ public void start() { if (!isRunning()) { - interval = plugin.getShopChestConfig().update_quality.getInterval(); - running = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new ShopUpdaterTask(plugin), interval, interval); + long interval = plugin.getShopChestConfig().update_quality.getInterval(); + running = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new ShopUpdaterTask(), interval, interval); } } @@ -72,16 +74,26 @@ public class ShopUpdater { return running != null; } - private static class ShopUpdaterTask implements Runnable { + /** + * Register a task to run before next loop + * + * @param runnable task to run + */ + public void beforeNext(Runnable runnable) { + beforeNext.add(runnable); + } - private final ShopChest plugin; - - private ShopUpdaterTask(ShopChest plugin) { - this.plugin = plugin; - } + 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); } diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java index 4e97196..029d091 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java @@ -13,16 +13,13 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.util.Vector; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class ShopUtils { - private HashMap shopLocation = new HashMap<>(); - private HashMap playerLocation = new HashMap<>(); - private ShopChest plugin; + private final HashMap shopLocation = new HashMap<>(); + private final HashMap playerLocation = new HashMap<>(); + private final ShopChest plugin; public ShopUtils(ShopChest plugin) { this.plugin = plugin; @@ -55,8 +52,7 @@ public class ShopUtils { * @return Array of all Shops */ public Shop[] getShops() { - Collection shops = shopLocation.values(); - return shops.toArray(new Shop[shops.size()]); + return shopLocation.values().toArray(new Shop[0]); } /** @@ -274,7 +270,7 @@ public class ShopUtils { * @param force Whether update should be forced even if player has not moved */ public void updateShops(Player player, boolean force) { - if (!force && player.getLocation().equals(playerLocation.get(player))) { + if (!force && player.getLocation().equals(playerLocation.get(player.getUniqueId()))) { // Player has not moved, so don't calculate shops again. return; } @@ -314,7 +310,7 @@ public class ShopUtils { updateNearestShops(player); } - playerLocation.put(player, player.getLocation()); + playerLocation.put(player.getUniqueId(), player.getLocation()); } private Set getShopsInSight(Player player) { From 5bb338494dbdece5b42eb12da9dc9fcf776a9e5d Mon Sep 17 00:00:00 2001 From: MineTheCube Date: Thu, 27 Jul 2017 01:17:34 +0200 Subject: [PATCH 3/4] Cleanup pom.xml --- pom.xml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 6826dd2..790fdd6 100644 --- a/pom.xml +++ b/pom.xml @@ -6,21 +6,30 @@ de.epiceric ShopChest - jar ${version.final} - ShopChest + + ${project.artifactId} https://www.spigotmc.org/resources/shopchest.11431/ Let your players create their own nice-looking shops to sell their stuff to other players! + jar - 1.7 - 1.7 + + UTF-8 + ${projectEncoding} + ${projectEncoding} + + 1.7 + ${jdkVersion} + ${jdkVersion} + + 1.12.3 ${version.number}-${version.git} + github - @@ -252,6 +261,7 @@ de.epiceric.shopchest.utils + false From 48059811fb64ff3a47d55e9c5be325b16ddc2197 Mon Sep 17 00:00:00 2001 From: MineTheCube Date: Thu, 27 Jul 2017 13:10:00 +0200 Subject: [PATCH 4/4] Method getShops now returns a collection --- src/main/java/de/epiceric/shopchest/utils/ShopUtils.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java index 029d091..ba5755d 100644 --- a/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java +++ b/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java @@ -18,6 +18,7 @@ import java.util.*; public class ShopUtils { private final HashMap shopLocation = new HashMap<>(); + private final Collection shopLocationValues = Collections.unmodifiableCollection(shopLocation.values()); private final HashMap playerLocation = new HashMap<>(); private final ShopChest plugin; @@ -48,11 +49,11 @@ public class ShopUtils { } /** - * Get all Shops - * @return Array of all Shops + * Get all shops + * @return Read-only collection of all shops, may contain duplicates */ - public Shop[] getShops() { - return shopLocation.values().toArray(new Shop[0]); + public Collection getShops() { + return shopLocationValues; } /**