diff --git a/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java b/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java index e626a715..ca879773 100644 --- a/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java +++ b/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java @@ -16,12 +16,12 @@ import dev.esophose.playerparticles.styles.ParticleStyle; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.bukkit.Location; import org.bukkit.Material; @@ -525,7 +525,7 @@ public ParticleGroup savePlayerParticleGroup(@NotNull Player player, @NotNull St Objects.requireNonNull(groupName); Objects.requireNonNull(particles); - Map mappedParticles = new HashMap<>(); + Map mappedParticles = new ConcurrentHashMap<>(); particles.forEach(x -> mappedParticles.put(x.getId(), x)); ParticleGroup particleGroup = new ParticleGroup(groupName.toLowerCase(), mappedParticles); return this.savePlayerParticleGroup(player, particleGroup); diff --git a/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java b/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java index 372ef83d..925a0768 100644 --- a/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java +++ b/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java @@ -13,9 +13,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; @@ -101,7 +101,7 @@ private void onSave(PPlayer pplayer, String groupName) { ParticleGroup group = pplayer.getParticleGroupByName(groupName); boolean groupUpdated = false; if (group == null) { - Map particles = new HashMap<>(); + Map particles = new ConcurrentHashMap<>(); for (ParticlePair particle : pplayer.getActiveParticles()) particles.put(particle.getId(), particle.clone()); // Make sure the ParticlePairs aren't the same references in both the active and saved group group = new ParticleGroup(groupName, particles); diff --git a/src/main/java/dev/esophose/playerparticles/command/ReloadCommandModule.java b/src/main/java/dev/esophose/playerparticles/command/ReloadCommandModule.java index 8a336bd0..5658435e 100644 --- a/src/main/java/dev/esophose/playerparticles/command/ReloadCommandModule.java +++ b/src/main/java/dev/esophose/playerparticles/command/ReloadCommandModule.java @@ -9,21 +9,24 @@ import dev.esophose.playerparticles.styles.DefaultStyles; import java.util.ArrayList; import java.util.List; +import org.bukkit.Bukkit; public class ReloadCommandModule implements CommandModule { public void onCommandExecute(PPlayer pplayer, String[] args) { PlayerParticles playerParticles = PlayerParticles.getInstance(); - LocaleManager localeManager = playerParticles.getManager(LocaleManager.class); - if (playerParticles.getManager(PermissionManager.class).canReloadPlugin(pplayer.getUnderlyingExecutor())) { - playerParticles.reload(); - ParticleEffect.reloadSettings(); - DefaultStyles.reloadSettings(playerParticles.getManager(ParticleStyleManager.class)); - localeManager.sendMessage(pplayer, "reload-success"); - playerParticles.getLogger().info("Reloaded configuration."); - } else { - localeManager.sendMessage(pplayer, "reload-no-permission"); - } + Bukkit.getScheduler().runTask(playerParticles, () -> { + LocaleManager localeManager = playerParticles.getManager(LocaleManager.class); + if (playerParticles.getManager(PermissionManager.class).canReloadPlugin(pplayer.getUnderlyingExecutor())) { + playerParticles.reload(); + ParticleEffect.reloadSettings(); + DefaultStyles.reloadSettings(playerParticles.getManager(ParticleStyleManager.class)); + localeManager.sendMessage(pplayer, "reload-success"); + playerParticles.getLogger().info("Reloaded configuration."); + } else { + localeManager.sendMessage(pplayer, "reload-no-permission"); + } + }); } public List onTabComplete(PPlayer pplayer, String[] args) { diff --git a/src/main/java/dev/esophose/playerparticles/gui/GuiInventory.java b/src/main/java/dev/esophose/playerparticles/gui/GuiInventory.java index 90062ecb..760f148e 100644 --- a/src/main/java/dev/esophose/playerparticles/gui/GuiInventory.java +++ b/src/main/java/dev/esophose/playerparticles/gui/GuiInventory.java @@ -1,10 +1,12 @@ package dev.esophose.playerparticles.gui; +import dev.esophose.playerparticles.PlayerParticles; import dev.esophose.playerparticles.manager.ConfigurationManager.Setting; import dev.esophose.playerparticles.particles.PPlayer; import dev.esophose.playerparticles.util.ParticleUtils; import java.util.ArrayList; import java.util.List; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -161,4 +163,8 @@ public void onClick(InventoryClickEvent event) { } } + public void close() { + Bukkit.getScheduler().runTask(PlayerParticles.getInstance(), () -> this.pplayer.getPlayer().closeInventory()); + } + } diff --git a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java index 454fa953..2f701a55 100644 --- a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java +++ b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java @@ -63,9 +63,8 @@ public GuiInventoryLoadPresetGroups(PPlayer pplayer, boolean isEndPoint) { } PlayerParticlesAPI.getInstance().savePlayerParticleGroup(pplayer.getPlayer(), activeGroup); - if (Setting.GUI_CLOSE_AFTER_GROUP_SELECTED.getBoolean()) { - pplayer.getPlayer().closeInventory(); - } + if (Setting.GUI_CLOSE_AFTER_GROUP_SELECTED.getBoolean()) + this.close(); }); this.actionButtons.add(groupButton); diff --git a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryManageGroups.java b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryManageGroups.java index cd0bbcb9..9a047b79 100644 --- a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryManageGroups.java +++ b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryManageGroups.java @@ -16,9 +16,9 @@ import dev.esophose.playerparticles.util.StringPlaceholders; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; public class GuiInventoryManageGroups extends GuiInventory { @@ -76,9 +76,8 @@ public GuiInventoryManageGroups(PPlayer pplayer) { activeGroup.getParticles().put(particle.getId(), particle.clone()); PlayerParticlesAPI.getInstance().savePlayerParticleGroup(pplayer.getPlayer(), activeGroup); - if (Setting.GUI_CLOSE_AFTER_GROUP_SELECTED.getBoolean()) { - pplayer.getPlayer().closeInventory(); - } + if (Setting.GUI_CLOSE_AFTER_GROUP_SELECTED.getBoolean()) + this.close(); } }); this.actionButtons.add(groupButton); @@ -138,7 +137,7 @@ public GuiInventoryManageGroups(PPlayer pplayer) { ParticleGroup group = pplayer.getParticleGroupByName(groupName); boolean groupUpdated = false; if (group == null) { - Map particles = new HashMap<>(); + Map particles = new ConcurrentHashMap<>(); for (ParticlePair particle : pplayer.getActiveParticles()) particles.put(particle.getId(), particle.clone()); // Make sure the ParticlePairs aren't the same references in both the active and saved group group = new ParticleGroup(groupName, particles); @@ -157,7 +156,7 @@ public GuiInventoryManageGroups(PPlayer pplayer) { guiManager.transition(new GuiInventoryManageGroups(pplayer)); } })); - pplayer.getPlayer().closeInventory(); + this.close(); }); this.actionButtons.add(saveGroupButton); diff --git a/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java b/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java index b8e94f80..618480f5 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java @@ -146,30 +146,34 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String return true; } - String[] cmdArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]; - - if (!commandModule.canConsoleExecute()) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Error: This command can only be executed by a player."); - return true; - } - } else if (sender instanceof ConsoleCommandSender) { - commandModule.onCommandExecute(PlayerParticlesAPI.getInstance().getConsolePPlayer(), cmdArgs); - return true; - } - - Player p = (Player) sender; - - this.playerParticles.getManager(DataManager.class).getPPlayer(p.getUniqueId(), (pplayer) -> { - PermissionManager permissionManager = PlayerParticles.getInstance().getManager(PermissionManager.class); - if (commandModule.requiresEffectsAndStyles() && (permissionManager.getEffectsUserHasPermissionFor(pplayer).isEmpty() || permissionManager.getStylesUserHasPermissionFor(pplayer).isEmpty())) { - localeManager.sendMessage(pplayer, "command-error-missing-effects-or-styles"); - } else { - commandModule.onCommandExecute(pplayer, cmdArgs); + Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, () -> { + String[] cmdArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]; + + if (!commandModule.canConsoleExecute()) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "Error: This command can only be executed by a player."); + return; + } + } else if (sender instanceof ConsoleCommandSender) { + commandModule.onCommandExecute(PlayerParticlesAPI.getInstance().getConsolePPlayer(), cmdArgs); + return; } + + Player p = (Player) sender; + + this.playerParticles.getManager(DataManager.class).getPPlayer(p.getUniqueId(), (pplayer) -> { + PermissionManager permissionManager = PlayerParticles.getInstance().getManager(PermissionManager.class); + if (commandModule.requiresEffectsAndStyles() && (permissionManager.getEffectsUserHasPermissionFor(pplayer).isEmpty() || permissionManager.getStylesUserHasPermissionFor(pplayer).isEmpty())) { + localeManager.sendMessage(pplayer, "command-error-missing-effects-or-styles"); + } else { + commandModule.onCommandExecute(pplayer, cmdArgs); + } + }); }); + + return true; } else if (cmd.getName().equalsIgnoreCase("ppo")) { - this.ppoCommand.onCommandExecute(sender, args); + Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, () -> this.ppoCommand.onCommandExecute(sender, args)); } return true; diff --git a/src/main/java/dev/esophose/playerparticles/manager/DataManager.java b/src/main/java/dev/esophose/playerparticles/manager/DataManager.java index e67f91e6..8939990b 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/DataManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/DataManager.java @@ -18,11 +18,11 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -106,8 +106,8 @@ public void getPPlayer(UUID playerUUID, Consumer callback) { } this.async(() -> { - Map groups = new HashMap<>(); - Map fixedParticles = new HashMap<>(); + Map groups = new ConcurrentHashMap<>(); + Map fixedParticles = new ConcurrentHashMap<>(); this.databaseConnector.connect((connection) -> { // Load settings @@ -133,9 +133,9 @@ public void getPPlayer(UUID playerUUID, Consumer callback) { } // Load particle groups - String groupQuery = "SELECT * FROM " + this.getTablePrefix() + "group g " + // @formatter:off + String groupQuery = "SELECT * FROM " + this.getTablePrefix() + "group g " + "JOIN " + this.getTablePrefix() + "particle p ON g.uuid = p.group_uuid " + - "WHERE g.owner_uuid = ?"; // @formatter:on + "WHERE g.owner_uuid = ?"; try (PreparedStatement statement = connection.prepareStatement(groupQuery)) { statement.setString(1, playerUUID.toString()); @@ -172,7 +172,7 @@ public void getPPlayer(UUID playerUUID, Consumer callback) { // Add the particle to a new group if one didn't already exist if (!groupAlreadyExists) { - HashMap particles = new HashMap<>(); + Map particles = new ConcurrentHashMap<>(); if (!invalid) particles.put(particle.getId(), particle); ParticleGroup newGroup = new ParticleGroup(groupName, particles); @@ -190,9 +190,9 @@ public void getPPlayer(UUID playerUUID, Consumer callback) { } // Load fixed effects - String fixedQuery = "SELECT f.id AS f_id, f.world, f.xPos, f.yPos, f.zPos, p.id AS p_id, p.effect, p.style, p.item_material, p.block_material, p.note, p.r, p.g, p.b FROM " + this.getTablePrefix() + "fixed f " + // @formatter:off + String fixedQuery = "SELECT f.id AS f_id, f.world, f.xPos, f.yPos, f.zPos, p.id AS p_id, p.effect, p.style, p.item_material, p.block_material, p.note, p.r, p.g, p.b FROM " + this.getTablePrefix() + "fixed f " + "JOIN " + this.getTablePrefix() + "particle p ON f.particle_uuid = p.uuid " + - "WHERE f.owner_uuid = ?"; // @formatter:on + "WHERE f.owner_uuid = ?"; try (PreparedStatement statement = connection.prepareStatement(fixedQuery)) { statement.setString(1, playerUUID.toString()); @@ -240,7 +240,7 @@ public void getPPlayer(UUID playerUUID, Consumer callback) { } if (!activeGroupExists) { - ParticleGroup activeGroup = new ParticleGroup(ParticleGroup.DEFAULT_NAME, new HashMap<>()); + ParticleGroup activeGroup = new ParticleGroup(ParticleGroup.DEFAULT_NAME, new ConcurrentHashMap<>()); this.saveParticleGroup(playerUUID, activeGroup); groups.put(activeGroup.getName(), activeGroup); } @@ -522,12 +522,16 @@ public void removeFixedEffect(UUID playerUUID, int id) { } /** - * Asynchronizes the callback with it's own thread + * Asynchronizes the callback with it's own thread unless it is already not on the main thread * * @param asyncCallback The callback to run on a separate thread */ private void async(Runnable asyncCallback) { - Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, asyncCallback); + if (Bukkit.isPrimaryThread()) { + Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, asyncCallback); + } else { + asyncCallback.run(); + } } /** diff --git a/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java b/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java index 033de715..02343c00 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java @@ -14,16 +14,20 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.scheduler.BukkitTask; public class GuiManager extends Manager implements Listener, Runnable { - private List guiInventories = new ArrayList<>(); - private BukkitTask guiTask = null; + private List guiInventories; + private BukkitTask guiTask; public GuiManager(PlayerParticles playerParticles) { super(playerParticles); + this.guiInventories = new ArrayList<>(); + this.guiTask = null; + Bukkit.getPluginManager().registerEvents(this, this.playerParticles); } @@ -41,46 +45,36 @@ public void disable() { /** * Ticks GuiInventories - * Removes entries from playerGuiInventories if the player no longer has the inventory open or is offline */ public void run() { - List toRemoveList = new ArrayList<>(); - - for (GuiInventory inventory : this.guiInventories) { - PPlayer pplayer = PlayerParticles.getInstance().getManager(DataManager.class).getPPlayer(inventory.getPPlayer().getUniqueId()); - if (pplayer == null) { - toRemoveList.add(inventory); - continue; - } - - Player player = Bukkit.getPlayer(inventory.getPPlayer().getUniqueId()); - if (player == null) { - toRemoveList.add(inventory); - continue; - } - - if (!inventory.getInventory().equals(player.getOpenInventory().getTopInventory())) { - toRemoveList.add(inventory); - continue; - } - - inventory.onTick(); - } - - for (GuiInventory inventory : toRemoveList) - this.guiInventories.remove(inventory); + this.guiInventories.forEach(GuiInventory::onTick); } @EventHandler(priority = EventPriority.HIGHEST) public void onInventoryClick(InventoryClickEvent event) { - if (!(event.getWhoClicked() instanceof Player)) return; - Player player = (Player)event.getWhoClicked(); - + if (!(event.getWhoClicked() instanceof Player)) + return; + + Player player = (Player) event.getWhoClicked(); GuiInventory inventory = this.getGuiInventory(player); - if (inventory == null) return; + if (inventory == null) + return; event.setCancelled(true); - inventory.onClick(event); + Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, () -> inventory.onClick(event)); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onInventoryClose(InventoryCloseEvent event) { + if (!(event.getPlayer() instanceof Player)) + return; + + Player player = (Player) event.getPlayer(); + GuiInventory inventory = this.getGuiInventory(player); + if (inventory == null) + return; + + this.guiInventories.remove(inventory); } /** @@ -114,8 +108,6 @@ public void forceCloseAllOpenGUIs() { * @param pplayer The PPlayer to open the GUI screen for */ public void openDefault(PPlayer pplayer) { - this.removeGuiInventory(pplayer); - GuiInventory inventoryToOpen; if (!Setting.GUI_PRESETS_ONLY.getBoolean()) { inventoryToOpen = new GuiInventoryDefault(pplayer); @@ -124,7 +116,7 @@ public void openDefault(PPlayer pplayer) { } this.guiInventories.add(inventoryToOpen); - pplayer.getPlayer().openInventory(inventoryToOpen.getInventory()); + Bukkit.getScheduler().runTask(this.playerParticles, () -> pplayer.getPlayer().openInventory(inventoryToOpen.getInventory())); } /** @@ -133,9 +125,8 @@ public void openDefault(PPlayer pplayer) { * @param nextInventory The GuiInventory to transition to */ public void transition(GuiInventory nextInventory) { - this.removeGuiInventory(nextInventory.getPPlayer()); this.guiInventories.add(nextInventory); - nextInventory.getPPlayer().getPlayer().openInventory(nextInventory.getInventory()); + Bukkit.getScheduler().runTask(this.playerParticles, () -> nextInventory.getPPlayer().getPlayer().openInventory(nextInventory.getInventory())); } /** @@ -145,10 +136,10 @@ public void transition(GuiInventory nextInventory) { * @return The GuiInventory belonging to the Player, if any */ private GuiInventory getGuiInventory(Player player) { - for (GuiInventory inventory : this.guiInventories) - if (inventory.getPPlayer().getUniqueId().equals(player.getUniqueId())) - return inventory; - return null; + return this.guiInventories.stream() + .filter(x -> x.getPPlayer().getUniqueId().equals(player.getUniqueId())) + .findFirst() + .orElse(null); } /** @@ -157,12 +148,7 @@ private GuiInventory getGuiInventory(Player player) { * @param pplayer The PPlayer who owns the GuiInventory */ private void removeGuiInventory(PPlayer pplayer) { - for (GuiInventory inventory : this.guiInventories) { - if (inventory.getPPlayer().getUniqueId().equals(pplayer.getUniqueId())) { - this.guiInventories.remove(inventory); - break; - } - } + this.guiInventories.removeIf(x -> x.getPPlayer().getUniqueId().equals(pplayer.getUniqueId())); } } diff --git a/src/main/java/dev/esophose/playerparticles/manager/ParticleManager.java b/src/main/java/dev/esophose/playerparticles/manager/ParticleManager.java index ce56e006..6474b59d 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/ParticleManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/ParticleManager.java @@ -13,11 +13,11 @@ import dev.esophose.playerparticles.styles.DefaultStyles; import java.awt.Color; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -35,23 +35,29 @@ public class ParticleManager extends Manager implements Listener, Runnable { /** * The map containing all the loaded PPlayer info */ - private Map particlePlayers = new HashMap<>(); + private final Map particlePlayers; /** * The task that spawns the particles */ - private BukkitTask particleTask = null; + private BukkitTask particleTask; /** * Rainbow particle effect hue and note color used for rainbow colorable effects */ - private int hue = 0; - private int note = 0; - private final Random random = new Random(); + private int hue; + private int note; + private final Random random; public ParticleManager(PlayerParticles playerParticles) { super(playerParticles); + this.particlePlayers = new ConcurrentHashMap<>(); + this.particleTask = null; + this.hue = 0; + this.note = 0; + this.random = new Random(); + Bukkit.getPluginManager().registerEvents(this, this.playerParticles); } @@ -62,7 +68,7 @@ public void reload() { Bukkit.getScheduler().runTaskLater(this.playerParticles, () -> { long ticks = Setting.TICKS_PER_PARTICLE.getLong(); - this.particleTask = Bukkit.getScheduler().runTaskTimer(this.playerParticles, this, 5, ticks); + this.particleTask = Bukkit.getScheduler().runTaskTimerAsynchronously(this.playerParticles, this, 5, ticks); }, 1); this.particlePlayers.clear(); diff --git a/src/main/java/dev/esophose/playerparticles/manager/PermissionManager.java b/src/main/java/dev/esophose/playerparticles/manager/PermissionManager.java index 5a70a138..50943d59 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/PermissionManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/PermissionManager.java @@ -77,6 +77,10 @@ public PermissionManager(PlayerParticles playerParticles) { // Register plugin permissions to Bukkit PluginManager pluginManager = Bukkit.getPluginManager(); + // Don't register the permissions if we already have, could have happened because of a reload? + if (pluginManager.getPermission("playerparticles.*") != null) + return; + Set allPermissions = new HashSet<>(); // Effects diff --git a/src/main/java/dev/esophose/playerparticles/particles/OtherPPlayer.java b/src/main/java/dev/esophose/playerparticles/particles/OtherPPlayer.java index 40defb97..f84a30f6 100644 --- a/src/main/java/dev/esophose/playerparticles/particles/OtherPPlayer.java +++ b/src/main/java/dev/esophose/playerparticles/particles/OtherPPlayer.java @@ -1,6 +1,6 @@ package dev.esophose.playerparticles.particles; -import java.util.HashMap; +import java.util.Collections; import java.util.UUID; import org.bukkit.command.CommandSender; @@ -9,7 +9,7 @@ public class OtherPPlayer extends PPlayer { private CommandSender sender; public OtherPPlayer(CommandSender sender) { - super(UUID.randomUUID(), new HashMap<>(), new HashMap<>(), false); + super(UUID.randomUUID(), Collections.emptyMap(), Collections.emptyMap(), false); this.sender = sender; } diff --git a/src/main/java/dev/esophose/playerparticles/particles/ParticleGroup.java b/src/main/java/dev/esophose/playerparticles/particles/ParticleGroup.java index c6f1407f..224662c0 100644 --- a/src/main/java/dev/esophose/playerparticles/particles/ParticleGroup.java +++ b/src/main/java/dev/esophose/playerparticles/particles/ParticleGroup.java @@ -2,8 +2,8 @@ import dev.esophose.playerparticles.PlayerParticles; import dev.esophose.playerparticles.manager.PermissionManager; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class ParticleGroup { @@ -42,7 +42,7 @@ public Map getParticles() { * @return The default empty active ParticleGroup */ public static ParticleGroup getDefaultGroup() { - return new ParticleGroup(DEFAULT_NAME, new HashMap<>()); + return new ParticleGroup(DEFAULT_NAME, new ConcurrentHashMap<>()); } /** diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java index e52f19b4..e24a17b6 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java @@ -1,8 +1,6 @@ package dev.esophose.playerparticles.styles; -import dev.esophose.playerparticles.PlayerParticles; import dev.esophose.playerparticles.config.CommentedFileConfiguration; -import dev.esophose.playerparticles.manager.ParticleManager; import dev.esophose.playerparticles.particles.PParticle; import dev.esophose.playerparticles.particles.ParticlePair; import java.util.ArrayList; @@ -17,17 +15,15 @@ public class ParticleStyleArrows extends DefaultParticleStyle implements Listener { - private List arrows = new ArrayList<>(); + private List projectiles = new ArrayList<>(); private int maxArrowsPerPlayer; private boolean onlySpawnIfFlying; - private List arrowEntityNames; - private ParticleManager particleManager; + private List projectileEntityNames; + private int arrowTrackingTime; public ParticleStyleArrows() { super("arrows", false, false, 0); - - this.particleManager = PlayerParticles.getInstance().getManager(ParticleManager.class); } @Override @@ -35,13 +31,13 @@ public List getParticles(ParticlePair particle, Location location) { List particles = new ArrayList<>(); int count = 0; - for (int i = this.arrows.size() - 1; i >= 0; i--) { // Loop backwards so the last-fired arrows are the ones that have particles if they go over the max - Projectile arrow = this.arrows.get(i); - if (this.onlySpawnIfFlying && arrow.isOnGround()) + for (int i = this.projectiles.size() - 1; i >= 0; i--) { // Loop backwards so the last-fired projectiles are the ones that have particles if they go over the max + Projectile projectile = this.projectiles.get(i); + if (this.onlySpawnIfFlying && projectile.isOnGround()) continue; - if (arrow.getShooter() != null && ((Player) arrow.getShooter()).getUniqueId().equals(particle.getOwnerUniqueId())) { - particles.add(new PParticle(arrow.getLocation(), 0.05F, 0.05F, 0.05F, 0.0F)); + if (projectile.getShooter() != null && ((Player) projectile.getShooter()).getUniqueId().equals(particle.getOwnerUniqueId())) { + particles.add(new PParticle(projectile.getLocation(), 0.05F, 0.05F, 0.05F, 0.0F)); count++; } @@ -57,10 +53,10 @@ public List getParticles(ParticlePair particle, Location location) { */ @Override public void updateTimers() { - for (int i = this.arrows.size() - 1; i >= 0; i--) { - Projectile arrow = this.arrows.get(i); - if (arrow.getTicksLived() >= 1200 || arrow.isDead() || !arrow.isValid() || arrow.getShooter() == null) - this.arrows.remove(i); + for (int i = this.projectiles.size() - 1; i >= 0; i--) { + Projectile projectile = this.projectiles.get(i); + if ((this.arrowTrackingTime != -1 && projectile.getTicksLived() >= this.arrowTrackingTime) || projectile.isDead() || !projectile.isValid() || projectile.getShooter() == null) + this.projectiles.remove(i); } } @@ -81,8 +77,8 @@ public void onProjectileLaunch(ProjectileLaunchEvent event) { return; String entityName = event.getEntity().getType().name(); - if (this.arrowEntityNames.contains(entityName)) - this.arrows.add(event.getEntity()); + if (this.projectileEntityNames.contains(entityName)) + this.projectiles.add(event.getEntity()); } @Override @@ -90,13 +86,15 @@ protected void setDefaultSettings(CommentedFileConfiguration config) { this.setIfNotExists("max-arrows-per-player", 10, "The max number of arrows that will spawn particles per player"); this.setIfNotExists("only-spawn-if-flying", false, "Only spawn particles while the arrow is still in the air"); this.setIfNotExists("arrow-entities", Arrays.asList("ARROW", "SPECTRAL_ARROW", "TIPPED_ARROW"), "The name of the projectile entities that are counted as arrows"); + this.setIfNotExists("arrow-tracking-time", 1200, "The maximum number of ticks to track an arrow for", "Set to -1 to disable (not recommended)"); } @Override protected void loadSettings(CommentedFileConfiguration config) { this.maxArrowsPerPlayer = config.getInt("max-arrows-per-player"); this.onlySpawnIfFlying = config.getBoolean("only-spawn-if-flying"); - this.arrowEntityNames = config.getStringList("arrow-entities"); + this.projectileEntityNames = config.getStringList("arrow-entities"); + this.arrowTrackingTime = config.getInt("arrow-tracking-time"); } } diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java index 647fb1db..cc619277 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java @@ -62,11 +62,11 @@ public void updateTimers() { if (player != null && player.getGameMode() != GameMode.SPECTATOR && permissionManager.isWorldEnabled(player.getWorld().getName())) for (ParticlePair particle : pplayer.getActiveParticles()) if (particle.getStyle() == this) - this.spawnFirework(player.getLocation(), pplayer, particle, random); + this.spawnFirework(player.getLocation(), pplayer, pplayer.getPlayer(), particle, random); for (FixedParticleEffect fixedEffect : pplayer.getFixedParticles()) if (fixedEffect.getParticlePair().getStyle() == this && permissionManager.isWorldEnabled(fixedEffect.getLocation().getWorld().getName())) - this.spawnFirework(fixedEffect.getLocation(), pplayer, fixedEffect.getParticlePair(), random); + this.spawnFirework(fixedEffect.getLocation(), pplayer, null, fixedEffect.getParticlePair(), random); } } } @@ -102,14 +102,13 @@ protected void loadSettings(CommentedFileConfiguration config) { this.fuseEffect = ParticleEffect.FIREWORK; } - private void spawnFirework(final Location location, final PPlayer pplayer, final ParticlePair particle, final Random random) { + private void spawnFirework(final Location location, final PPlayer pplayer, final Player player, final ParticlePair particle, final Random random) { double angle = random.nextDouble() * Math.PI * 2; double distanceFrom = this.baseDistanceFrom + random.nextDouble() * this.distanceFromRandomizer; double dx = MathL.sin(angle) * distanceFrom; double dz = MathL.cos(angle) * distanceFrom; final Location loc = location.clone().add(dx, 1, dz); final int fuse = this.baseFuseLength + random.nextInt(this.fuseLengthRandomizer); - Player player = pplayer.getPlayer(); ParticleManager particleManager = PlayerParticles.getInstance().getManager(ParticleManager.class); new BukkitRunnable() { diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java index 9ea856a2..b65ba394 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java @@ -53,12 +53,12 @@ protected void loadSettings(CommentedFileConfiguration config) { public void onPlayerMove(PlayerMoveEvent event) { ParticleManager particleManager = PlayerParticles.getInstance().getManager(ParticleManager.class); - PPlayer pplayer = PlayerParticles.getInstance().getManager(DataManager.class).getPPlayer(event.getPlayer().getUniqueId()); + Player player = event.getPlayer(); + PPlayer pplayer = PlayerParticles.getInstance().getManager(DataManager.class).getPPlayer(player.getUniqueId()); if (pplayer != null) { for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.MOVE)) { - Location loc = event.getPlayer().getLocation().clone(); + Location loc = player.getLocation().clone(); loc.setY(loc.getY() + 0.05); - Player player = event.getPlayer(); particleManager.displayParticles(player, player.getWorld(), particle, DefaultStyles.MOVE.getParticles(particle, loc), false); } }