diff --git a/build.gradle b/build.gradle index 94568c5..10720f3 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ sourceCompatibility = 1.8 targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' group = 'dev.esophose' -version = '7.25' +version = '8.0-SNAPSHOT' java { withJavadocJar() @@ -27,15 +27,15 @@ repositories { } dependencies { - api 'org.slf4j:slf4j-api:1.7.25' - api 'org.slf4j:slf4j-nop:1.7.25' + compileOnly 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT' + compileOnly 'org.jetbrains:annotations:23.0.0' + compileOnly 'me.clip:placeholderapi:2.10.4' + compileOnly 'org.xerial:sqlite-jdbc:3.36.0.3' + api 'org.slf4j:slf4j-api:1.7.36' + api 'org.slf4j:slf4j-nop:1.7.36' api 'com.zaxxer:HikariCP:3.2.0' api 'org.bstats:bstats-bukkit-lite:1.7' api 'org.codemc.worldguardwrapper:worldguardwrapper:1.2.0-SNAPSHOT' - compileOnly 'org.jetbrains:annotations:16.0.2' - compileOnly 'me.clip:placeholderapi:2.10.4' - compileOnly 'org.xerial:sqlite-jdbc:3.23.1' - compileOnly 'org.spigotmc:spigot-api:1.18.1-R0.1-SNAPSHOT' } shadowJar { @@ -60,33 +60,22 @@ publishing { publications { shadow(MavenPublication) { publication -> project.shadow.component(publication) - } - mavenJava(MavenPublication) { artifactId = 'playerparticles' - from components.java - versionMapping { - usage('java-api') { - fromResolutionOf('runtimeClasspath') - } - usage('java-runtime') { - fromResolutionResult() - } - } pom { name = 'playerparticles' } } } repositories { - if (project.hasProperty('mavenUsername') && project.hasProperty('mavenPassword')) { + if (project.hasProperty('mavenUser') && project.hasProperty('mavenPassword')) { maven { credentials { - username project.mavenUsername + username project.mavenUser password project.mavenPassword } - def releasesRepoUrl = 'https://repo.codemc.org/repository/maven-releases/' - def snapshotsRepoUrl = 'https://repo.codemc.org/repository/maven-snapshots/' + def releasesRepoUrl = 'https://repo.rosewooddev.io/repository/public-releases/' + def snapshotsRepoUrl = 'https://repo.rosewooddev.io/repository/public-snapshots/' url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl } } diff --git a/changelog.txt b/changelog.txt index 94a47a7..d16829f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +=== v8.0 === ++ Added support for Particle Packs ++ Added setting toggle-on-combat-include-mobs +* Fixed particle effects now save the pitch/yaw of the player when they are created +* Fixed an error when doing /pp reload if a player has the GUI open +* The icosphere style now fades between dust colors when using the dust_color_transition effect === v7.24 === * Fixed configs not generating properly on newer versions of 1.18.1 === v7.23 === diff --git a/src/main/java/dev/esophose/playerparticles/PlayerParticles.java b/src/main/java/dev/esophose/playerparticles/PlayerParticles.java index 064de64..d20a2cf 100644 --- a/src/main/java/dev/esophose/playerparticles/PlayerParticles.java +++ b/src/main/java/dev/esophose/playerparticles/PlayerParticles.java @@ -19,6 +19,7 @@ import dev.esophose.playerparticles.manager.LocaleManager; import dev.esophose.playerparticles.manager.Manager; import dev.esophose.playerparticles.manager.ParticleGroupPresetManager; import dev.esophose.playerparticles.manager.ParticleManager; +import dev.esophose.playerparticles.manager.ParticlePackManager; import dev.esophose.playerparticles.manager.ParticleStyleManager; import dev.esophose.playerparticles.manager.PermissionManager; import dev.esophose.playerparticles.manager.PluginUpdateManager; @@ -70,9 +71,8 @@ public class PlayerParticles extends JavaPlugin { pm.registerEvents(new PPlayerCombatListener(), this); pm.registerEvents(new PlayerChatHook(), this); - if (Setting.SEND_METRICS.getBoolean()) - if (NMSUtil.getVersionNumber() > 7) - new MetricsLite(this, 3531); + if (Setting.SEND_METRICS.getBoolean() && NMSUtil.getVersionNumber() > 7) + new MetricsLite(this, 3531); if (PlaceholderAPIHook.enabled()) new ParticlePlaceholderExpansion(this).register(); @@ -128,6 +128,7 @@ public class PlayerParticles extends JavaPlugin { this.getManager(ConfigurationManager.class); this.getManager(LocaleManager.class); + this.getManager(ParticlePackManager.class); this.getManager(DataManager.class); this.getManager(PermissionManager.class); this.getManager(CommandManager.class); diff --git a/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java b/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java index af74347..0642903 100644 --- a/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java +++ b/src/main/java/dev/esophose/playerparticles/api/PlayerParticlesAPI.java @@ -865,7 +865,7 @@ public final class PlayerParticlesAPI { if (fixedEffect == null) return null; - fixedEffect.setCoordinates(location.getX(), location.getY(), location.getZ()); + fixedEffect.setCoordinates(location); dataManager.saveFixedEffect(fixedEffect); return fixedEffect; } diff --git a/src/main/java/dev/esophose/playerparticles/command/FixedCommandModule.java b/src/main/java/dev/esophose/playerparticles/command/FixedCommandModule.java index 88fa677..cf94747 100644 --- a/src/main/java/dev/esophose/playerparticles/command/FixedCommandModule.java +++ b/src/main/java/dev/esophose/playerparticles/command/FixedCommandModule.java @@ -151,6 +151,9 @@ public class FixedCommandModule implements CommandModule { } if (player != null) { + location.setYaw(player.getLocation().getYaw()); + location.setPitch(player.getLocation().getPitch()); + double distanceFromEffect = player.getLocation().distance(location); int maxCreationDistance = permissionManager.getMaxFixedEffectCreationDistance(); if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) { @@ -292,6 +295,9 @@ public class FixedCommandModule implements CommandModule { } if (player != null) { + location.setYaw(player.getLocation().getYaw()); + location.setPitch(player.getLocation().getPitch()); + double distanceFromEffect = player.getLocation().distance(location); int maxCreationDistance = permissionManager.getMaxFixedEffectCreationDistance(); if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) { @@ -300,7 +306,7 @@ public class FixedCommandModule implements CommandModule { } } - fixedEffect.setCoordinates(location.getX(), location.getY(), location.getZ()); + fixedEffect.setCoordinates(location); break; case "effect": { ParticleEffect effect = inputParser.next(ParticleEffect.class); diff --git a/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java b/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java index add56c4..a02da36 100644 --- a/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java +++ b/src/main/java/dev/esophose/playerparticles/command/GroupCommandModule.java @@ -40,28 +40,28 @@ public class GroupCommandModule implements CommandModule { } switch (args[0].toLowerCase()) { - case "save": - this.onSave(pplayer, args[1].toLowerCase()); - break; - case "load": - this.onLoad(pplayer, args[1].toLowerCase()); - break; - case "remove": - this.onRemove(pplayer, args[1].toLowerCase()); - break; - case "info": - this.onInfo(pplayer, args[1].toLowerCase()); - break; - case "list": - this.onList(pplayer); - break; - default: - localeManager.sendMessage(pplayer, "command-description-group-save"); - localeManager.sendMessage(pplayer, "command-description-group-load"); - localeManager.sendMessage(pplayer, "command-description-group-remove"); - localeManager.sendMessage(pplayer, "command-description-group-info"); - localeManager.sendMessage(pplayer, "command-description-group-list"); - break; + case "save": + this.onSave(pplayer, args[1].toLowerCase()); + break; + case "load": + this.onLoad(pplayer, args[1].toLowerCase()); + break; + case "remove": + this.onRemove(pplayer, args[1].toLowerCase()); + break; + case "info": + this.onInfo(pplayer, args[1].toLowerCase()); + break; + case "list": + this.onList(pplayer); + break; + default: + localeManager.sendMessage(pplayer, "command-description-group-save"); + localeManager.sendMessage(pplayer, "command-description-group-load"); + localeManager.sendMessage(pplayer, "command-description-group-remove"); + localeManager.sendMessage(pplayer, "command-description-group-info"); + localeManager.sendMessage(pplayer, "command-description-group-list"); + break; } } @@ -163,10 +163,11 @@ public class GroupCommandModule implements CommandModule { // Update group and notify player PlayerParticlesAPI.getInstance().savePlayerParticleGroup(pplayer.getPlayer(), activeGroup); - if (!isPreset) + if (!isPreset) { localeManager.sendMessage(pplayer, "group-load-success", StringPlaceholders.builder("amount", activeGroup.getParticles().size()).addPlaceholder("name", groupName).build()); - else + } else { localeManager.sendMessage(pplayer, "group-load-preset-success", StringPlaceholders.builder("amount", activeGroup.getParticles().size()).addPlaceholder("name", groupName).build()); + } } /** diff --git a/src/main/java/dev/esophose/playerparticles/database/migrations/_4_Add_Fixed_Effect_Yaw_Pitch_Columns.java b/src/main/java/dev/esophose/playerparticles/database/migrations/_4_Add_Fixed_Effect_Yaw_Pitch_Columns.java new file mode 100644 index 0000000..9e78377 --- /dev/null +++ b/src/main/java/dev/esophose/playerparticles/database/migrations/_4_Add_Fixed_Effect_Yaw_Pitch_Columns.java @@ -0,0 +1,24 @@ +package dev.esophose.playerparticles.database.migrations; + +import dev.esophose.playerparticles.database.DataMigration; +import dev.esophose.playerparticles.database.DatabaseConnector; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class _4_Add_Fixed_Effect_Yaw_Pitch_Columns extends DataMigration { + + public _4_Add_Fixed_Effect_Yaw_Pitch_Columns() { + super(4); + } + + @Override + public void migrate(DatabaseConnector connector, Connection connection, String tablePrefix) throws SQLException { + try (Statement statement = connection.createStatement()) { + statement.executeUpdate("ALTER TABLE " + tablePrefix + "fixed ADD COLUMN yaw DOUBLE DEFAULT 0"); + statement.executeUpdate("ALTER TABLE " + tablePrefix + "fixed ADD COLUMN pitch DOUBLE DEFAULT 0"); + } + } + +} + diff --git a/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java b/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java index 1669270..a91793f 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/CommandManager.java @@ -23,6 +23,7 @@ import dev.esophose.playerparticles.command.ToggleCommandModule; import dev.esophose.playerparticles.command.UseCommandModule; import dev.esophose.playerparticles.command.VersionCommandModule; import dev.esophose.playerparticles.command.WorldsCommandModule; +import dev.esophose.playerparticles.hook.PlaceholderAPIHook; import dev.esophose.playerparticles.particles.PPlayer; import dev.esophose.playerparticles.util.ParticleUtils; import java.util.ArrayList; @@ -178,7 +179,11 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl return true; } else if (cmd.getName().equalsIgnoreCase("ppo")) { - Bukkit.getScheduler().runTask(this.playerParticles, () -> this.ppoCommand.onCommandExecute(sender, args)); + String[] replacedArgs = new String[args.length]; + Player player = sender instanceof Player ? (Player) sender : null; + for (int i = 0; i < args.length; i++) + replacedArgs[i] = PlaceholderAPIHook.applyPlaceholders(player, args[i]); + Bukkit.getScheduler().runTask(this.playerParticles, () -> this.ppoCommand.onCommandExecute(sender, replacedArgs)); } return true; diff --git a/src/main/java/dev/esophose/playerparticles/manager/ConfigurationManager.java b/src/main/java/dev/esophose/playerparticles/manager/ConfigurationManager.java index 8b8bbd3..63a10d9 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/ConfigurationManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/ConfigurationManager.java @@ -48,6 +48,7 @@ public class ConfigurationManager extends Manager { TOGGLE_ON_MOVE_DELAY("toggle-on-move-delay", 9, "The time (in ticks) a player has to be standing still before they are considered to be stopped", "This setting has no effect if toggle-on-move is set to false", "The value must be a positive whole number"), TOGGLE_ON_COMBAT("toggle-on-combat", false, "If true, particles will be completely disabled while the player is in combat", "Note: You can change what styles follow this setting in their individual setting files"), TOGGLE_ON_COMBAT_DELAY("toggle-on-combat-delay", 15, "The time (in seconds) a player has to not be damaged/attacked to be considered out of combat", "This setting has no effect if toggle-on-combat is set to false", "The value must be a positive whole number"), + TOGGLE_ON_COMBAT_INCLUDE_MOBS("toggle-on-combat-include-mobs", false, "If true, mobs will be included in the combat check in addition to players"), DISABLED_WORLDS("disabled-worlds", Collections.singletonList("disabled_world_name"), "A list of worlds that the plugin is disabled in"), CHECK_PERMISSIONS_ON_LOGIN("check-permissions-on-login", false, "Should particles a player no longer has permission to use be removed on login?"), MAX_PARTICLES("max-particles", 3, "The maximum number of particles a player can apply at once", "The GUI will only display up to 21, don't set this any higher than that"), diff --git a/src/main/java/dev/esophose/playerparticles/manager/DataManager.java b/src/main/java/dev/esophose/playerparticles/manager/DataManager.java index e54f414..efb685e 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/DataManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/DataManager.java @@ -103,7 +103,6 @@ public class DataManager extends Manager { * @param callback The callback to execute with the found pplayer, or a newly generated one */ public void getPPlayer(UUID playerUUID, Consumer callback) { - // Try to get them from cache first PPlayer fromCache = this.getPPlayer(playerUUID); if (fromCache != null) { @@ -201,7 +200,7 @@ public class DataManager extends Manager { } // 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, p.r_end, p.g_end, p.b_end, p.duration FROM " + this.getTablePrefix() + "fixed f " + + String fixedQuery = "SELECT f.id AS f_id, f.world, f.xPos, f.yPos, f.zPos, f.yaw, f.pitch, p.id AS p_id, p.effect, p.style, p.item_material, p.block_material, p.note, p.r, p.g, p.b, p.r_end, p.g_end, p.b_end, p.duration FROM " + this.getTablePrefix() + "fixed f " + "JOIN " + this.getTablePrefix() + "particle p ON f.particle_uuid = p.uuid " + "WHERE f.owner_uuid = ?"; try (PreparedStatement statement = connection.prepareStatement(fixedQuery)) { @@ -214,6 +213,8 @@ public class DataManager extends Manager { double xPos = result.getDouble("xPos"); double yPos = result.getDouble("yPos"); double zPos = result.getDouble("zPos"); + double yaw = result.getDouble("yaw"); + double pitch = result.getDouble("pitch"); World world = Bukkit.getWorld(result.getString("world")); if (world == null) { // World was deleted, remove the fixed effect as it is no longer valid @@ -241,7 +242,7 @@ public class DataManager extends Manager { continue; } - fixedParticles.put(fixedEffectId, new FixedParticleEffect(playerUUID, fixedEffectId, new Location(world, xPos, yPos, zPos), particle)); + fixedParticles.put(fixedEffectId, new FixedParticleEffect(playerUUID, fixedEffectId, new Location(world, xPos, yPos, zPos, (float) yaw, (float) pitch), particle)); } } @@ -492,7 +493,7 @@ public class DataManager extends Manager { statement.executeUpdate(); } - String fixedEffectQuery = "INSERT INTO " + this.getTablePrefix() + "fixed (owner_uuid, id, particle_uuid, world, xPos, yPos, zPos) VALUES (?, ?, ?, ?, ?, ?, ?)"; + String fixedEffectQuery = "INSERT INTO " + this.getTablePrefix() + "fixed (owner_uuid, id, particle_uuid, world, xPos, yPos, zPos, yaw, pitch) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; try (PreparedStatement statement = connection.prepareStatement(fixedEffectQuery)) { statement.setString(1, fixedEffect.getOwnerUniqueId().toString()); statement.setInt(2, fixedEffect.getId()); @@ -501,6 +502,8 @@ public class DataManager extends Manager { statement.setDouble(5, fixedEffect.getLocation().getX()); statement.setDouble(6, fixedEffect.getLocation().getY()); statement.setDouble(7, fixedEffect.getLocation().getZ()); + statement.setDouble(8, fixedEffect.getLocation().getYaw()); + statement.setDouble(9, fixedEffect.getLocation().getPitch()); statement.executeUpdate(); } })); @@ -514,13 +517,15 @@ public class DataManager extends Manager { public void updateFixedEffect(FixedParticleEffect fixedEffect) { this.async(() -> this.databaseConnector.connect((connection) -> { // Update fixed effect - String fixedEffectQuery = "UPDATE " + this.getTablePrefix() + "fixed SET xPos = ?, yPos = ?, zPos = ? WHERE owner_uuid = ? AND id = ?"; + String fixedEffectQuery = "UPDATE " + this.getTablePrefix() + "fixed SET xPos = ?, yPos = ?, zPos = ?, yaw = ?, pitch = ? WHERE owner_uuid = ? AND id = ?"; try (PreparedStatement statement = connection.prepareStatement(fixedEffectQuery)) { statement.setDouble(1, fixedEffect.getLocation().getX()); statement.setDouble(2, fixedEffect.getLocation().getY()); statement.setDouble(3, fixedEffect.getLocation().getZ()); - statement.setString(4, fixedEffect.getOwnerUniqueId().toString()); - statement.setInt(5, fixedEffect.getId()); + statement.setDouble(4, fixedEffect.getLocation().getYaw()); + statement.setDouble(5, fixedEffect.getLocation().getPitch()); + statement.setString(6, fixedEffect.getOwnerUniqueId().toString()); + statement.setInt(7, fixedEffect.getId()); statement.executeUpdate(); } @@ -589,7 +594,7 @@ public class DataManager extends Manager { } /** - * Asynchronizes the callback with it's own thread unless it is already not on the main thread + * Asynchronizes the callback with its own thread unless it is already not on the main thread * * @param asyncCallback The callback to run on a separate thread */ diff --git a/src/main/java/dev/esophose/playerparticles/manager/DataMigrationManager.java b/src/main/java/dev/esophose/playerparticles/manager/DataMigrationManager.java index afa14b2..59679e5 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/DataMigrationManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/DataMigrationManager.java @@ -7,6 +7,7 @@ import dev.esophose.playerparticles.database.SQLiteConnector; import dev.esophose.playerparticles.database.migrations._1_InitialMigration; import dev.esophose.playerparticles.database.migrations._2_Add_Data_Columns; import dev.esophose.playerparticles.database.migrations._3_Add_Setting_Toggle_Self_Column; +import dev.esophose.playerparticles.database.migrations._4_Add_Fixed_Effect_Yaw_Pitch_Columns; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Arrays; @@ -24,7 +25,8 @@ public class DataMigrationManager extends Manager { this.migrations = Arrays.asList( new _1_InitialMigration(), new _2_Add_Data_Columns(), - new _3_Add_Setting_Toggle_Self_Column() + new _3_Add_Setting_Toggle_Self_Column(), + new _4_Add_Fixed_Effect_Yaw_Pitch_Columns() ); } diff --git a/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java b/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java index 51f0b07..5088637 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/GuiManager.java @@ -94,15 +94,22 @@ public class GuiManager extends Manager implements Listener, Runnable { * Used for when the plugin unloads so players can't take items from the GUI */ public void forceCloseAllOpenGUIs() { + List toClose = new ArrayList<>(); for (Player player : Bukkit.getOnlinePlayers()) { for (GuiInventory inventory : this.guiInventories) { if (inventory.getPPlayer().getUniqueId().equals(player.getUniqueId()) && inventory.getInventory().equals(player.getOpenInventory().getTopInventory())) { - player.closeInventory(); + toClose.add(player); break; } } } this.guiInventories.clear(); + + if (Bukkit.isPrimaryThread()) { + toClose.forEach(Player::closeInventory); + } else { + Bukkit.getScheduler().runTask(this.playerParticles, x -> toClose.forEach(Player::closeInventory)); + } } /** diff --git a/src/main/java/dev/esophose/playerparticles/manager/ParticlePackManager.java b/src/main/java/dev/esophose/playerparticles/manager/ParticlePackManager.java new file mode 100644 index 0000000..5486cb6 --- /dev/null +++ b/src/main/java/dev/esophose/playerparticles/manager/ParticlePackManager.java @@ -0,0 +1,242 @@ +package dev.esophose.playerparticles.manager; + +import dev.esophose.playerparticles.PlayerParticles; +import dev.esophose.playerparticles.pack.ParticlePack; +import dev.esophose.playerparticles.pack.ParticlePackDescription; +import dev.esophose.playerparticles.pack.ParticlePackInitializationException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +public class ParticlePackManager extends Manager { + + public static final String PACK_DIRECTORY_NAME = "packs"; + public static final String INFO_FILE_NAME = "particle_pack.yml"; + private final Map loadedPacks; + + public ParticlePackManager(PlayerParticles playerParticles) { + super(playerParticles); + this.loadedPacks = new HashMap<>(); + } + + @Override + public void reload() { + this.moveParticlePacksFromPluginsFolder(); + + File packDirectory = new File(this.playerParticles.getDataFolder(), PACK_DIRECTORY_NAME); + if (!packDirectory.exists()) + packDirectory.mkdirs(); + + File[] files = packDirectory.listFiles(); + if (files == null || files.length == 0) + return; + + for (File file : files) { + if (!file.isFile() || !file.getName().endsWith(".jar") || !this.isParticlePack(file)) + continue; + + ParticlePack particlePack = this.load(file); + if (particlePack == null) + continue; + + ParticlePackDescription description = particlePack.getDescription(); + if (description.getName() == null || description.getName().isEmpty()) { + this.playerParticles.getLogger().warning("Particle pack '" + file.getName() + "' has no name, skipping!"); + continue; + } + + if (description.getVersion() == null || description.getVersion().isEmpty()) { + this.playerParticles.getLogger().warning("Particle pack '" + description.getName() + "' has no version, skipping!"); + continue; + } + + ParticlePack possibleDuplicate = this.getParticlePack(description.getName()); + if (possibleDuplicate != null) { + this.playerParticles.getLogger().warning("Found duplicate particle pack '" + description.getName() + "', overwriting!"); + this.loadedPacks.values().remove(possibleDuplicate); + } + + this.loadedPacks.put(particlePack.getName(), particlePack); + this.playerParticles.getLogger().info("Loaded particle pack '" + particlePack.getName() + " v" + particlePack.getDescription().getVersion() + "' with " + particlePack.getNumberOfStyles() + " style" + (particlePack.getNumberOfStyles() > 1 ? "s" : "")); + } + + int numStyles = this.loadedPacks.values().stream().mapToInt(ParticlePack::getNumberOfStyles).sum(); + this.playerParticles.getLogger().info("Loaded " + this.loadedPacks.size() + " particle pack" + (this.loadedPacks.size() > 1 ? "s" : "") + " with " + numStyles + " style" + (numStyles > 1 ? "s" : "")); + } + + @Override + public void disable() { + this.loadedPacks.values().forEach(particlePack -> { + try { + particlePack.getClassLoader().close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + this.loadedPacks.clear(); + } + + /** + * Gets the particle pack with the given name, case-insensitive + * + * @param packName The name of the particle pack + * @return The particle pack with the given name, or null if not found + */ + public ParticlePack getParticlePack(String packName) { + return this.loadedPacks.entrySet().stream() + .filter(x -> x.getKey().equalsIgnoreCase(packName)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + } + + /** + * @return A collection of all loaded particle packs + */ + public Collection getLoadedParticlePacks() { + return this.loadedPacks.values(); + } + + /** + * Attempts to load a particle pack from the given file + * + * @param packJar The file to load the particle pack from + * @return The loaded particle pack, or null if the file is not a valid particle pack + */ + public ParticlePack load(File packJar) { + try { + URL jar = packJar.toURI().toURL(); + URLClassLoader classLoader = new URLClassLoader(new URL[]{jar}, this.getClass().getClassLoader()); + List matches = new ArrayList<>(); + List> classes = new ArrayList<>(); + + try (JarInputStream jarInputStream = new JarInputStream(jar.openStream())) { + JarEntry entry; + while ((entry = jarInputStream.getNextJarEntry()) != null) { + String name = entry.getName(); + if (name.endsWith(".class")) + matches.add(name.substring(0, name.lastIndexOf('.')).replace('/', '.')); + } + } + + for (String match : matches) { + try { + Class clazz = classLoader.loadClass(match); + if (ParticlePack.class.isAssignableFrom(clazz)) + classes.add(clazz.asSubclass(ParticlePack.class)); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + if (classes.isEmpty()) { + this.playerParticles.getLogger().warning("Failed to load particle pack " + packJar.getName() + ": No particle pack found"); + classLoader.close(); + return null; + } + + if (classes.size() > 1) { + this.playerParticles.getLogger().warning("Failed to load particle pack " + packJar.getName() + ": Multiple particle packs found"); + return null; + } + + try (InputStream inputStream = new URL("jar:file:" + packJar.getAbsolutePath() + "!/" + INFO_FILE_NAME).openStream(); + Reader fileReader = new InputStreamReader(inputStream)) { + FileConfiguration particlePackConfig = YamlConfiguration.loadConfiguration(fileReader); + ParticlePack particlePack = classes.get(0).getDeclaredConstructor().newInstance(); + Method initMethod = ParticlePack.class.getDeclaredMethod("init", PlayerParticles.class, ParticlePackDescription.class, URLClassLoader.class); + initMethod.setAccessible(true); + initMethod.invoke(particlePack, this.playerParticles, new ParticlePackDescription(particlePackConfig), classLoader); + return particlePack; + } + } catch (Exception e) { + throw new ParticlePackInitializationException(packJar.getName(), e); + } + } + + /** + * Attempts to unload a particle pack with the given name + * + * @param packName The name of the particle pack to unload + * @return True if the particle pack was unloaded, false if it was not found or something went wrong + */ + public boolean unload(String packName) { + ParticlePack particlePack = this.getParticlePack(packName); + if (particlePack == null) + return false; + + try { + ParticleStyleManager particleStyleManager = this.playerParticles.getManager(ParticleStyleManager.class); + particlePack.getStyles().forEach(particleStyleManager::removeAllStyleReferences); + particlePack.getEventStyles().forEach(particleStyleManager::removeAllStyleReferences); + + this.loadedPacks.remove(particlePack.getName()); + particlePack.getClassLoader().close(); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + return true; + } + + /** + * Moves particle packs in the plugins directory to the packs directory + */ + private void moveParticlePacksFromPluginsFolder() { + File pluginsDirectory = this.playerParticles.getDataFolder().getParentFile(); + File[] files = pluginsDirectory.listFiles(); + if (files == null || files.length == 0) + return; + + for (File file : files) { + if (!file.isFile() || !file.getName().endsWith(".jar")) + continue; + + if (this.isParticlePack(file)) { + this.playerParticles.getLogger().warning("Found particle pack in plugins directory, attempting to move to packs directory: " + file.getName()); + + // Move the jar to the packs folder + File newFile = new File(this.playerParticles.getDataFolder(), PACK_DIRECTORY_NAME + File.separator + file.getName()); + if (newFile.exists()) { + this.playerParticles.getLogger().warning("Found duplicate particle pack when moving to packs directory, deleting old version: " + file.getName()); + newFile.delete(); + } + + file.renameTo(newFile); + } + } + } + + /** + * Checks if the given file is a particle pack + * + * @param file The file to check + * @return True if the file is a particle pack, false otherwise + */ + private boolean isParticlePack(File file) { + try { + // Try to find a file named "particle_pack.yml" in the jar and immediately discard it + new URL("jar:file:" + file.getAbsolutePath() + "!/" + INFO_FILE_NAME).openStream().close(); + return true; + } catch (IOException e) { + return false; + } + } + +} diff --git a/src/main/java/dev/esophose/playerparticles/manager/ParticleStyleManager.java b/src/main/java/dev/esophose/playerparticles/manager/ParticleStyleManager.java index ce3e11d..3ed1741 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/ParticleStyleManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/ParticleStyleManager.java @@ -2,12 +2,14 @@ package dev.esophose.playerparticles.manager; import dev.esophose.playerparticles.PlayerParticles; import dev.esophose.playerparticles.event.ParticleStyleRegistrationEvent; +import dev.esophose.playerparticles.particles.PPlayer; +import dev.esophose.playerparticles.particles.ParticleGroup; +import dev.esophose.playerparticles.styles.ConfiguredParticleStyle; import dev.esophose.playerparticles.styles.DefaultStyles; import dev.esophose.playerparticles.styles.ParticleStyle; import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -25,8 +27,8 @@ public class ParticleStyleManager extends Manager { public ParticleStyleManager(PlayerParticles playerParticles) { super(playerParticles); - this.stylesByName = new LinkedHashMap<>(); - this.stylesByInternalName = new LinkedHashMap<>(); + this.stylesByName = new HashMap<>(); + this.stylesByInternalName = new HashMap<>(); this.eventStyles = new ArrayList<>(); DefaultStyles.initStyles(); @@ -43,12 +45,18 @@ public class ParticleStyleManager extends Manager { // Call registration event // We use this event internally, so no other action needs to be done for us to register the default styles ParticleStyleRegistrationEvent event = new ParticleStyleRegistrationEvent(); + + // Register styles from particle packs + this.playerParticles.getManager(ParticlePackManager.class).getLoadedParticlePacks().forEach(pack -> { + pack.getStyles().forEach(event::registerStyle); + pack.getEventStyles().forEach(event::registerEventStyle); + }); + Bukkit.getPluginManager().callEvent(event); Collection eventStyles = event.getRegisteredEventStyles().values(); List styles = new ArrayList<>(event.getRegisteredStyles().values()); styles.addAll(eventStyles); - styles.sort(Comparator.comparing(ParticleStyle::getName)); for (ParticleStyle style : styles) { try { @@ -64,6 +72,9 @@ public class ParticleStyleManager extends Manager { if (this.stylesByInternalName.containsKey(style.getInternalName().toLowerCase())) throw new IllegalArgumentException("Tried to register two styles with the same internal name spelling: '" + style.getInternalName() + "'"); + if (style instanceof ConfiguredParticleStyle) + ((ConfiguredParticleStyle) style).loadSettings(); + this.stylesByName.put(style.getName().toLowerCase(), style); this.stylesByInternalName.put(style.getInternalName().toLowerCase(), style); @@ -81,6 +92,25 @@ public class ParticleStyleManager extends Manager { } + /** + * Removes all references of a ParticleStyle from all PPlayers + * + * @param style The style to remove + */ + public void removeAllStyleReferences(ParticleStyle style) { + Collection pplayers = this.playerParticles.getManager(ParticleManager.class).getPPlayers().values(); + for (PPlayer pplayer : pplayers) { + // Remove all references to style from groups + pplayer.getParticleGroups().values().removeIf(group -> { + group.getParticles().values().removeIf(particle -> particle.getStyle().equals(style)); + return group.getParticles().isEmpty() && !group.getName().equals(ParticleGroup.DEFAULT_NAME); + }); + + // Remove all references to style from fixed effects + pplayer.getFixedParticlesMap().values().removeIf(x -> x.getParticlePair().getStyle().equals(style)); + } + } + /** * Returns if a given style is customly handled * @@ -92,10 +122,14 @@ public class ParticleStyleManager extends Manager { } /** - * @return A List of styles that are registered and enabled + * @return A List of styles that are registered, enabled, and sorted by name */ - public Collection getStyles() { - return this.stylesByName.values().stream().filter(ParticleStyle::isEnabled).collect(Collectors.toList()); + public List getStyles() { + return this.stylesByName.entrySet().stream() + .filter(x -> x.getValue().isEnabled()) + .sorted(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue) + .collect(Collectors.toList()); } /** diff --git a/src/main/java/dev/esophose/playerparticles/pack/ParticlePack.java b/src/main/java/dev/esophose/playerparticles/pack/ParticlePack.java new file mode 100644 index 0000000..0eb4ce8 --- /dev/null +++ b/src/main/java/dev/esophose/playerparticles/pack/ParticlePack.java @@ -0,0 +1,83 @@ +package dev.esophose.playerparticles.pack; + +import dev.esophose.playerparticles.PlayerParticles; +import dev.esophose.playerparticles.manager.ParticlePackManager; +import dev.esophose.playerparticles.styles.ParticleStyle; +import java.io.File; +import java.net.URLClassLoader; +import java.util.List; + +public abstract class ParticlePack { + + protected PlayerParticles playerParticles; + private ParticlePackDescription description; + private URLClassLoader classLoader; + + /** + * @return The list of styles registered by this particle pack + */ + public abstract List getStyles(); + + /** + * @return The list of event-based styles registered by this particle pack + */ + public abstract List getEventStyles(); + + /** + * Called when the pack is enabled, does nothing by default + */ + public void onEnable() { + + } + + /** + * @return The total number of styles returned by {@link #getStyles()} and {@link #getEventStyles()} + */ + public final int getNumberOfStyles() { + return this.getStyles().size() + this.getEventStyles().size(); + } + + /** + * @return The name of the pack, shorthand for {@link ParticlePackDescription#getName()} + */ + public final String getName() { + return this.description.getName(); + } + + /** + * @return The description of the pack + */ + public final ParticlePackDescription getDescription() { + return this.description; + } + + /** + * @return The classloader of the pack + */ + public final URLClassLoader getClassLoader() { + return this.classLoader; + } + + /** + * @return The directory of the pack's configuration files + */ + public final File getConfigDirectory() { + return new File(PlayerParticles.getInstance().getDataFolder(), ParticlePackManager.PACK_DIRECTORY_NAME + File.separator + this.getName()); + } + + /** + * Called reflectively from the ParticlePackManager when loaded + * + * @param playerParticles The plugin instance + * @param description The description of the pack + * @param classLoader The classloader of the pack + */ + private void init(PlayerParticles playerParticles, ParticlePackDescription description, URLClassLoader classLoader) { + this.playerParticles = playerParticles; + this.description = description; + this.classLoader = classLoader; + + this.onEnable(); + } + +} diff --git a/src/main/java/dev/esophose/playerparticles/pack/ParticlePackDescription.java b/src/main/java/dev/esophose/playerparticles/pack/ParticlePackDescription.java new file mode 100644 index 0000000..8522304 --- /dev/null +++ b/src/main/java/dev/esophose/playerparticles/pack/ParticlePackDescription.java @@ -0,0 +1,29 @@ +package dev.esophose.playerparticles.pack; + +import org.bukkit.configuration.file.FileConfiguration; + +public class ParticlePackDescription { + + private final String name; + private final String version; + + public ParticlePackDescription(FileConfiguration packFileConfig) { + this.name = packFileConfig.getString("name"); + this.version = packFileConfig.getString("version"); + } + + /** + * @return the name of the pack + */ + public String getName() { + return this.name; + } + + /** + * @return the version of the pack + */ + public String getVersion() { + return this.version; + } + +} diff --git a/src/main/java/dev/esophose/playerparticles/pack/ParticlePackInitializationException.java b/src/main/java/dev/esophose/playerparticles/pack/ParticlePackInitializationException.java new file mode 100644 index 0000000..51b6335 --- /dev/null +++ b/src/main/java/dev/esophose/playerparticles/pack/ParticlePackInitializationException.java @@ -0,0 +1,9 @@ +package dev.esophose.playerparticles.pack; + +public class ParticlePackInitializationException extends RuntimeException { + + public ParticlePackInitializationException(String packName, Throwable cause) { + super("An error occurred initializing a particle pack: " + packName, cause); + } + +} diff --git a/src/main/java/dev/esophose/playerparticles/particles/FixedParticleEffect.java b/src/main/java/dev/esophose/playerparticles/particles/FixedParticleEffect.java index 8875fb1..9a5050f 100644 --- a/src/main/java/dev/esophose/playerparticles/particles/FixedParticleEffect.java +++ b/src/main/java/dev/esophose/playerparticles/particles/FixedParticleEffect.java @@ -90,4 +90,13 @@ public class FixedParticleEffect { this.location.setZ(z); } + /** + * Updates the coordinates of the FixedParticleEffect + * + * @param location The new Location + */ + public void setCoordinates(Location location) { + this.location = location; + } + } diff --git a/src/main/java/dev/esophose/playerparticles/particles/listener/PPlayerCombatListener.java b/src/main/java/dev/esophose/playerparticles/particles/listener/PPlayerCombatListener.java index 35a4f8a..8157741 100644 --- a/src/main/java/dev/esophose/playerparticles/particles/listener/PPlayerCombatListener.java +++ b/src/main/java/dev/esophose/playerparticles/particles/listener/PPlayerCombatListener.java @@ -21,7 +21,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; public class PPlayerCombatListener implements Listener { private static final int CHECK_INTERVAL = 20; - private Map timeSinceCombat = new HashMap<>(); + private final Map timeSinceCombat = new HashMap<>(); public PPlayerCombatListener() { DataManager dataManager = PlayerParticles.getInstance().getManager(DataManager.class); @@ -31,7 +31,6 @@ public class PPlayerCombatListener implements Listener { return; List toRemove = new ArrayList<>(); - for (UUID uuid : this.timeSinceCombat.keySet()) { PPlayer pplayer = dataManager.getPPlayer(uuid); if (pplayer == null) { @@ -50,13 +49,15 @@ public class PPlayerCombatListener implements Listener { } /** - * Used to detect if the player is moving + * Used to detect if the player is in combat * * @param event The event */ @EventHandler(priority = EventPriority.MONITOR) public void onPlayerAttack(EntityDamageByEntityEvent event) { - if (event.getEntity().getType() != EntityType.PLAYER) + boolean attackedIsPlayer = event.getEntity().getType() == EntityType.PLAYER; + boolean includeMobs = Setting.TOGGLE_ON_COMBAT_INCLUDE_MOBS.getBoolean(); + if (!attackedIsPlayer && !includeMobs) return; Player attacker; @@ -70,10 +71,10 @@ public class PPlayerCombatListener implements Listener { attacker = (Player) event.getDamager(); } else return; - Player damaged = (Player) event.getEntity(); + if (attackedIsPlayer) + this.markInCombat((Player) event.getEntity()); this.markInCombat(attacker); - this.markInCombat(damaged); } /** diff --git a/src/main/java/dev/esophose/playerparticles/styles/DefaultParticleStyle.java b/src/main/java/dev/esophose/playerparticles/styles/ConfiguredParticleStyle.java similarity index 79% rename from src/main/java/dev/esophose/playerparticles/styles/DefaultParticleStyle.java rename to src/main/java/dev/esophose/playerparticles/styles/ConfiguredParticleStyle.java index 4b49092..9fbb565 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/DefaultParticleStyle.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ConfiguredParticleStyle.java @@ -3,22 +3,24 @@ package dev.esophose.playerparticles.styles; import com.google.common.collect.ObjectArrays; import dev.esophose.playerparticles.PlayerParticles; import dev.esophose.playerparticles.config.CommentedFileConfiguration; +import dev.esophose.playerparticles.pack.ParticlePack; import dev.esophose.playerparticles.util.ParticleUtils; import java.io.File; import java.util.List; import org.bukkit.Material; -public abstract class DefaultParticleStyle implements ParticleStyle { +public abstract class ConfiguredParticleStyle implements ParticleStyle { protected PlayerParticles playerParticles; private CommentedFileConfiguration config; private boolean changed; - private String internalStyleName; - private boolean canBeFixedByDefault; - private boolean canToggleWithMovementByDefault; - private boolean canToggleWithCombatByDefault; - private double fixedEffectOffsetByDefault; + private final ParticlePack owningPack; + private final String internalStyleName; + private final boolean canBeFixedByDefault; + private final boolean canToggleWithMovementByDefault; + private final boolean canToggleWithCombatByDefault; + private final double fixedEffectOffsetByDefault; private String styleName; private boolean enabled; @@ -28,23 +30,31 @@ public abstract class DefaultParticleStyle implements ParticleStyle { private double fixedEffectOffset; private Material guiIconMaterial; - protected DefaultParticleStyle(String internalStyleName, boolean canBeFixedByDefault, boolean canToggleWithMovementByDefault, double fixedEffectOffsetByDefault) { + protected ConfiguredParticleStyle(String internalStyleName, boolean canBeFixedByDefault, boolean canToggleWithMovementByDefault, double fixedEffectOffsetByDefault) { + this(null, internalStyleName, canBeFixedByDefault, canToggleWithMovementByDefault, fixedEffectOffsetByDefault); + } + + protected ConfiguredParticleStyle(ParticlePack owningPack, String internalStyleName, boolean canBeFixedByDefault, boolean canToggleWithMovementByDefault, double fixedEffectOffsetByDefault) { + this.owningPack = owningPack; this.internalStyleName = internalStyleName; this.canBeFixedByDefault = canBeFixedByDefault; this.canToggleWithMovementByDefault = canToggleWithMovementByDefault; this.canToggleWithCombatByDefault = true; this.fixedEffectOffsetByDefault = fixedEffectOffsetByDefault; this.playerParticles = PlayerParticles.getInstance(); - - this.setDefaultSettings(); - this.loadSettings(false); } /** - * Sets the default settings shared for each style then calls setDefaultSettings(CommentedFileConfiguration) + * Sets the default settings shared for each style then calls {@link #setDefaultSettings(CommentedFileConfiguration)} */ private void setDefaultSettings() { - File directory = new File(this.playerParticles.getDataFolder(), "styles"); + File directory; + if (this.owningPack == null) { + directory = new File(this.playerParticles.getDataFolder(), "styles"); + } else { + directory = this.owningPack.getConfigDirectory(); + } + directory.mkdirs(); File file = new File(directory, this.internalStyleName + ".yml"); @@ -66,13 +76,10 @@ public abstract class DefaultParticleStyle implements ParticleStyle { } /** - * Loads the settings shared for each style then calls loadSettings(CommentedFileConfiguration) - * - * @param reloadConfig If the settings should be reloaded or not + * Loads the settings shared for each style then calls {@link #loadSettings(CommentedFileConfiguration)} */ - public final void loadSettings(boolean reloadConfig) { - if (reloadConfig) - this.setDefaultSettings(); + public final void loadSettings() { + this.setDefaultSettings(); this.styleName = this.config.getString("style-name"); this.enabled = this.config.getBoolean("enabled"); diff --git a/src/main/java/dev/esophose/playerparticles/styles/DefaultStyles.java b/src/main/java/dev/esophose/playerparticles/styles/DefaultStyles.java index e1ec3ba..4c3830e 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/DefaultStyles.java +++ b/src/main/java/dev/esophose/playerparticles/styles/DefaultStyles.java @@ -124,8 +124,8 @@ public class DefaultStyles implements Listener { */ public static void reloadSettings(ParticleStyleManager particleStyleManager) { for (ParticleStyle style : particleStyleManager.getStylesWithDisabled()) - if (style instanceof DefaultParticleStyle) - ((DefaultParticleStyle) style).loadSettings(true); + if (style instanceof ConfiguredParticleStyle) + ((ConfiguredParticleStyle) style).loadSettings(); } } diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java index a871a27..cb43653 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleArrows.java @@ -17,7 +17,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.ProjectileLaunchEvent; -public class ParticleStyleArrows extends DefaultParticleStyle implements Listener { +public class ParticleStyleArrows extends ConfiguredParticleStyle implements Listener { private List projectiles; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBatman.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBatman.java index 0fc7c1a..6b22518 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBatman.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBatman.java @@ -13,7 +13,7 @@ import org.bukkit.util.Vector; /* * Equations Source: https://www.desmos.com/calculator/cscx2zcrlf */ -public class ParticleStyleBatman extends DefaultParticleStyle { +public class ParticleStyleBatman extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBeam.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBeam.java index e71d657..125ad10 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBeam.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBeam.java @@ -9,7 +9,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleBeam extends DefaultParticleStyle { +public class ParticleStyleBeam extends ConfiguredParticleStyle { private int step = 0; private boolean reversed = false; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockBreak.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockBreak.java index 95a8912..2a9d261 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockBreak.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockBreak.java @@ -17,7 +17,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -public class ParticleStyleBlockBreak extends DefaultParticleStyle implements Listener { +public class ParticleStyleBlockBreak extends ConfiguredParticleStyle implements Listener { private int particleAmount; private double particleSpread; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockPlace.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockPlace.java index d3ed9ac..f364a7e 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockPlace.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleBlockPlace.java @@ -17,7 +17,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; -public class ParticleStyleBlockPlace extends DefaultParticleStyle implements Listener { +public class ParticleStyleBlockPlace extends ConfiguredParticleStyle implements Listener { private int particleAmount; private double particleSpread; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java index c1eeab2..73274b3 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCelebration.java @@ -21,7 +21,7 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -public class ParticleStyleCelebration extends DefaultParticleStyle { +public class ParticleStyleCelebration extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleChains.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleChains.java index 59591c7..f4a57b7 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleChains.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleChains.java @@ -8,7 +8,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleChains extends DefaultParticleStyle { +public class ParticleStyleChains extends ConfiguredParticleStyle { private int chainParticleAmount; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCompanion.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCompanion.java index ccefa20..6dec803 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCompanion.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCompanion.java @@ -33,7 +33,7 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.util.Vector; -public class ParticleStyleCompanion extends DefaultParticleStyle { +public class ParticleStyleCompanion extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCube.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCube.java index ae32517..c9856e0 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCube.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleCube.java @@ -38,7 +38,7 @@ import org.bukkit.util.Vector; * The project this is from is called EffectLib and can be found here: * https://github.com/Slikey/EffectLib */ -public class ParticleStyleCube extends DefaultParticleStyle { +public class ParticleStyleCube extends ConfiguredParticleStyle { private int step = 0; private boolean skipNextStep = false; // Only spawn every 2 ticks diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleDeath.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleDeath.java index e8339f1..0b5ac0b 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleDeath.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleDeath.java @@ -20,7 +20,7 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.scheduler.BukkitRunnable; -public class ParticleStyleDeath extends DefaultParticleStyle implements Listener { +public class ParticleStyleDeath extends ConfiguredParticleStyle implements Listener { private String style; private List causes; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFeet.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFeet.java index 7ab1685..48c712f 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFeet.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFeet.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleFeet extends DefaultParticleStyle { +public class ParticleStyleFeet extends ConfiguredParticleStyle { private double feetOffset; private double particleSpreadX, particleSpreadY, particleSpreadZ; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFishing.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFishing.java index e6ac119..af0430d 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFishing.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleFishing.java @@ -20,7 +20,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.projectiles.ProjectileSource; -public class ParticleStyleFishing extends DefaultParticleStyle implements Listener { +public class ParticleStyleFishing extends ConfiguredParticleStyle implements Listener { // I hate legacy versions. The Spigot API changed the PlayerFishEvent#getHook method from returning a Fish to a FishHook in 1.13 private static Method PlayerFishEvent_getHook; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHalo.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHalo.java index 2ae780c..14ce8ee 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHalo.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHalo.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleHalo extends DefaultParticleStyle { +public class ParticleStyleHalo extends ConfiguredParticleStyle { private boolean skipNextSpawn = false; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHurt.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHurt.java index be0b4a7..9d5a822 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHurt.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleHurt.java @@ -17,7 +17,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; -public class ParticleStyleHurt extends DefaultParticleStyle implements Listener { +public class ParticleStyleHurt extends ConfiguredParticleStyle implements Listener { private int thickMultiplier; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleIcosphere.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleIcosphere.java index 0be58e0..40fa101 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleIcosphere.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleIcosphere.java @@ -19,7 +19,7 @@ import java.util.Set; import org.bukkit.Location; import org.bukkit.util.Vector; -public class ParticleStyleIcosphere extends DefaultParticleStyle { +public class ParticleStyleIcosphere extends ConfiguredParticleStyle { private int ticksPerSpawn; private double radius; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleInvocation.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleInvocation.java index 0e66339..cbbf919 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleInvocation.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleInvocation.java @@ -10,7 +10,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleInvocation extends DefaultParticleStyle { +public class ParticleStyleInvocation extends ConfiguredParticleStyle { private double step = 0; private int circleStep = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java index 26fb6b6..84c4fcf 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleMove.java @@ -17,7 +17,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; -public class ParticleStyleMove extends DefaultParticleStyle implements Listener { +public class ParticleStyleMove extends ConfiguredParticleStyle implements Listener { private final ParticleManager particleManager = PlayerParticles.getInstance().getManager(ParticleManager.class); private final DataManager dataManager = PlayerParticles.getInstance().getManager(DataManager.class); diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleNormal.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleNormal.java index 8ea9a91..0bfd67a 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleNormal.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleNormal.java @@ -9,7 +9,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleNormal extends DefaultParticleStyle { +public class ParticleStyleNormal extends ConfiguredParticleStyle { protected ParticleStyleNormal() { super("normal", true, false, 0); diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOrbit.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOrbit.java index 17ed476..68ce343 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOrbit.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOrbit.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleOrbit extends DefaultParticleStyle { +public class ParticleStyleOrbit extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOutline.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOutline.java index cba934d..d0e2953 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOutline.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOutline.java @@ -15,7 +15,7 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -public class ParticleStyleOutline extends DefaultParticleStyle { +public class ParticleStyleOutline extends ConfiguredParticleStyle { private double particleDistance; private int spawnDelay; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOverhead.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOverhead.java index ae6914f..7a5149d 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOverhead.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleOverhead.java @@ -8,7 +8,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleOverhead extends DefaultParticleStyle { +public class ParticleStyleOverhead extends ConfiguredParticleStyle { private double headOffset; private double particleSpreadX, particleSpreadY, particleSpreadZ; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePoint.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePoint.java index 2b8625d..18e5de1 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePoint.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePoint.java @@ -7,7 +7,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStylePoint extends DefaultParticleStyle { +public class ParticleStylePoint extends ConfiguredParticleStyle { private double offset; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePopper.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePopper.java index 3f8c8ed..8f064da 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePopper.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePopper.java @@ -10,7 +10,7 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.util.Vector; -public class ParticleStylePopper extends DefaultParticleStyle { +public class ParticleStylePopper extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePulse.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePulse.java index d19a943..6af1721 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePulse.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStylePulse.java @@ -10,7 +10,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStylePulse extends DefaultParticleStyle { +public class ParticleStylePulse extends ConfiguredParticleStyle { private double step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleQuadhelix.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleQuadhelix.java index 210a1c5..13f2b13 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleQuadhelix.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleQuadhelix.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleQuadhelix extends DefaultParticleStyle { +public class ParticleStyleQuadhelix extends ConfiguredParticleStyle { private int stepX = 0; private int stepY = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleRings.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleRings.java index e850a29..9c0551d 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleRings.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleRings.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleRings extends DefaultParticleStyle { +public class ParticleStyleRings extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSphere.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSphere.java index 30cd727..c6dbdcc 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSphere.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSphere.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleSphere extends DefaultParticleStyle { +public class ParticleStyleSphere extends ConfiguredParticleStyle { private int density; private double radius; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpin.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpin.java index 7116bb0..e8c8107 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpin.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpin.java @@ -8,7 +8,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleSpin extends DefaultParticleStyle { +public class ParticleStyleSpin extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpiral.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpiral.java index 964e506..53dd24b 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpiral.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSpiral.java @@ -9,7 +9,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleSpiral extends DefaultParticleStyle { +public class ParticleStyleSpiral extends ConfiguredParticleStyle { private int stepX = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSwords.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSwords.java index e7baf26..9743aa9 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSwords.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleSwords.java @@ -21,7 +21,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; -public class ParticleStyleSwords extends DefaultParticleStyle implements Listener { +public class ParticleStyleSwords extends ConfiguredParticleStyle implements Listener { private static final List DEFAULT_SWORD_NAMES; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTeleport.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTeleport.java index b2ded41..035d45d 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTeleport.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTeleport.java @@ -19,7 +19,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -public class ParticleStyleTeleport extends DefaultParticleStyle implements Listener { +public class ParticleStyleTeleport extends ConfiguredParticleStyle implements Listener { private boolean before; private boolean after; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleThick.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleThick.java index 39d8983..93f0f16 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleThick.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleThick.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleThick extends DefaultParticleStyle { +public class ParticleStyleThick extends ConfiguredParticleStyle { private int multiplier; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTrail.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTrail.java index ea4b113..1aa3a76 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTrail.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTrail.java @@ -16,7 +16,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; -public class ParticleStyleTrail extends DefaultParticleStyle implements Listener { +public class ParticleStyleTrail extends ConfiguredParticleStyle implements Listener { private final ParticleManager particleManager = PlayerParticles.getInstance().getManager(ParticleManager.class); private final DataManager dataManager = PlayerParticles.getInstance().getManager(DataManager.class); diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTwins.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTwins.java index b7fcb83..a6f0956 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTwins.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleTwins.java @@ -9,7 +9,7 @@ import java.util.Arrays; import java.util.List; import org.bukkit.Location; -public class ParticleStyleTwins extends DefaultParticleStyle { +public class ParticleStyleTwins extends ConfiguredParticleStyle { private int stepX = 0; private int stepY = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleVortex.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleVortex.java index fbc8fb3..0a63c25 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleVortex.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleVortex.java @@ -33,7 +33,7 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.util.Vector; -public class ParticleStyleVortex extends DefaultParticleStyle { +public class ParticleStyleVortex extends ConfiguredParticleStyle { private int step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirl.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirl.java index 2f87097..fdcfb78 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirl.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirl.java @@ -10,7 +10,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleWhirl extends DefaultParticleStyle { +public class ParticleStyleWhirl extends ConfiguredParticleStyle { private double step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirlwind.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirlwind.java index 67fea36..698b5f9 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirlwind.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWhirlwind.java @@ -10,7 +10,7 @@ import java.util.Collections; import java.util.List; import org.bukkit.Location; -public class ParticleStyleWhirlwind extends DefaultParticleStyle { +public class ParticleStyleWhirlwind extends ConfiguredParticleStyle { private double step = 0; diff --git a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWings.java b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWings.java index 2c85ecf..a913206 100644 --- a/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWings.java +++ b/src/main/java/dev/esophose/playerparticles/styles/ParticleStyleWings.java @@ -11,14 +11,13 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.util.Vector; -public class ParticleStyleWings extends DefaultParticleStyle { - - private int spawnTimer = 0; // Spawn particles every 3 ticks +public class ParticleStyleWings extends ConfiguredParticleStyle { + private int spawnTimer; private int spawnDelay; protected ParticleStyleWings() { - super("wings", false, true, 0); + super("wings", true, true, 0); } @Override diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b4236f6..efeb76f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ version: '@version@' api-version: '1.13' description: Display particles around your player and blocks using customized styles and data! author: Esophose -website: https://www.spigotmc.org/resources/playerparticles.40261/ +website: https://www.spigotmc.org/resources/40261/ softdepend: [PlaceholderAPI, WorldGuard, WorldEdit] commands: pp: