diff --git a/src/com/esophose/playerparticles/PlayerParticles.java b/src/com/esophose/playerparticles/PlayerParticles.java index 1fea150..c0f703c 100644 --- a/src/com/esophose/playerparticles/PlayerParticles.java +++ b/src/com/esophose/playerparticles/PlayerParticles.java @@ -5,22 +5,8 @@ * * Permission to allow players to overrule the max particle groups allowed in the config playerparticles.groups.unlimited * * Setting in config.yml to disable non-event styles while the player is moving * * Setting in config.yml for max particles allowed per player, default 3 - * * Permission to allow players to overrule the max particles allowed playerparticles.particle.max - * * Permissions for the following: - * - playerparticles.particles.max.1 - * - playerparticles.particles.max.2 - * - playerparticles.particles.max.3 - * - playerparticles.particles.max.4 - * - playerparticles.particles.max.5 - * - playerparticles.particles.max.6 - * - playerparticles.particles.max.7 - * - playerparticles.particles.max.8 - * - playerparticles.particles.max.9 - * - playerparticles.particles.max.10 + * * Permission to allow players to overrule the max particles allowed in the config.yml * - playerparticles.particles.max.unlimited - * Note: The default max particles in the config.yml is used instead if the playerparticles.particles.max.# is lower - * Note: The highest number the user has permission for is how many they are able to use - * Ex. they have 4 and 7, they will have a max of 7 */ package com.esophose.playerparticles; @@ -41,9 +27,11 @@ import com.esophose.playerparticles.database.DatabaseConnector; import com.esophose.playerparticles.database.MySqlDatabaseConnector; import com.esophose.playerparticles.database.SqliteDatabaseConnector; import com.esophose.playerparticles.gui.PlayerParticlesGui; -import com.esophose.playerparticles.manager.DataManager; import com.esophose.playerparticles.manager.LangManager; import com.esophose.playerparticles.manager.ParticleManager; +import com.esophose.playerparticles.manager.SettingManager; +import com.esophose.playerparticles.manager.SettingManager.PSetting; +import com.esophose.playerparticles.particles.ParticleGroup; import com.esophose.playerparticles.styles.DefaultStyles; import com.esophose.playerparticles.updater.PluginUpdateListener; import com.esophose.playerparticles.updater.Updater; @@ -89,8 +77,9 @@ public class PlayerParticles extends JavaPlugin { Bukkit.getPluginManager().registerEvents(new PlayerParticlesGui(), this); saveDefaultConfig(); - double configVersion = getConfig().getDouble("version"); - if (configVersion < Double.parseDouble(getDescription().getVersion())) { + double configVersion = PSetting.VERSION.getDouble(); + boolean updatePluginSettings = configVersion < Double.parseDouble(getDescription().getVersion()); + if (updatePluginSettings) { File configFile = new File(getDataFolder(), "config.yml"); if (configFile.exists()) { configFile.delete(); @@ -100,7 +89,7 @@ public class PlayerParticles extends JavaPlugin { getLogger().warning("The config.yml has been updated to v" + getDescription().getVersion() + "!"); } - if (shouldCheckUpdates()) { + if (PSetting.CHECK_UPDATES.getBoolean()) { new BukkitRunnable() { public void run() { try { // This can throw an exception if the server has no internet connection or if the Curse API is down @@ -116,7 +105,7 @@ public class PlayerParticles extends JavaPlugin { }.runTaskAsynchronously(this); } - this.reload(); + this.reload(updatePluginSettings); } /** @@ -131,7 +120,7 @@ public class PlayerParticles extends JavaPlugin { /** * Reloads the settings of the plugin */ - public void reload() { + public void reload(boolean updatePluginSettings) { this.reloadConfig(); // If not null, plugin is already loaded @@ -145,10 +134,12 @@ public class PlayerParticles extends JavaPlugin { DefaultStyles.registerStyles(); // Only ever load styles once } - configureDatabase(getConfig().getBoolean("database-enable")); + // This runs before the SettingManager is reloaded, the credentials will not be stored in memory for more than a few milliseconds + configureDatabase(PSetting.DATABASE_ENABLE.getBoolean()); - DataManager.reload(); - LangManager.reload(); + SettingManager.reload(); + LangManager.reload(updatePluginSettings); + ParticleGroup.reload(); PlayerParticlesGui.setup(); @@ -174,15 +165,6 @@ public class PlayerParticles extends JavaPlugin { return databaseConnector; } - /** - * Checks the config if the plugin can look for updates - * - * @return True if check-updates is set to true in the config - */ - public boolean shouldCheckUpdates() { - return getConfig().getBoolean("check-updates"); - } - /** * Checks if database-enable is true in the config, if it is then uses MySql * Gets the database connection information from the config and tries to connect to the server @@ -193,7 +175,7 @@ public class PlayerParticles extends JavaPlugin { */ private void configureDatabase(boolean useMySql) { if (useMySql) { - databaseConnector = new MySqlDatabaseConnector(this.getConfig()); + databaseConnector = new MySqlDatabaseConnector(); } else { databaseConnector = new SqliteDatabaseConnector(this.getDataFolder().getAbsolutePath()); } @@ -260,7 +242,7 @@ public class PlayerParticles extends JavaPlugin { final Plugin playerParticles = this; new BukkitRunnable() { public void run() { - long ticks = getConfig().getLong("ticks-per-particle"); + long ticks = PSetting.TICKS_PER_PARTICLE.getLong(); particleTask = new ParticleManager().runTaskTimer(playerParticles, 0, ticks); } }.runTaskLater(playerParticles, 1); diff --git a/src/com/esophose/playerparticles/command/AddCommandModule.java b/src/com/esophose/playerparticles/command/AddCommandModule.java index 84d0f8f..69bbec0 100644 --- a/src/com/esophose/playerparticles/command/AddCommandModule.java +++ b/src/com/esophose/playerparticles/command/AddCommandModule.java @@ -19,6 +19,7 @@ import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty; import com.esophose.playerparticles.particles.ParticleGroup; import com.esophose.playerparticles.particles.ParticlePair; import com.esophose.playerparticles.styles.api.ParticleStyle; +import com.esophose.playerparticles.styles.api.ParticleStyleManager; import com.esophose.playerparticles.util.ParticleUtils; public class AddCommandModule implements CommandModule { @@ -29,6 +30,12 @@ public class AddCommandModule implements CommandModule { return; } + int maxParticlesAllowed = PermissionManager.getMaxParticlesAllowed(pplayer.getPlayer()); + if (pplayer.getActiveParticles().size() >= maxParticlesAllowed) { + LangManager.sendMessage(pplayer, Lang.ADD_REACHED_MAX, maxParticlesAllowed); + return; + } + ParticleEffect effect = ParticleEffect.fromName(args[0]); if (effect == null) { LangManager.sendMessage(pplayer, Lang.EFFECT_INVALID, args[0]); @@ -125,6 +132,10 @@ public class AddCommandModule implements CommandModule { DataManager.saveParticleGroup(pplayer.getUniqueId(), group); LangManager.sendMessage(pplayer, Lang.ADD_PARTICLE_APPLIED, newParticle.getEffect().getName(), newParticle.getStyle().getName(), newParticle.getDataString()); + + if (ParticleStyleManager.isCustomHandled(newParticle.getStyle())) { + LangManager.sendMessage(pplayer, Lang.STYLE_EVENT_SPAWNING_INFO, newParticle.getStyle().getName()); + } } public List onTabComplete(PPlayer pplayer, String[] args) { diff --git a/src/com/esophose/playerparticles/command/DefaultCommandModule.java b/src/com/esophose/playerparticles/command/DefaultCommandModule.java index be3a5dc..9eefee8 100644 --- a/src/com/esophose/playerparticles/command/DefaultCommandModule.java +++ b/src/com/esophose/playerparticles/command/DefaultCommandModule.java @@ -12,7 +12,7 @@ public class DefaultCommandModule implements CommandModule { public void onCommandExecute(PPlayer pplayer, String[] args) { // The default command just opens the GUI, execute the GUICommandModule - ParticleCommandHandler.findMatchingCommand("gui").onCommandExecute(pplayer, new String[] { "byDefault" }); + ParticleCommandHandler.findMatchingCommand("gui").onCommandExecute(pplayer, new String[] { "_byDefault_" }); } public List onTabComplete(PPlayer pplayer, String[] args) { diff --git a/src/com/esophose/playerparticles/command/FixedCommandModule.java b/src/com/esophose/playerparticles/command/FixedCommandModule.java index 7794c39..7f7c359 100644 --- a/src/com/esophose/playerparticles/command/FixedCommandModule.java +++ b/src/com/esophose/playerparticles/command/FixedCommandModule.java @@ -89,7 +89,7 @@ public class FixedCommandModule implements CommandModule { * @param args The command arguments */ private void handleCreate(PPlayer pplayer, Player p, String[] args) { - boolean reachedMax = DataManager.hasPlayerReachedMaxFixedEffects(pplayer); + boolean reachedMax = PermissionManager.hasPlayerReachedMaxFixedEffects(pplayer); if (reachedMax) { LangManager.sendMessage(p, Lang.FIXED_MAX_REACHED); return; @@ -153,7 +153,7 @@ public class FixedCommandModule implements CommandModule { } double distanceFromEffect = p.getLocation().distance(new Location(p.getWorld(), xPos, yPos, zPos)); - int maxCreationDistance = DataManager.getMaxFixedEffectCreationDistance(); + int maxCreationDistance = PermissionManager.getMaxFixedEffectCreationDistance(); if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) { LangManager.sendMessage(p, Lang.FIXED_CREATE_OUT_OF_RANGE, maxCreationDistance + ""); return; @@ -377,7 +377,7 @@ public class FixedCommandModule implements CommandModule { * @param args The command arguments */ private void handleClear(PPlayer pplayer, Player p, String[] args) { - if (!p.hasPermission("playerparticles.fixed.clear")) { + if (!PermissionManager.canClearFixedEffects(p)) { LangManager.sendMessage(p, Lang.FIXED_CLEAR_NO_PERMISSION); return; } diff --git a/src/com/esophose/playerparticles/command/GUICommandModule.java b/src/com/esophose/playerparticles/command/GUICommandModule.java index b7e177a..bfbccce 100644 --- a/src/com/esophose/playerparticles/command/GUICommandModule.java +++ b/src/com/esophose/playerparticles/command/GUICommandModule.java @@ -14,7 +14,7 @@ public class GUICommandModule implements CommandModule { public void onCommandExecute(PPlayer pplayer, String[] args) { boolean byDefault = false; - if (args.length > 0 && args[0].equals("byDefault")) { + if (args.length > 0 && args[0].equals("_byDefault_")) { byDefault = true; } diff --git a/src/com/esophose/playerparticles/command/GroupCommandModule.java b/src/com/esophose/playerparticles/command/GroupCommandModule.java index 567a1af..739b8b0 100644 --- a/src/com/esophose/playerparticles/command/GroupCommandModule.java +++ b/src/com/esophose/playerparticles/command/GroupCommandModule.java @@ -10,6 +10,7 @@ import org.bukkit.util.StringUtil; import com.esophose.playerparticles.manager.DataManager; import com.esophose.playerparticles.manager.LangManager; import com.esophose.playerparticles.manager.LangManager.Lang; +import com.esophose.playerparticles.manager.PermissionManager; import com.esophose.playerparticles.particles.PPlayer; import com.esophose.playerparticles.particles.ParticleGroup; import com.esophose.playerparticles.particles.ParticlePair; @@ -73,13 +74,25 @@ public class GroupCommandModule implements CommandModule { return; } + // Check if the player actually has any particles + if (pplayer.getActiveParticles().size() == 0) { + LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_NO_PARTICLES); + return; + } + // The database column can only hold up to 100 characters, cut it off there if (groupName.length() >= 100) { groupName = groupName.substring(0, 100); } + // Check if they are creating a new group, if they are, check that they haven't gone over their limit + if (pplayer.getParticleGroupByName(groupName) == null && PermissionManager.hasPlayerReachedMaxGroups(pplayer)) { + LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_REACHED_MAX); + return; + } + // Use the existing group if available, otherwise create a new one - ParticleGroup group = pplayer.getParticlesByName(groupName); + ParticleGroup group = pplayer.getParticleGroupByName(groupName); boolean groupUpdated = false; if (group == null) { List particles = new ArrayList(); @@ -113,10 +126,22 @@ public class GroupCommandModule implements CommandModule { } // Get the group - ParticleGroup group = pplayer.getParticlesByName(groupName); + boolean isPreset = false; + ParticleGroup group = pplayer.getParticleGroupByName(groupName); if (group == null) { - LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName); - return; + // Didn't find a saved group, look at the presets + group = ParticleGroup.getPresetGroup(groupName); + if (group == null) { + LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName); + return; + } + + if (!group.canPlayerUse(pplayer.getPlayer())) { + LangManager.sendMessage(pplayer, Lang.GROUP_PRESET_NO_PERMISSION, groupName); + return; + } + + isPreset = true; } // Empty out the active group and fill it with clones from the target group @@ -127,7 +152,11 @@ public class GroupCommandModule implements CommandModule { // Update group and notify player DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup); - LangManager.sendMessage(pplayer, Lang.GROUP_LOAD_SUCCESS, activeGroup.getParticles().size(), groupName); + + if (!isPreset) + LangManager.sendMessage(pplayer, Lang.GROUP_LOAD_SUCCESS, activeGroup.getParticles().size(), groupName); + else + LangManager.sendMessage(pplayer, Lang.GROUP_LOAD_PRESET_SUCCESS, activeGroup.getParticles().size(), groupName); } /** @@ -143,11 +172,14 @@ public class GroupCommandModule implements CommandModule { return; } - // Get the group - ParticleGroup group = pplayer.getParticlesByName(groupName); + ParticleGroup group = pplayer.getParticleGroupByName(groupName); if (group == null) { - LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName); - return; + // Didn't find a saved group, look at the presets + group = ParticleGroup.getPresetGroup(groupName); + if (group != null) { + LangManager.sendMessage(pplayer, Lang.GROUP_REMOVE_PRESET); + return; + } } // Delete the group and notify player @@ -168,11 +200,19 @@ public class GroupCommandModule implements CommandModule { return; } - // Get the group - ParticleGroup group = pplayer.getParticlesByName(groupName); + ParticleGroup group = pplayer.getParticleGroupByName(groupName); if (group == null) { - LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName); - return; + // Didn't find a saved group, look at the presets + group = ParticleGroup.getPresetGroup(groupName); + if (group == null) { + LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName); + return; + } + + if (!group.canPlayerUse(pplayer.getPlayer())) { + LangManager.sendMessage(pplayer, Lang.GROUP_PRESET_NO_PERMISSION, groupName); + return; + } } LangManager.sendMessage(pplayer, Lang.GROUP_INFO_HEADER, groupName); @@ -187,10 +227,6 @@ public class GroupCommandModule implements CommandModule { */ private void onList(PPlayer pplayer) { List groups = pplayer.getParticleGroups(); - if (groups.size() == 1) { - LangManager.sendMessage(pplayer, Lang.GROUP_LIST_NONE); - return; - } String groupsList = ""; for (ParticleGroup group : groups) @@ -199,9 +235,26 @@ public class GroupCommandModule implements CommandModule { if (groupsList.endsWith(", ")) groupsList = groupsList.substring(0, groupsList.length() - 2); - - LangManager.sendMessage(pplayer, Lang.GROUP_LIST_OUTPUT, groupsList); - // TODO: Implement Group Presets and output them here + + String presetsList = ""; + for (ParticleGroup group : ParticleGroup.getPresetGroupsForPlayer(pplayer.getPlayer())) + presetsList += group.getName() + ", "; + + if (presetsList.endsWith(", ")) + presetsList = presetsList.substring(0, presetsList.length() - 2); + + if (groupsList.isEmpty() && presetsList.isEmpty()) { + LangManager.sendMessage(pplayer, Lang.GROUP_LIST_NONE); + return; + } + + if (!groupsList.isEmpty()) { + LangManager.sendMessage(pplayer, Lang.GROUP_LIST_OUTPUT, groupsList); + } + + if (!presetsList.isEmpty()) { + LangManager.sendMessage(pplayer, Lang.GROUP_LIST_PRESETS, presetsList); + } } public List onTabComplete(PPlayer pplayer, String[] args) { @@ -219,7 +272,9 @@ public class GroupCommandModule implements CommandModule { for (ParticleGroup group : pplayer.getParticleGroups()) if (!group.getName().equals(ParticleGroup.DEFAULT_NAME)) groupNames.add(group.getName()); - // TODO: Include Group Presets and add them to groupNames + if (!args[0].equals("remove")) + for (ParticleGroup group : ParticleGroup.getPresetGroupsForPlayer(pplayer.getPlayer())) + groupNames.add(group.getName()); StringUtil.copyPartialMatches(args[1], groupNames, matches); } } diff --git a/src/com/esophose/playerparticles/command/ReloadCommandModule.java b/src/com/esophose/playerparticles/command/ReloadCommandModule.java index ce69c50..fad2afa 100644 --- a/src/com/esophose/playerparticles/command/ReloadCommandModule.java +++ b/src/com/esophose/playerparticles/command/ReloadCommandModule.java @@ -6,13 +6,14 @@ import java.util.List; import com.esophose.playerparticles.PlayerParticles; import com.esophose.playerparticles.manager.LangManager; import com.esophose.playerparticles.manager.LangManager.Lang; +import com.esophose.playerparticles.manager.PermissionManager; import com.esophose.playerparticles.particles.PPlayer; public class ReloadCommandModule implements CommandModule { public void onCommandExecute(PPlayer pplayer, String[] args) { - if (pplayer.getPlayer().hasPermission("playerparticles.reload")) { - ((PlayerParticles)PlayerParticles.getPlugin()).reload(); + if (PermissionManager.canReloadPlugin(pplayer.getPlayer())) { + ((PlayerParticles)PlayerParticles.getPlugin()).reload(false); LangManager.sendMessage(pplayer, Lang.RELOAD_SUCCESS); } else { LangManager.sendMessage(pplayer, Lang.RELOAD_NO_PERMISSION); diff --git a/src/com/esophose/playerparticles/command/WorldsCommandModule.java b/src/com/esophose/playerparticles/command/WorldsCommandModule.java index d6d3696..7916da4 100644 --- a/src/com/esophose/playerparticles/command/WorldsCommandModule.java +++ b/src/com/esophose/playerparticles/command/WorldsCommandModule.java @@ -3,21 +3,21 @@ package com.esophose.playerparticles.command; import java.util.ArrayList; import java.util.List; -import com.esophose.playerparticles.manager.DataManager; import com.esophose.playerparticles.manager.LangManager; import com.esophose.playerparticles.manager.LangManager.Lang; +import com.esophose.playerparticles.manager.PermissionManager; import com.esophose.playerparticles.particles.PPlayer; public class WorldsCommandModule implements CommandModule { public void onCommandExecute(PPlayer pplayer, String[] args) { - if (DataManager.getDisabledWorlds() == null || DataManager.getDisabledWorlds().isEmpty()) { + if (PermissionManager.getDisabledWorlds() == null || PermissionManager.getDisabledWorlds().isEmpty()) { LangManager.sendMessage(pplayer, Lang.DISABLED_WORLDS_NONE); return; } String worlds = ""; - for (String s : DataManager.getDisabledWorlds()) { + for (String s : PermissionManager.getDisabledWorlds()) { worlds += s + ", "; } if (worlds.length() > 2) worlds = worlds.substring(0, worlds.length() - 2); diff --git a/src/com/esophose/playerparticles/database/MySqlDatabaseConnector.java b/src/com/esophose/playerparticles/database/MySqlDatabaseConnector.java index 063e299..db77d13 100644 --- a/src/com/esophose/playerparticles/database/MySqlDatabaseConnector.java +++ b/src/com/esophose/playerparticles/database/MySqlDatabaseConnector.java @@ -3,9 +3,8 @@ package com.esophose.playerparticles.database; import java.sql.Connection; import java.sql.SQLException; -import org.bukkit.configuration.file.FileConfiguration; - import com.esophose.playerparticles.PlayerParticles; +import com.esophose.playerparticles.manager.SettingManager.PSetting; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @@ -14,12 +13,12 @@ public class MySqlDatabaseConnector implements DatabaseConnector { private HikariDataSource hikari; private boolean initializedSuccessfully = false; - public MySqlDatabaseConnector(FileConfiguration pluginConfig) { - String hostname = pluginConfig.getString("database-hostname"); - String port = pluginConfig.getString("database-port"); - String database = pluginConfig.getString("database-name"); - String user = pluginConfig.getString("database-user-name"); - String pass = pluginConfig.getString("database-user-password"); + public MySqlDatabaseConnector() { + String hostname = PSetting.DATABASE_HOSTNAME.getString(); + String port = PSetting.DATABASE_PORT.getString(); + String database = PSetting.DATABASE_NAME.getString(); + String user = PSetting.DATABASE_USER_NAME.getString(); + String pass = PSetting.DATABASE_USER_PASSWORD.getString(); HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database); diff --git a/src/com/esophose/playerparticles/gui/PlayerParticlesGui.java b/src/com/esophose/playerparticles/gui/PlayerParticlesGui.java index beb4572..e5567af 100644 --- a/src/com/esophose/playerparticles/gui/PlayerParticlesGui.java +++ b/src/com/esophose/playerparticles/gui/PlayerParticlesGui.java @@ -33,7 +33,6 @@ import com.esophose.playerparticles.PlayerParticles; import com.esophose.playerparticles.manager.DataManager; import com.esophose.playerparticles.manager.LangManager; import com.esophose.playerparticles.manager.LangManager.Lang; -import com.esophose.playerparticles.manager.ParticleManager; import com.esophose.playerparticles.manager.PermissionManager; import com.esophose.playerparticles.particles.PPlayer; import com.esophose.playerparticles.particles.ParticleEffect; diff --git a/src/com/esophose/playerparticles/manager/DataManager.java b/src/com/esophose/playerparticles/manager/DataManager.java index bca9b3d..06483d2 100644 --- a/src/com/esophose/playerparticles/manager/DataManager.java +++ b/src/com/esophose/playerparticles/manager/DataManager.java @@ -26,24 +26,6 @@ import com.esophose.playerparticles.util.ParticleUtils; */ public class DataManager { - /** - * The disabled worlds cached for quick access - */ - private static List disabledWorlds = null; - - /** - * The max number of fixed effects a player can have, defined in the config - */ - private static int maxFixedEffects = -1; - - /** - * The max distance a fixed effect can be created relative to the player - */ - private static int maxFixedEffectCreationDistance = -1; - - /** - * This is not instantiable - */ private DataManager() { } @@ -403,64 +385,6 @@ public class DataManager { }); } - /** - * Checks if the given player has reached the max number of fixed effects - * - * @param pplayer The player to check - * @return If the player has reached the max number of fixed effects - */ - public static boolean hasPlayerReachedMaxFixedEffects(PPlayer pplayer) { - if (maxFixedEffects == -1) { // Initialize on the fly - maxFixedEffects = PlayerParticles.getPlugin().getConfig().getInt("max-fixed-effects"); - } - - if (pplayer.getPlayer().hasPermission("playerparticles.fixed.unlimited")) return false; - return pplayer.getFixedEffectIds().size() >= maxFixedEffects; - } - - /** - * Gets the max distance a fixed effect can be created from the player - * - * @return The max distance a fixed effect can be created from the player - */ - public static int getMaxFixedEffectCreationDistance() { - if (maxFixedEffectCreationDistance == -1) { // Initialize on the fly - maxFixedEffectCreationDistance = PlayerParticles.getPlugin().getConfig().getInt("max-fixed-effect-creation-distance"); - } - return maxFixedEffectCreationDistance; - } - - /** - * Checks if a world is disabled for particles to spawn in - * - * @param world The world name to check - * @return True if the world is disabled - */ - public static boolean isWorldDisabled(String world) { - return getDisabledWorlds().contains(world); - } - - /** - * Gets all the worlds that are disabled - * - * @return All world names that are disabled - */ - public static List getDisabledWorlds() { - if (disabledWorlds == null) { // Initialize on the fly - disabledWorlds = PlayerParticles.getPlugin().getConfig().getStringList("disabled-worlds"); - } - return disabledWorlds; - } - - /** - * Resets all config-related settings - */ - public static void reload() { - maxFixedEffects = -1; - maxFixedEffectCreationDistance = -1; - disabledWorlds = null; - } - /** * Asynchronizes the callback with it's own thread * diff --git a/src/com/esophose/playerparticles/manager/LangManager.java b/src/com/esophose/playerparticles/manager/LangManager.java index dfe2e0e..0e7d6f1 100644 --- a/src/com/esophose/playerparticles/manager/LangManager.java +++ b/src/com/esophose/playerparticles/manager/LangManager.java @@ -8,11 +8,11 @@ import java.nio.file.Paths; import java.text.MessageFormat; import org.bukkit.ChatColor; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import com.esophose.playerparticles.PlayerParticles; +import com.esophose.playerparticles.manager.SettingManager.PSetting; import com.esophose.playerparticles.particles.PPlayer; public class LangManager { @@ -64,6 +64,7 @@ public class LangManager { ID_UNKNOWN, // Add Command + ADD_REACHED_MAX, ADD_PARTICLE_APPLIED, // Data Command @@ -77,6 +78,7 @@ public class LangManager { // Group Command GROUP_INVALID, + GROUP_PRESET_NO_PERMISSION, GROUP_RESERVED, GROUP_NO_NAME, GROUP_SAVE_REACHED_MAX, @@ -84,6 +86,8 @@ public class LangManager { GROUP_SAVE_SUCCESS, GROUP_SAVE_SUCCESS_OVERWRITE, GROUP_LOAD_SUCCESS, + GROUP_LOAD_PRESET_SUCCESS, + GROUP_REMOVE_PRESET, GROUP_REMOVE_SUCCESS, GROUP_INFO_HEADER, GROUP_LIST_NONE, @@ -114,6 +118,7 @@ public class LangManager { // Styles STYLE_NO_PERMISSION, + STYLE_EVENT_SPAWNING_INFO, STYLE_INVALID, STYLE_LIST, @@ -211,38 +216,25 @@ public class LangManager { return new MessageFormat(this.message).format(replacements); } } - - /** - * Stores if messages and their prefixes should be displayed - */ - private static boolean messagesEnabled, prefixEnabled; - /** - * The prefix to place before all sent messages contained in the config - */ - private static String messagePrefix; + /** * The current lang file name */ private static String langFileName; + + private LangManager() { + + } /** * Used to set up the LangManager * This should only get called once by the PlayerParticles class, however * calling it multiple times wont affect anything negatively */ - public static void reload() { - FileConfiguration config = PlayerParticles.getPlugin().getConfig(); - messagesEnabled = config.getBoolean("messages-enabled"); - prefixEnabled = config.getBoolean("use-message-prefix"); - messagePrefix = parseColors(config.getString("message-prefix")); - - YamlConfiguration lang = configureLangFile(config); - if (lang == null) { - messagesEnabled = false; - } else { - for (Lang messageType : Lang.values()) - messageType.setMessage(lang); - } + public static void reload(boolean resetLangFile) { + YamlConfiguration lang = configureLangFile(resetLangFile); + for (Lang messageType : Lang.values()) + messageType.setMessage(lang); } /** @@ -250,13 +242,20 @@ public class LangManager { * If it doesn't exist, default to default.lang * If default.lang doesn't exist, copy the file from this .jar to the target directory * - * @param config The plugin's configuration file * @return The YamlConfiguration of the target .lang file */ - private static YamlConfiguration configureLangFile(FileConfiguration config) { + private static YamlConfiguration configureLangFile(boolean resetLangFile) { File pluginDataFolder = PlayerParticles.getPlugin().getDataFolder(); - langFileName = config.getString("lang-file"); + langFileName = PSetting.LANG_FILE.getString(); File targetLangFile = new File(pluginDataFolder.getAbsolutePath() + "/lang/" + langFileName); + + if (resetLangFile) { + File defaultLangFile = new File(pluginDataFolder.getAbsolutePath() + "/lang/default.lang"); + if (defaultLangFile.exists()) { + defaultLangFile.delete(); + PlayerParticles.getPlugin().getLogger().warning("default.lang has been reset!"); + } + } if (!targetLangFile.exists()) { // Target .lang file didn't exist, default to default.lang if (!langFileName.equals("default.lang")) { @@ -272,7 +271,7 @@ public class LangManager { return YamlConfiguration.loadConfiguration(targetLangFile); } catch (IOException ex) { ex.printStackTrace(); - PlayerParticles.getPlugin().getLogger().severe("Unable to write default.lang to disk! All messages for the plugin have been disabled until this is fixed!"); + PlayerParticles.getPlugin().getLogger().severe("Unable to write default.lang to disk! You and your players will be seeing lots of error messages!"); return null; } } @@ -300,14 +299,14 @@ public class LangManager { * @param replacements The replacements for the message */ public static void sendMessage(Player player, Lang messageType, Object... replacements) { - if (!messagesEnabled) return; + if (!PSetting.MESSAGES_ENABLED.getBoolean()) return; String message = messageType.get(replacements); if (message.length() == 0) return; - if (prefixEnabled) { - message = messagePrefix + " " + message; + if (PSetting.USE_MESSAGE_PREFIX.getBoolean()) { + message = parseColors(PSetting.MESSAGE_PREFIX.getString()) + " " + message; } if (message.trim().equals("")) return; @@ -334,12 +333,12 @@ public class LangManager { * @param message The message to send to the player */ public static void sendCustomMessage(Player player, String message) { - if (!messagesEnabled) return; + if (!PSetting.MESSAGES_ENABLED.getBoolean()) return; if (message.trim().length() == 0) return; - if (prefixEnabled) { - message = messagePrefix + " " + message; + if (PSetting.USE_MESSAGE_PREFIX.getBoolean()) { + message = parseColors(PSetting.MESSAGE_PREFIX.getString()) + " " + message; } player.sendMessage(message); diff --git a/src/com/esophose/playerparticles/manager/ParticleManager.java b/src/com/esophose/playerparticles/manager/ParticleManager.java index 4afbdba..4953ecb 100644 --- a/src/com/esophose/playerparticles/manager/ParticleManager.java +++ b/src/com/esophose/playerparticles/manager/ParticleManager.java @@ -102,14 +102,14 @@ public class ParticleManager extends BukkitRunnable implements Listener { // Don't show their particles if they are in spectator mode // Don't spawn particles if the world doesn't allow it - if (player != null && player.getGameMode() != GameMode.SPECTATOR && !DataManager.isWorldDisabled(player.getWorld().getName())) + if (player != null && player.getGameMode() != GameMode.SPECTATOR && !PermissionManager.isWorldDisabled(player.getWorld().getName())) for (ParticlePair particles : pplayer.getActiveParticles()) displayParticles(particles, player.getLocation().clone().add(0, 1, 0)); // Loop for FixedParticleEffects // Don't spawn particles if the world doesn't allow it for (FixedParticleEffect effect : pplayer.getFixedParticles()) - if (!DataManager.isWorldDisabled(effect.getLocation().getWorld().getName())) + if (!PermissionManager.isWorldDisabled(effect.getLocation().getWorld().getName())) displayFixedParticleEffect(effect); } } diff --git a/src/com/esophose/playerparticles/manager/PermissionManager.java b/src/com/esophose/playerparticles/manager/PermissionManager.java index 2954c79..45bffbd 100644 --- a/src/com/esophose/playerparticles/manager/PermissionManager.java +++ b/src/com/esophose/playerparticles/manager/PermissionManager.java @@ -5,40 +5,168 @@ import java.util.List; import org.bukkit.entity.Player; +import com.esophose.playerparticles.manager.SettingManager.PSetting; +import com.esophose.playerparticles.particles.PPlayer; import com.esophose.playerparticles.particles.ParticleEffect; import com.esophose.playerparticles.styles.DefaultStyles; import com.esophose.playerparticles.styles.api.ParticleStyle; import com.esophose.playerparticles.styles.api.ParticleStyleManager; public class PermissionManager { + + private static final String PERMISSION_PREFIX = "playerparticles."; + + public enum PPermission { + ALL("*"), + + EFFECT_ALL("effect.*"), + EFFECT("effect"), + + STYLE_ALL("style.*"), + STYLE("style"), + + FIXED("fixed"), + FIXED_UNLIMITED("fixed.unlimited"), + FIXED_CLEAR("fixed.clear"), + + RELOAD("reload"), + + PARTICLES_UNLIMITED("particles.unlimited"), + GROUPS_UNLIMITED("groups.unlimited"); + + private final String permissionString; + + private PPermission(String permissionString) { + this.permissionString = permissionString; + } + + /** + * Checks if a Player has a PlayerParticles permission + * + * @param p The Player + * @return True if the Player has permission + */ + public boolean check(Player p) { + String permission = PERMISSION_PREFIX + this.permissionString; + return p.hasPermission(permission); + } + + /** + * Checks if a Player has a PlayerParticles permission with a sub-permission + * + * @param p The Player + * @param subPermission The sub-permission + * @return True if the Player has permission + */ + public boolean check(Player p, String subPermission) { + String permission = PERMISSION_PREFIX + this.permissionString + '.' + subPermission; + return p.hasPermission(permission); + } + } + + private PermissionManager() { + + } + + /** + * Checks if the given player has reached the max number of particles in their active group + * + * @param pplayer The player to check + * @return If the player has reached the max number of particles in their active group + */ + public static boolean hasPlayerReachedMaxParticles(PPlayer pplayer) { + if (PPermission.ALL.check(pplayer.getPlayer())) return false; + if (PPermission.PARTICLES_UNLIMITED.check(pplayer.getPlayer())) return false; + return pplayer.getActiveParticles().size() >= PSetting.MAX_PARTICLES.getInt(); + } + + /** + * Checks if the given player has reached the max number of saved particle groups + * + * @param pplayer The player to check + * @return If the player has reached the max number of saved particle groups + */ + public static boolean hasPlayerReachedMaxGroups(PPlayer pplayer) { + if (PPermission.ALL.check(pplayer.getPlayer())) return false; + if (PPermission.GROUPS_UNLIMITED.check(pplayer.getPlayer())) return false; + return pplayer.getParticleGroups().size() >= PSetting.MAX_GROUPS.getInt(); + } + + /** + * Checks if the given player has reached the max number of fixed effects + * + * @param pplayer The player to check + * @return If the player has reached the max number of fixed effects + */ + public static boolean hasPlayerReachedMaxFixedEffects(PPlayer pplayer) { + if (PPermission.ALL.check(pplayer.getPlayer())) return false; + if (PPermission.FIXED_UNLIMITED.check(pplayer.getPlayer())) return false; + return pplayer.getFixedEffectIds().size() >= PSetting.MAX_FIXED_EFFECTS.getInt(); + } + + /** + * Gets the max distance a fixed effect can be created from the player + * + * @return The max distance a fixed effect can be created from the player + */ + public static int getMaxFixedEffectCreationDistance() { + return PSetting.MAX_FIXED_EFFECT_CREATION_DISTANCE.getInt(); + } + + /** + * Gets the maximum number of particles a player is allowed to use + * + * @param player The player to check + * @return The maximum number of particles based on the config.yml value, or unlimited + */ + public static int getMaxParticlesAllowed(Player player) { + if (PPermission.ALL.check(player) || PPermission.PARTICLES_UNLIMITED.check(player)) return Integer.MAX_VALUE; + return PSetting.MAX_PARTICLES.getInt(); + } + + /** + * Checks if a world is disabled for particles to spawn in + * + * @param world The world name to check + * @return True if the world is disabled + */ + public static boolean isWorldDisabled(String world) { + return getDisabledWorlds().contains(world); + } + + /** + * Gets all the worlds that are disabled + * + * @return All world names that are disabled + */ + public static List getDisabledWorlds() { + return PSetting.DISABLED_WORLDS.getStringList(); + } /** * Checks if a player has permission to use an effect - * Always returns true for 'none' * * @param player The player to check the permission for * @param effect The effect to check * @return True if the player has permission to use the effect */ public static boolean hasEffectPermission(Player player, ParticleEffect effect) { - if (player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.effect.*")) return true; - if (player.hasPermission("playerparticles.effect." + effect.getName())) return true; - return false; + if (PPermission.ALL.check(player) || PPermission.EFFECT_ALL.check(player)) return true; + return PPermission.EFFECT.check(player, effect.getName()); } /** * Checks if a player has permission to use a style - * Always returns true for 'none' so they can be reset + * Always returns true for 'normal', a player needs at least one style to apply particles * * @param player The player to check the permission for * @param style The style to check * @return If the player has permission to use the style */ public static boolean hasStylePermission(Player player, ParticleStyle style) { - if (player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.style.*")) return true; - if (player.hasPermission("playerparticles.style." + style.getName())) return true; if (style == DefaultStyles.NORMAL) return true; - return false; + if (PPermission.ALL.check(player) || PPermission.STYLE_ALL.check(player)) return true; + return PPermission.STYLE.check(player, style.getName()); } /** @@ -76,7 +204,27 @@ public class PermissionManager { * @return True if the player has permission */ public static boolean canUseFixedEffects(Player player) { - return player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.fixed"); + return PPermission.ALL.check(player) || PPermission.FIXED.check(player); + } + + /** + * Checks if a player has permission to clear fixed effects + * + * @param player The player to check the permission for + * @return True if the player has permission to use /pp fixed clear + */ + public static boolean canClearFixedEffects(Player player) { + return PPermission.ALL.check(player) || PPermission.FIXED_CLEAR.check(player); + } + + /** + * Checks if a player has permission to use /pp reload + * + * @param player The player to check the permission for + * @return True if the player has permission to reload the plugin's settings + */ + public static boolean canReloadPlugin(Player player) { + return PPermission.ALL.check(player) || PPermission.RELOAD.check(player); } } diff --git a/src/com/esophose/playerparticles/manager/SettingManager.java b/src/com/esophose/playerparticles/manager/SettingManager.java new file mode 100644 index 0000000..c48118d --- /dev/null +++ b/src/com/esophose/playerparticles/manager/SettingManager.java @@ -0,0 +1,159 @@ +package com.esophose.playerparticles.manager; + +import java.util.List; + +import com.esophose.playerparticles.PlayerParticles; + +public class SettingManager { + + private enum PSettingType { + BOOLEAN, + INTEGER, + LONG, + DOUBLE, + STRING, + STRING_LIST + } + + public enum PSetting { + VERSION(PSettingType.DOUBLE), + TICKS_PER_PARTICLE(PSettingType.LONG), + CHECK_UPDATES(PSettingType.BOOLEAN), + + MESSAGES_ENABLED(PSettingType.BOOLEAN), + USE_MESSAGE_PREFIX(PSettingType.BOOLEAN), + MESSAGE_PREFIX(PSettingType.STRING), + + DATABASE_ENABLE(PSettingType.BOOLEAN), + DATABASE_HOSTNAME(PSettingType.STRING), + DATABASE_PORT(PSettingType.STRING), + DATABASE_NAME(PSettingType.STRING), + DATABASE_USER_NAME(PSettingType.STRING), + DATABASE_USER_PASSWORD(PSettingType.STRING), + + MAX_FIXED_EFFECTS(PSettingType.INTEGER), + MAX_FIXED_EFFECT_CREATION_DISTANCE(PSettingType.INTEGER), + + MAX_PARTICLES(PSettingType.INTEGER), + + MAX_GROUPS(PSettingType.INTEGER), + + DISABLED_WORLDS(PSettingType.STRING_LIST), + + LANG_FILE(PSettingType.STRING); + + private final PSettingType settingType; + private Object value = null; + + private PSetting(PSettingType settingType) { + this.settingType = settingType; + } + + /** + * Resets the setting's value so it will be fetched from the config the next time it's needed + */ + private void resetDefault() { + this.value = null; + } + + /** + * Gets the value from cache, or the config.yml if it isn't loaded yet + * + * @return The value of this setting + */ + private Object getValue() { + if (this.value == null) { + String configPath = this.name().toLowerCase().replaceAll("_", "-"); + switch (this.settingType) { + case BOOLEAN: + this.value = PlayerParticles.getPlugin().getConfig().getBoolean(configPath); + break; + case INTEGER: + this.value = PlayerParticles.getPlugin().getConfig().getInt(configPath); + break; + case LONG: + this.value = PlayerParticles.getPlugin().getConfig().getLong(configPath); + break; + case DOUBLE: + this.value = PlayerParticles.getPlugin().getConfig().getDouble(configPath); + break; + case STRING: + this.value = PlayerParticles.getPlugin().getConfig().getString(configPath); + break; + case STRING_LIST: + this.value = PlayerParticles.getPlugin().getConfig().getStringList(configPath); + break; + } + } + return this.value; + } + + /** + * Gets the setting's value as a boolean + * + * @return The setting's value as a boolean + */ + public boolean getBoolean() { + return (boolean) this.getValue(); + } + + /** + * Gets the setting's value as an int + * + * @return The setting's value as an int + */ + public int getInt() { + return (int) this.getValue(); + } + + /** + * Gets the setting's value as a long + * + * @return The setting's value as a long + */ + public long getLong() { + return (long) this.getValue(); + } + + /** + * Gets the setting's value as a double + * + * @return The setting's value as a double + */ + public double getDouble() { + return (double) this.getValue(); + } + + /** + * Gets the setting's value as a String + * + * @return The setting's value as a String + */ + public String getString() { + return (String) this.getValue(); + } + + /** + * Gets the setting's value as a List of Strings + * + * @return The setting's value as a List of Strings + */ + @SuppressWarnings("unchecked") + public List getStringList() { + return (List) this.getValue(); + } + } + + private SettingManager() { + + } + + /** + * Resets the settings to their default values + */ + public static void reload() { + for (PSetting setting : PSetting.values()) + setting.resetDefault(); + } + +} diff --git a/src/com/esophose/playerparticles/particles/PPlayer.java b/src/com/esophose/playerparticles/particles/PPlayer.java index 56f323b..812d999 100644 --- a/src/com/esophose/playerparticles/particles/PPlayer.java +++ b/src/com/esophose/playerparticles/particles/PPlayer.java @@ -73,7 +73,7 @@ public class PPlayer { * @param name The name of the ParticleGroup * @return The target named ParticleGroup */ - public ParticleGroup getParticlesByName(String name) { + public ParticleGroup getParticleGroupByName(String name) { for (ParticleGroup group : this.particleGroups) if (group.getName().equalsIgnoreCase(name)) return group; diff --git a/src/com/esophose/playerparticles/particles/ParticleGroup.java b/src/com/esophose/playerparticles/particles/ParticleGroup.java index 04af0be..b736b47 100644 --- a/src/com/esophose/playerparticles/particles/ParticleGroup.java +++ b/src/com/esophose/playerparticles/particles/ParticleGroup.java @@ -1,11 +1,32 @@ package com.esophose.playerparticles.particles; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import com.esophose.playerparticles.PlayerParticles; +import com.esophose.playerparticles.manager.PermissionManager; +import com.esophose.playerparticles.particles.ParticleEffect.NoteColor; +import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor; +import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty; +import com.esophose.playerparticles.styles.api.ParticleStyle; +import com.esophose.playerparticles.util.ParticleUtils; public class ParticleGroup { public static final String DEFAULT_NAME = "active"; + private static List presetGroups; private String name; private List particles; @@ -14,7 +35,7 @@ public class ParticleGroup { this.name = name; this.particles = particles; } - + /** * Get the player-given name of this ParticleGroup * This will be null if it's the player's active ParticleGroup @@ -33,6 +54,21 @@ public class ParticleGroup { public List getParticles() { return this.particles; } + + /** + * Checks if a Player can use this ParticleGroup + * + * @param player The Player + * @return True if the Player can use this ParticleGroup + */ + public boolean canPlayerUse(Player player) { + if (PermissionManager.getMaxParticlesAllowed(player) < this.particles.size()) return false; + for (ParticlePair particle : this.particles) { + if (!PermissionManager.hasEffectPermission(player, particle.getEffect())) return false; + if (!PermissionManager.hasStylePermission(player, particle.getStyle())) return false; + } + return true; + } /** * Gets an empty ParticleGroup @@ -42,5 +78,159 @@ public class ParticleGroup { public static ParticleGroup getDefaultGroup() { return new ParticleGroup(DEFAULT_NAME, new ArrayList()); } + + /** + * Loads the preset groups from the groups.yml file + * + * @param pluginDataFolder + */ + public static void reload() { + presetGroups = new ArrayList(); + + File pluginDataFolder = PlayerParticles.getPlugin().getDataFolder(); + File groupsFile = new File(pluginDataFolder.getAbsolutePath() + File.separator + "groups.yml"); + + // Create the file if it doesn't exist + if (!groupsFile.exists()) { + try (InputStream inStream = PlayerParticles.getPlugin().getResource("groups.yml")) { + Files.copy(inStream, Paths.get(groupsFile.getAbsolutePath())); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Parse groups.yml file + YamlConfiguration groupsYaml = YamlConfiguration.loadConfiguration(groupsFile); + Set groupNames = groupsYaml.getKeys(false); + for (String groupName : groupNames) { + try { + List particles = new ArrayList(); + ConfigurationSection groupSection = groupsYaml.getConfigurationSection(groupName); + + Set particleKeys = groupSection.getKeys(false); + for (String stringId : particleKeys) { + ConfigurationSection particleSection = groupSection.getConfigurationSection(stringId); + + int id = Integer.parseInt(stringId); + ParticleEffect effect = ParticleEffect.fromName(particleSection.getString("effect")); + ParticleStyle style = ParticleStyle.fromName(particleSection.getString("style")); + + if (effect == null) { + PlayerParticles.getPlugin().getLogger().severe("Invalid effect name: '" + particleSection.getString("effect") + "'!"); + throw new Exception(); + } + + if (style == null) { + PlayerParticles.getPlugin().getLogger().severe("Invalid style name: '" + particleSection.getString("style") + "'!"); + throw new Exception(); + } + + Material itemData = null; + Material blockData = null; + OrdinaryColor colorData = null; + NoteColor noteColorData = null; + + String dataString = particleSection.getString("data"); + if (!dataString.isEmpty()) { + String[] args = dataString.split(" "); + + if (effect.hasProperty(ParticleProperty.COLORABLE)) { + if (effect == ParticleEffect.NOTE) { + if (args[0].equalsIgnoreCase("rainbow")) { + noteColorData = new NoteColor(99); + } else { + int note = -1; + try { + note = Integer.parseInt(args[0]); + } catch (Exception e) { + PlayerParticles.getPlugin().getLogger().severe("Invalid note: '" + args[0] + "'!"); + throw new Exception(); + } + + if (note < 0 || note > 23) { + PlayerParticles.getPlugin().getLogger().severe("Invalid note: '" + args[0] + "'!"); + throw new Exception(); + } + + noteColorData = new NoteColor(note); + } + } else { + if (args[0].equalsIgnoreCase("rainbow")) { + colorData = new OrdinaryColor(999, 999, 999); + } else { + int r = -1; + int g = -1; + int b = -1; + + try { + r = Integer.parseInt(args[0]); + g = Integer.parseInt(args[1]); + b = Integer.parseInt(args[2]); + } catch (Exception e) { + PlayerParticles.getPlugin().getLogger().severe("Invalid color: '" + args[0] + " " + args[1] + " " + args[2] + "'!"); + throw new Exception(); + } + + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) { + PlayerParticles.getPlugin().getLogger().severe("Invalid color: '" + args[0] + " " + args[1] + " " + args[2] + "'!"); + throw new Exception(); + } + + colorData = new OrdinaryColor(r, g, b); + } + } + } else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) { + if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) { + try { + blockData = ParticleUtils.closestMatch(args[0]); + if (blockData == null || !blockData.isBlock()) throw new Exception(); + } catch (Exception e) { + PlayerParticles.getPlugin().getLogger().severe("Invalid block: '" + args[0] + "'!"); + throw new Exception(); + } + } else if (effect == ParticleEffect.ITEM) { + try { + itemData = ParticleUtils.closestMatch(args[0]); + if (itemData == null || itemData.isBlock()) throw new Exception(); + } catch (Exception e) { + PlayerParticles.getPlugin().getLogger().severe("Invalid item: '" + args[0] + "'!"); + throw new Exception(); + } + } + } + } + + particles.add(new ParticlePair(null, id, effect, style, blockData, blockData, colorData, noteColorData)); + } + + presetGroups.add(new ParticleGroup(groupName, particles)); + } catch (Exception ex) { + PlayerParticles.getPlugin().getLogger().severe("An error occurred while parsing the groups.yml file!"); + } + } + } + + /** + * Gets all the preset ParticleGroups that a player can use + * + * @param player The player + * @return a List of preset ParticleGroups the player can use + */ + public static List getPresetGroupsForPlayer(Player player) { + return presetGroups.stream().filter(x -> x.canPlayerUse(player)).collect(Collectors.toList()); + } + + /** + * Gets a preset ParticleGroup by its name + * + * @param groupName The ParticleGroup name + * @return The preset ParticleGroup if it exists, otherwise null + */ + public static ParticleGroup getPresetGroup(String groupName) { + for (ParticleGroup group : presetGroups) + if (group.getName().equalsIgnoreCase(groupName)) + return group; + return null; + } } diff --git a/src/config.yml b/src/config.yml index 006c1de..35b92d5 100644 --- a/src/config.yml +++ b/src/config.yml @@ -48,6 +48,14 @@ disabled-worlds: [] # - your_world_name_here # - add_more_under_these +# The maximum number of particles a player can apply at once +# Default: 3 +max-particles: 3 + +# The maximum number of groups a player can have saved +# Default: 10 +max-groups: 10 + # Max fixed effects per player # Default: 5 max-fixed-effects: 5 @@ -56,8 +64,8 @@ max-fixed-effects: 5 # Determines how far away a player may create a fixed effect from themselves # This measurement is in blocks # Set to 0 for infinite distance -# Default: 128 -max-fixed-effect-creation-distance: 128 +# Default: 32 +max-fixed-effect-creation-distance: 32 # How many ticks to wait before spawning more particles # Increasing this value may cause less lag (if there was any), but will decrease prettiness diff --git a/src/groups.yml b/src/groups.yml index e636724..4a718b0 100644 --- a/src/groups.yml +++ b/src/groups.yml @@ -6,6 +6,9 @@ # effect and style! # # * Feel free to create your own, they will be # # available for users to select within the GUI! # +# * This file is not automatically updated. If you # +# want to reset the file to its defaults, simply # +# delete it and run the command '/pp reload'. # # ==================================================== # raincloud: diff --git a/src/lang/default.lang b/src/lang/default.lang index 842e22c..5dab866 100644 --- a/src/lang/default.lang +++ b/src/lang/default.lang @@ -50,6 +50,7 @@ id-invalid: '&cThe ID you entered is invalid, it must be a positive whole number id-unknown: '&cYou do not have a particle applied with the ID &b{0}&c!' # Add Command +add-reached-max: '&cUnable to apply particle, you have reached the maximum amount of &b{0} &callowed!' add-particle-applied: '&aA new particle has been applied with the effect &b{0}&a, style &b{1}&a, and data &b{2}&a!' # Data Command @@ -62,14 +63,17 @@ edit-success-style: '&aYour particle with an ID of &b{0} &ahas had its style cha edit-success-data: '&aYour particle with an ID of &b{0} &ahas had its data changed to &b{1}&a!' # Group Command -group-invalid: '&cA group does not exist with the name &b{0}&c!' +group-invalid: '&cA saved group or preset group does not exist with the name &b{0}&c!' +group-preset-no-permission: '&cYou are missing permission for an effect or style to use the preset group &b{0}&c!' group-reserved: '&cThe group name &bactive &cis reserved and cannot be used!' group-no-name: '&cYou did not provide a group name! &b/pp {0} ' group-save-reached-max: '&cUnable to save group, you have reached the max number of groups!' group-save-no-particles: '&cUnable to save group, you do not have any particles applied!' group-save-success: '&aYour current particles have been saved under the group named &b{0}&a!' group-save-success-overwrite: '&aThe group named &b{0} &ahas been updated with your current particles!' -group-load-success: '&aApplied &b{0} &aparticles from the group &b{1}&a!' +group-load-success: '&aApplied &b{0} &aparticle(s) from your saved group named &b{1}&a!' +group-load-preset-success: '&aApplied &b{0} &aparticle(s) from the preset group named &b{1}&a!' +group-remove-preset: '&cYou cannot remove a preset group!' group-remove-success: '&aRemoved the particle group named &b{0}&a!' group-info-header: '&eThe group &b{0} &ehas the following particles:' group-list-none: '&eYou do not have any particle groups saved!' @@ -100,6 +104,7 @@ effect-list-empty: '&cYou do not have permission to use any effects!' # Styles style-no-permission: '&cYou do not have permission to use the style &b{0} &c!' +style-event-spawning-info: '&eNote: The style &b{0} &espawns particles based on an event.' style-invalid: '&cThe style &b{0} &cdoes not exist! Use &b/pp styles &cfor a list of styles you can use.' style-list: '&eYou can use the following styles: &b{0}'