Updating to v4.3

Implemented Fixed Effects, still working on the command
Fixed a few bugs
This commit is contained in:
Esophose 2017-02-15 22:05:50 -07:00
parent 26866f9052
commit 69dddacd92
32 changed files with 1062 additions and 158 deletions

20
PlayerParticles.jardesc Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<jardesc>
<jar path="C:/Users/Esophose/Desktop/1.11.2 Dev Server/plugins/update/PlayerParticles v4.3 BETA.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/PlayerParticles/PlayerParticles.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="false" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>
<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
<sealing sealJar="false">
<packagesToSeal/>
<packagesToUnSeal/>
</sealing>
</manifest>
<selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
<javaElement handleIdentifier="=PlayerParticles/src"/>
<file path="/PlayerParticles/.gitignore"/>
<file path="/PlayerParticles/.classpath"/>
<file path="/PlayerParticles/.gitattributes"/>
<file path="/PlayerParticles/.project"/>
</selectedElements>
</jardesc>

View file

@ -0,0 +1,222 @@
/**
* Copyright Esophose 2016
* While using any of the code provided by this plugin
* you must not claim it as your own. This plugin may
* be modified and installed on a server, but may not
* be distributed to any person by any means.
*/
package com.esophose.playerparticles;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import com.esophose.playerparticles.library.ParticleEffect;
import com.esophose.playerparticles.library.ParticleEffect.BlockData;
import com.esophose.playerparticles.library.ParticleEffect.ItemData;
import com.esophose.playerparticles.library.ParticleEffect.NoteColor;
import com.esophose.playerparticles.library.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.library.ParticleEffect.ParticleColor;
import com.esophose.playerparticles.library.ParticleEffect.ParticleData;
import com.esophose.playerparticles.library.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.manager.ConfigManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class FixedParticleEffect {
/**
* The UUID of the player who owns this effect
*/
private UUID pplayerUUID;
/**
* The ID of this effect, unique to the owner's UUID
*/
private int id;
/**
* The location for this effect to be displayed
*/
private Location location;
/**
* The effect and style this effect uses
*/
private ParticleEffect particleEffect;
private ParticleStyle particleStyle;
/**
* The data this effect uses
*/
private ItemData particleItemData;
private BlockData particleBlockData;
private OrdinaryColor particleColorData;
private NoteColor particleNoteColorData;
/**
* Constructs a new FixedParticleEffect
* FixedParticleEffects can NOT use custom handled styles
* This is basically the same thing as a PPlayer, maybe we can extend it in the future?
*
* @param pplayerUUID The UUID of the player who owns the effect
* @param worldName The world name this effect will be displayed in
* @param xPos The X position in the world
* @param yPos The Y position in the world
* @param zPos The Z position in the world
* @param particleEffect The particle effect to use
* @param particleStyle The particle style to use
* @param particleData The particle data to use with the effect
*/
public FixedParticleEffect(UUID pplayerUUID, int id, String worldName, double xPos, double yPos, double zPos, ParticleEffect particleEffect, ParticleStyle particleStyle, ItemData itemData, BlockData blockData, OrdinaryColor colorData, NoteColor noteColorData) {
this.pplayerUUID = pplayerUUID;
this.id = id;
this.particleEffect = particleEffect;
this.particleStyle = particleStyle;
this.particleItemData = itemData;
this.particleBlockData = blockData;
this.particleColorData = colorData;
this.particleNoteColorData = noteColorData;
PPlayer owner = ConfigManager.getInstance().getPPlayer(this.pplayerUUID, false);
// Check nulls, if any are null set them to the PPlayer's values
if (this.particleItemData == null) this.particleItemData = owner.getItemData();
if (this.particleBlockData == null) this.particleBlockData = owner.getBlockData();
if (this.particleColorData == null) this.particleColorData = owner.getColorData();
if (this.particleNoteColorData == null) this.particleNoteColorData = owner.getNoteColorData();
World world = Bukkit.getWorld(worldName);
if (world == null) { // Default to the first world in case it doesn't exist
world = Bukkit.getWorlds().get(0); // All servers will have at least one world
}
this.location = new Location(world, xPos, yPos, zPos);
}
/**
* Gets the owner of the effect's UUID
*
* @return The owner of the effect's UUID
*/
public UUID getOwnerUniqueId() {
return this.pplayerUUID;
}
/**
* Gets the id unique to the owner's UUID
*
* @return This effect's id
*/
public int getId() {
return this.id;
}
/**
* Gets the particle effect used for this effect
*
* @return The particle effect used for this effect
*/
public ParticleEffect getParticleEffect() {
return this.particleEffect;
}
/**
* Gets the particle style used for this effect
*
* @return The particle style used for this effect
*/
public ParticleStyle getParticleStyle() {
return this.particleStyle;
}
/**
* Gets the effect's item data
*
* @return The effect's item data
*/
public ItemData getItemData() {
return this.particleItemData;
}
/**
* Gets the effect's block data
*
* @return The effect's block data
*/
public BlockData getBlockData() {
return this.particleBlockData;
}
/**
* Gets the effect's color data
*
* @return The effect's color data
*/
public OrdinaryColor getColorData() {
return this.particleColorData;
}
/**
* Gets the effect's note color data
*
* @return The effect's note color data
*/
public NoteColor getNoteColorData() {
return this.particleNoteColorData;
}
/**
* Gets the data the current particle effect will spawn with
*
* @return The ParticleData the current particle effect requires
*/
public ParticleData getParticleSpawnData() {
if (this.particleEffect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
if (this.particleEffect == ParticleEffect.BLOCK_CRACK || this.particleEffect == ParticleEffect.BLOCK_DUST || this.particleEffect == ParticleEffect.FALLING_DUST) {
return particleBlockData;
} else if (this.particleEffect == ParticleEffect.ITEM_CRACK) {
return this.particleItemData;
}
}
return null;
}
/**
* Gets the color the current particle effect will spawn with
*
* @return Gets the ParticleColor the current particle effect will spawn with
*/
public ParticleColor getParticleSpawnColor() {
if (this.particleEffect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.particleEffect == ParticleEffect.NOTE) {
if (this.particleNoteColorData.getValueX() * 24 == 99) {
return ParticleManager.getRainbowNoteParticleColor();
}
return this.particleNoteColorData;
} else {
if (this.particleColorData.getRed() == 999 && this.particleColorData.getGreen() == 999 && this.particleColorData.getBlue() == 999) {
return ParticleManager.getRainbowParticleColor();
} else {
return this.particleColorData;
}
}
}
return null;
}
/**
* Gets the location this effect will be displayed at
*
* @return The effect's location
*/
public Location getLocation() {
return this.location;
}
}

View file

@ -20,6 +20,7 @@ import com.esophose.playerparticles.library.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.library.ParticleEffect.ParticleColor;
import com.esophose.playerparticles.library.ParticleEffect.ParticleData;
import com.esophose.playerparticles.library.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
@ -57,12 +58,12 @@ public class PPlayer {
*/
public PPlayer(UUID uuid, ParticleEffect effect, ParticleStyle style, ItemData itemData, BlockData blockData, OrdinaryColor colorData, NoteColor noteColorData) {
this.playerUUID = uuid;
this.particleEffect = effect;
this.particleStyle = style;
this.particleItemData = itemData;
this.particleBlockData = blockData;
this.particleColorData = colorData;
this.particleNoteColorData = noteColorData;
this.setParticleEffect(effect);
this.setParticleStyle(style);
this.setItemData(itemData);
this.setBlockData(blockData);
this.setColorData(colorData);
this.setNoteColorData(noteColorData);
}
/**
@ -134,6 +135,7 @@ public class PPlayer {
* @param effect The player's new particle effect
*/
public void setParticleEffect(ParticleEffect effect) {
if (effect == null) effect = ParticleEffect.NONE;
this.particleEffect = effect;
}
@ -143,6 +145,7 @@ public class PPlayer {
* @param effect The player's new particle style
*/
public void setParticleStyle(ParticleStyle style) {
if (style == null) style = DefaultStyles.NONE;
this.particleStyle = style;
}
@ -152,6 +155,7 @@ public class PPlayer {
* @param effect The player's new item data
*/
public void setItemData(ItemData itemData) {
if (itemData == null) itemData = new ItemData(Material.IRON_SPADE, (byte) 0);
this.particleItemData = itemData;
}
@ -161,6 +165,7 @@ public class PPlayer {
* @param effect The player's new block data
*/
public void setBlockData(BlockData blockData) {
if (blockData == null) blockData = new BlockData(Material.STONE, (byte) 0);
this.particleBlockData = blockData;
}
@ -170,6 +175,7 @@ public class PPlayer {
* @param effect The player's new color data
*/
public void setColorData(OrdinaryColor colorData) {
if (colorData == null) colorData = new OrdinaryColor(0, 0, 0);
this.particleColorData = colorData;
}
@ -179,6 +185,7 @@ public class PPlayer {
* @param effect The player's new note color data
*/
public void setNoteColorData(NoteColor noteColorData) {
if (noteColorData == null) noteColorData = new NoteColor(0);
this.particleNoteColorData = noteColorData;
}
@ -188,11 +195,11 @@ public class PPlayer {
* @return The ParticleData the current particle effect requires
*/
public ParticleData getParticleSpawnData() {
if (particleEffect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
if (particleEffect == ParticleEffect.BLOCK_CRACK || particleEffect == ParticleEffect.BLOCK_DUST || particleEffect == ParticleEffect.FALLING_DUST) {
if (this.particleEffect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
if (this.particleEffect == ParticleEffect.BLOCK_CRACK || this.particleEffect == ParticleEffect.BLOCK_DUST || this.particleEffect == ParticleEffect.FALLING_DUST) {
return particleBlockData;
} else if (particleEffect == ParticleEffect.ITEM_CRACK) {
return particleItemData;
} else if (this.particleEffect == ParticleEffect.ITEM_CRACK) {
return this.particleItemData;
}
}
return null;
@ -204,17 +211,17 @@ public class PPlayer {
* @return Gets the ParticleColor the current particle effect will spawn with
*/
public ParticleColor getParticleSpawnColor() {
if (particleEffect.hasProperty(ParticleProperty.COLORABLE)) {
if (particleEffect == ParticleEffect.NOTE) {
if (particleNoteColorData.getValueX() * 24 == 99) {
return ParticleCreator.getRainbowNoteParticleColor();
if (this.particleEffect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.particleEffect == ParticleEffect.NOTE) {
if (this.particleNoteColorData.getValueX() * 24 == 99) {
return ParticleManager.getRainbowNoteParticleColor();
}
return particleNoteColorData;
return this.particleNoteColorData;
} else {
if (particleColorData.getRed() == 999 && particleColorData.getGreen() == 999 && particleColorData.getBlue() == 999) {
return ParticleCreator.getRainbowParticleColor();
if (this.particleColorData.getRed() == 999 && this.particleColorData.getGreen() == 999 && this.particleColorData.getBlue() == 999) {
return ParticleManager.getRainbowParticleColor();
} else {
return particleColorData;
return this.particleColorData;
}
}
}

View file

@ -40,6 +40,8 @@ public class ParticleCommandCompleter implements TabCompleter {
list.add("styles");
list.add("worlds");
list.add("version");
list.add("fixed");
list.add("reset");
return list;
} else if (args.length == 1) {
if (args[0].equalsIgnoreCase("effect")) {

View file

@ -27,10 +27,12 @@ import com.esophose.playerparticles.library.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.manager.ConfigManager;
import com.esophose.playerparticles.manager.MessageManager;
import com.esophose.playerparticles.manager.MessageManager.MessageType;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticlesUtils;
public class ParticleCommandExecutor implements CommandExecutor {
@ -80,6 +82,9 @@ public class ParticleCommandExecutor implements CommandExecutor {
case "data":
onData(p, cmdArgs);
break;
case "fixed":
onFixed(p, cmdArgs);
break;
case "reset":
onReset(p, cmdArgs);
break;
@ -149,7 +154,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
* @param args The arguments for the command
*/
private void onData(Player p, String[] args) {
ParticleEffect effect = ConfigManager.getInstance().getPPlayer(p.getUniqueId()).getParticleEffect();
ParticleEffect effect = ConfigManager.getInstance().getPPlayer(p.getUniqueId(), false).getParticleEffect();
if ((!effect.hasProperty(ParticleProperty.REQUIRES_DATA) && !effect.hasProperty(ParticleProperty.COLORABLE)) || args.length == 0) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
@ -235,7 +240,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
int data = -1;
try {
material = ParticlesUtil.closestMatch(args[0]);
material = ParticlesUtils.closestMatch(args[0]);
if (material == null) material = Material.matchMaterial(args[0]);
if (material == null) throw new Exception();
} catch (Exception e) {
@ -271,7 +276,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
int data = -1;
try {
material = ParticlesUtil.closestMatch(args[0]);
material = ParticlesUtils.closestMatch(args[0]);
if (material == null) material = Material.matchMaterial(args[0]);
if (material == null) throw new Exception();
} catch (Exception e) {
@ -308,11 +313,11 @@ public class ParticleCommandExecutor implements CommandExecutor {
/**
* Called when a player uses /pp reset
* Can be executed for another player by having their name as the final command argument
*
* @param p The player who used the command
* @param altPlayer The alternate player to reset
*/
private void onReset(Player p, String[] args) { // TODO: Apply this to effects, styles, and data(?)
private void onReset(Player p, String[] args) {
if (args.length >= 1) {
String altPlayerName = args[0];
if (!PermissionManager.canExecuteForOthers(p)) {
@ -320,7 +325,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
} else {
Player altPlayer = getOnlinePlayerByName(altPlayerName);
if (altPlayer == null) {
MessageManager.sendMessage(p, MessageType.FAILED_EXECUTE_NOT_FOUND);
MessageManager.sendMessage(p, MessageType.FAILED_EXECUTE_NOT_FOUND, altPlayerName);
} else {
ConfigManager.getInstance().resetPPlayer(altPlayer.getUniqueId());
MessageManager.sendMessage(altPlayer, MessageType.RESET);
@ -339,7 +344,6 @@ public class ParticleCommandExecutor implements CommandExecutor {
*
* @param p The player who used the command
* @param args The arguments for the command
* @param altPlayer The alternate player to give the effect
*/
private void onEffect(Player p, String[] args) {
if (args.length == 0) {
@ -347,8 +351,8 @@ public class ParticleCommandExecutor implements CommandExecutor {
return;
}
String argument = args[0].replace("_", "");
if (ParticleCreator.particleFromString(argument) != null) {
ParticleEffect effect = ParticleCreator.particleFromString(argument);
if (ParticleManager.particleFromString(argument) != null) {
ParticleEffect effect = ParticleManager.particleFromString(argument);
if (!PermissionManager.hasEffectPermission(p, effect)) {
MessageManager.sendMessage(p, MessageType.NO_PERMISSION, effect.getName().toLowerCase());
return;
@ -393,7 +397,6 @@ public class ParticleCommandExecutor implements CommandExecutor {
*
* @param p The player who used the command
* @param args The arguments for the command
* @param altPlayer The alternate player to give the style
*/
private void onStyle(Player p, String[] args) {
if (args.length == 0) {
@ -441,5 +444,61 @@ public class ParticleCommandExecutor implements CommandExecutor {
MessageManager.sendCustomMessage(p, toSend);
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.STYLE_USAGE.getMessage());
}
/*
Requires permission playerparticles.fixed
Maximum number of fixed effects defined in config.yml, default value 5
*/
/**
* Called when a player uses /pp fixed
*
* @param p The player who used the command
* @param args The arguments for the command
*/
private void onFixed(Player p, String[] args) {
if (!PermissionManager.canUseFixedEffects(p)) {
MessageManager.sendMessage(p, MessageType.NO_PERMISSION_FIXED);
return;
}
if (args.length == 0) { // General information on command
MessageManager.sendMessage(p, MessageType.INVALID_FIXED_COMMAND);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_CREATE);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_REMOVE);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_LIST);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_INFO);
return;
}
String cmd = args[0];
if (cmd.equalsIgnoreCase("create")) {
if (ConfigManager.getInstance().getNumberOfFixedEffectsForPlayer(p.getUniqueId()) > PlayerParticles.getPlugin().getConfig().getInt("max-fixed-effects")) {
}
// /pp fixed create <x> <y> <z> <effect> <style> [data] - Creates a fixed effect and assigns it an id
} else if (cmd.equalsIgnoreCase("remove")) {
// /pp fixed remove <id> - Removes a fixed effect by its id
} else if (cmd.equalsIgnoreCase("list")) {
// /pp fixed list - Lists the location, and id of all fixed effects
} else if (cmd.equalsIgnoreCase("info")) {
// /pp fixed info <id> - Lists all information about the fixed effect with the matching id
} else {
MessageManager.sendMessage(p, MessageType.INVALID_FIXED_COMMAND);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_CREATE);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_REMOVE);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_LIST);
MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_INFO);
}
// Test data
//ConfigManager.getInstance().saveFixedEffect(new FixedParticleEffect(p.getUniqueId(), ConfigManager.getInstance().getNextFixedEffectId(p.getUniqueId()), p.getLocation().getWorld().getName(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), ParticleEffect.RED_DUST, DefaultStyles.ARROWS, null, null, new OrdinaryColor(999, 999, 999), null));
}
}

View file

@ -1,37 +0,0 @@
/**
* Copyright Esophose 2016
* While using any of the code provided by this plugin
* you must not claim it as your own. This plugin may
* be modified and installed on a server, but may not
* be distributed to any person by any means.
*/
package com.esophose.playerparticles;
import java.util.ArrayList;
import org.bukkit.Material;
public class ParticlesUtil {
/**
* Finds a block/item as a material from a string
* There must be some better way to do this that reliably gets the correct material
*
* @param input The material name as a string
* @return The material from the string
*/
@SuppressWarnings("deprecation")
public static Material closestMatch(String input) {
ArrayList<Material> matchList = new ArrayList<Material>();
for (Material mat : Material.values())
if (mat.name().replace("_", " ").toLowerCase().equals(input.toLowerCase()) || String.valueOf(mat.getId()).equals(input))
return mat;
else if (mat.name().replace("_", " ").toLowerCase().contains(input.toLowerCase()))
matchList.add(mat);
if (matchList.size() == 1) return matchList.get(0);
else return null;
}
}

View file

@ -7,21 +7,30 @@
*/
/*
v4.2 Changelog
v4.3 Changelog
* Fix effects and styles not defaulting to 'none' if the player no longer has permission
* Fix errors printing to console resulting from offline players trying to spawn particles
* Fix arrow style particles staying after an arrow is considered dead (in rare cases this occurred)
* Fix SQL queries getting logged to console when database-enable is set to true
* Added new style 'thick'
+ Added new style 'arrows'
* Renamed style 'spiral' to 'beam'
+ Added new style 'spiral'
* Spawning particles is now more efficient
* Checking disabled worlds is now taken from cache
+ Rainbow colorable particles - /pp data rainbow for any colorable particle
TODO:
+ Add command /pp fixed -
/pp fixed create <x> <y> <z> <effect> <style> [data] - Creates a fixed effect and assigns it an id
/pp fixed remove <id> - Removes a fixed effect by its id
/pp fixed list - Lists the location, and id of all fixed effects
/pp fixed info <id> - Lists all information about the fixed effect with the matching id
Requires permission playerparticles.fixed
Maximum number of fixed effects defined in config.yml, default value 5
+ Add player variable in commands
Requires permission playerparticles.altexecute
+ Add new style 'tornado'
+ Add new style 'atom'
+ Fixed particle spawn locations
+ GUI for styles and effects
/pp gui - Shows GUI that tells you your current effect, style, and data and lets you choose new ones
/pp gui effect - Shows GUI that lets you select a new effect, also shows your current one
/pp gui style - Shows GUI that lets you select a new style, also shows your current one
/pp gui data - Shows GUI that lets you choose from preset data based on your current effect, also shows your current data
*/
package com.esophose.playerparticles;
@ -36,6 +45,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import com.esophose.playerparticles.library.MySQL;
import com.esophose.playerparticles.manager.MessageManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.updater.PluginUpdateListener;
import com.esophose.playerparticles.updater.Updater;
@ -75,17 +85,18 @@ public class PlayerParticles extends JavaPlugin {
saveDefaultConfig();
getCommand("pp").setTabCompleter(new ParticleCommandCompleter());
getCommand("pp").setExecutor(new ParticleCommandExecutor());
Bukkit.getPluginManager().registerEvents(new ParticleCreator(), this);
Bukkit.getPluginManager().registerEvents(new ParticleManager(), this);
Bukkit.getPluginManager().registerEvents(new PluginUpdateListener(), this);
if (getConfig().getDouble("version") < Double.parseDouble(getDescription().getVersion())) {
File configFile = new File(getDataFolder(), "config.yml");
configFile.delete();
saveDefaultConfig();
reloadConfig();
getLogger().warning("[PlayerParticles] config.yml has been updated!");
getLogger().warning("The config.yml has been updated to v" + getDescription().getVersion() + "!");
}
checkDatabase();
ParticleCreator.refreshPPlayers();
ParticleManager.refreshPPlayers();
ParticleManager.addAllFixedEffects();
startTask();
if (shouldCheckUpdates()) {
@ -130,30 +141,38 @@ public class PlayerParticles extends JavaPlugin {
String user = getConfig().getString("database-user-name");
String pass = getConfig().getString("database-user-password");
mySQL = new MySQL(hostname, port, database, user, pass);
try (ResultSet res = mySQL.querySQL("SHOW TABLES LIKE 'playerparticles'")) { // Clean up the old mess
if (res.next()) {
mySQL.updateSQL("DROP TABLE playerparticles");
}
} catch (ClassNotFoundException | SQLException e1) {
getLogger().info("[PlayerParticles] Failed to connect to the MySQL Database! Check to see if your login information is correct!");
useMySQL = false;
return;
}
useMySQL = true; // If something goes wrong this will be set to false
// @formatter:off
try (ResultSet res = mySQL.querySQL("SHOW TABLES LIKE 'pp_users'")) {
if (!res.next()) { // @formatter:off
if (res.next()) { // Add the new fixed table and rename some columns
try (ResultSet res2 = mySQL.querySQL("SHOW TABLES LIKE 'pp_fixed'")) {
if (!res2.next()) { // Using an old database, update to the new one
mySQL.updateSQL("CREATE TABLE pp_fixed (uuid VARCHAR(36), player_uuid VARCHAR(36), id SMALLINT, effect VARCHAR(32), style VARCHAR(32), worldName VARCHAR(50), xPos DOUBLE, yPos DOUBLE, zPos DOUBLE);" +
"ALTER TABLE pp_data_item CHANGE player_uuid uuid VARCHAR(36);" +
"ALTER TABLE pp_data_block CHANGE player_uuid uuid VARCHAR(36);" +
"ALTER TABLE pp_data_color CHANGE player_uuid uuid VARCHAR(36);" +
"ALTER TABLE pp_data_note CHANGE player_uuid uuid VARCHAR(36);");
}
} catch (Exception e) {
throw e; // Try-catch block here is just for auto closure
}
} else { // No database is set up yet, create it
mySQL.updateSQL("CREATE TABLE pp_users (player_uuid VARCHAR(36), effect VARCHAR(32), style VARCHAR(32));" +
"CREATE TABLE pp_data_item (player_uuid VARCHAR(36), material VARCHAR(32), data SMALLINT);" +
"CREATE TABLE pp_data_block (player_uuid VARCHAR(36), material VARCHAR(32), data SMALLINT);" +
"CREATE TABLE pp_data_color (player_uuid VARCHAR(36), r SMALLINT, g SMALLINT, b SMALLINT);" +
"CREATE TABLE pp_data_note (player_uuid VARCHAR(36), note SMALLINT);"
); // @formatter:on
"CREATE TABLE pp_fixed (uuid VARCHAR(36), player_uuid VARCHAR(36), id SMALLINT, effect VARCHAR(32), style VARCHAR(32), worldName VARCHAR(50), xPos DOUBLE, yPos DOUBLE, zPos DOUBLE);" +
"CREATE TABLE pp_data_item (uuid VARCHAR(36), material VARCHAR(32), data SMALLINT);" +
"CREATE TABLE pp_data_block (uuid VARCHAR(36), material VARCHAR(32), data SMALLINT);" +
"CREATE TABLE pp_data_color (uuid VARCHAR(36), r SMALLINT, g SMALLINT, b SMALLINT);" +
"CREATE TABLE pp_data_note (uuid VARCHAR(36), note SMALLINT);"
);
}
useMySQL = true;
} catch (ClassNotFoundException | SQLException e) {
getLogger().info("[PlayerParticles] Failed to connect to the MySQL Database! Check to see if your login information is correct!");
getLogger().info("Additional information: " + e.getMessage());
useMySQL = false;
}
return;
} // @formatter:on
} else {
useMySQL = false;
}
@ -164,7 +183,7 @@ public class PlayerParticles extends JavaPlugin {
*/
private void startTask() {
double ticks = getConfig().getInt("ticks-per-particle");
new ParticleCreator().runTaskTimer(this, 20, (long) ticks);
new ParticleManager().runTaskTimer(this, 20, (long) ticks);
}
}

View file

@ -0,0 +1,9 @@
package com.esophose.playerparticles.gui;
public class GUIHandler {
public GUIHandler() {
// TODO Auto-generated constructor stub
}
}

View file

@ -82,8 +82,6 @@ public abstract class Database {
openConnection();
}
System.out.println("Running Query: " + query);
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery(query);
@ -117,6 +115,7 @@ public abstract class Database {
for (String q : queries) {
statement.addBatch(q);
}
results = statement.executeBatch();
} else {
results = new int[] { statement.executeUpdate(query) };

View file

@ -12,16 +12,19 @@ import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import com.esophose.playerparticles.FixedParticleEffect;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.ParticleCreator;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.library.ParticleEffect;
import com.esophose.playerparticles.library.ParticleEffect.BlockData;
@ -30,6 +33,7 @@ import com.esophose.playerparticles.library.ParticleEffect.NoteColor;
import com.esophose.playerparticles.library.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticlesUtils;
public class ConfigManager {
@ -45,7 +49,7 @@ public class ConfigManager {
* The configuration used to edit the .yaml file
*/
private FileConfiguration config;
/**
* The disabled worlds cached for quick access
*/
@ -91,13 +95,17 @@ public class ConfigManager {
/**
* Gets a player from the save data, creates one if it doesn't exist and adds it to the list
*/
public PPlayer getPPlayer(UUID playerUUID) {
for (PPlayer pp : ParticleCreator.particlePlayers) {
public PPlayer getPPlayer(UUID playerUUID, boolean addIfNotFound) {
for (PPlayer pp : ParticleManager.particlePlayers) {
if (pp.getUniqueId() == playerUUID) return pp;
}
PPlayer pplayer = buildPPlayer(playerUUID);
ParticleCreator.particlePlayers.add(pplayer);
if (addIfNotFound && Bukkit.getPlayer(playerUUID) != null) {
ParticleManager.particlePlayers.add(pplayer);
}
return pplayer;
}
@ -135,10 +143,10 @@ public class ConfigManager {
} else {
String id = playerUUID.toString(); // @formatter:off
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT * FROM pp_users u " +
"JOIN pp_data_item i ON u.player_uuid = i.player_uuid " +
"JOIN pp_data_block b ON u.player_uuid = b.player_uuid " +
"JOIN pp_data_color c ON u.player_uuid = c.player_uuid " +
"JOIN pp_data_note n ON u.player_uuid = n.player_uuid " +
"JOIN pp_data_item i ON u.player_uuid = i.uuid " +
"JOIN pp_data_block b ON u.player_uuid = b.uuid " +
"JOIN pp_data_color c ON u.player_uuid = c.uuid " +
"JOIN pp_data_note n ON u.player_uuid = n.uuid " +
"WHERE u.player_uuid = '" + id + "'")) { // @formatter:on
if (res.next()) {
@ -212,23 +220,23 @@ public class ConfigManager {
"'" + pplayer.getParticleEffect().getName() + "', " +
"'" + pplayer.getParticleStyle().getName() + "'" +
"); " +
"INSERT INTO pp_data_item (player_uuid, material, data) VALUES (" +
"INSERT INTO pp_data_item (uuid, material, data) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
"'" + pplayer.getItemData().getMaterial().name() + "', " +
pplayer.getItemData().getData() +
"); " +
"INSERT INTO pp_data_block (player_uuid, material, data) VALUES (" +
"INSERT INTO pp_data_block (uuid, material, data) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
"'" + pplayer.getBlockData().getMaterial().name() + "', " +
pplayer.getBlockData().getData() +
"); " +
"INSERT INTO pp_data_color (player_uuid, r, g, b) VALUES (" +
"INSERT INTO pp_data_color (uuid, r, g, b) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
pplayer.getColorData().getRed() + ", " +
pplayer.getColorData().getGreen() + ", " +
pplayer.getColorData().getBlue() +
"); " +
"INSERT INTO pp_data_note (player_uuid, note) VALUES (" +
"INSERT INTO pp_data_note (uuid, note) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
(byte) (pplayer.getNoteColorData().getValueX() * 24) +
");"
@ -239,7 +247,7 @@ public class ConfigManager {
}
}
ParticleCreator.updateIfContains(pplayer); // Update the player in case this is a /pp reset
ParticleManager.updateIfContains(pplayer); // Update the player in case this is a /pp reset
}
/**
@ -276,7 +284,7 @@ public class ConfigManager {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setParticleEffect(particleEffect);
getPPlayer(playerUUID, false).setParticleEffect(particleEffect);
}
/**
@ -297,7 +305,7 @@ public class ConfigManager {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setParticleStyle(particleStyle);
getPPlayer(playerUUID, false).setParticleStyle(particleStyle);
}
/**
@ -314,12 +322,12 @@ public class ConfigManager {
save();
} else {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_item SET material = '" + particleItemData.getMaterial().name() + "', data = '" + particleItemData.getData() + "' WHERE player_uuid = '" + playerUUID + "';");
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_item SET material = '" + particleItemData.getMaterial().name() + "', data = '" + particleItemData.getData() + "' WHERE uuid = '" + playerUUID + "';");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setItemData(particleItemData);
getPPlayer(playerUUID, false).setItemData(particleItemData);
}
/**
@ -336,12 +344,12 @@ public class ConfigManager {
save();
} else {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_block SET material = '" + particleBlockData.getMaterial().name() + "', data = '" + particleBlockData.getData() + "' WHERE player_uuid = '" + playerUUID + "';");
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_block SET material = '" + particleBlockData.getMaterial().name() + "', data = '" + particleBlockData.getData() + "' WHERE uuid = '" + playerUUID + "';");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setBlockData(particleBlockData);
getPPlayer(playerUUID, false).setBlockData(particleBlockData);
}
/**
@ -359,12 +367,12 @@ public class ConfigManager {
save();
} else {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_color SET r = " + particleColorData.getRed() + ", g = " + particleColorData.getGreen() + ", b = " + particleColorData.getBlue() + " WHERE player_uuid = '" + playerUUID + "';");
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_color SET r = " + particleColorData.getRed() + ", g = " + particleColorData.getGreen() + ", b = " + particleColorData.getBlue() + " WHERE uuid = '" + playerUUID + "';");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setColorData(particleColorData);
getPPlayer(playerUUID, false).setColorData(particleColorData);
}
/**
@ -380,12 +388,292 @@ public class ConfigManager {
save();
} else {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_note SET note = " + (byte) (particleNoteColorData.getValueX() * 24) + " WHERE player_uuid = '" + playerUUID + "';");
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_note SET note = " + (byte) (particleNoteColorData.getValueX() * 24) + " WHERE uuid = '" + playerUUID + "';");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
getPPlayer(playerUUID).setNoteColorData(particleNoteColorData);
getPPlayer(playerUUID, false).setNoteColorData(particleNoteColorData);
}
/**
* Saves a fixed effect to save data
*
* @param fixedEffect The fixed effect to save
*/
public void saveFixedEffect(FixedParticleEffect fixedEffect) {
if (!PlayerParticles.useMySQL) {
if (!config.isConfigurationSection(fixedEffect.getOwnerUniqueId().toString() + ".fixedEffect." + fixedEffect.getId())) {
ConfigurationSection baseSection = config.createSection(fixedEffect.getOwnerUniqueId().toString() + ".fixedEffect." + fixedEffect.getId());
baseSection.createSection("effect");
baseSection.createSection("style");
baseSection.createSection("itemData");
baseSection.createSection("blockData");
baseSection.createSection("colorData");
baseSection.createSection("noteColorData");
} else {
System.out.println("Tried to create a fixed effect with ID " + fixedEffect.getId() + " that already exists!");
return;
}
ConfigurationSection section = config.getConfigurationSection(fixedEffect.getOwnerUniqueId().toString() + ".fixedEffect." + fixedEffect.getId());
ConfigurationSection effectSection = section.getConfigurationSection("effect");
ConfigurationSection styleSection = section.getConfigurationSection("style");
ConfigurationSection itemDataSection = section.getConfigurationSection("itemData");
ConfigurationSection blockDataSection = section.getConfigurationSection("blockData");
ConfigurationSection colorDataSection = section.getConfigurationSection("colorData");
ConfigurationSection noteColorDataSection = section.getConfigurationSection("noteColorData");
section.set("id", fixedEffect.getId());
section.set("worldName", fixedEffect.getLocation().getWorld().getName());
section.set("xPos", fixedEffect.getLocation().getX());
section.set("yPos", fixedEffect.getLocation().getY());
section.set("zPos", fixedEffect.getLocation().getZ());
effectSection.set("name", fixedEffect.getParticleEffect().getName());
styleSection.set("name", fixedEffect.getParticleStyle().getName());
itemDataSection.set("material", fixedEffect.getItemData().getMaterial().name());
itemDataSection.set("data", fixedEffect.getItemData().getData());
blockDataSection.set("material", fixedEffect.getBlockData().getMaterial().name());
blockDataSection.set("data", fixedEffect.getBlockData().getData());
colorDataSection.set("r", fixedEffect.getColorData().getRed());
colorDataSection.set("g", fixedEffect.getColorData().getGreen());
colorDataSection.set("b", fixedEffect.getColorData().getBlue());
noteColorDataSection.set("note", (byte) (fixedEffect.getNoteColorData().getValueX() * 24));
save();
} else {
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT * FROM pp_fixed WHERE player_uuid = '" + fixedEffect.getOwnerUniqueId() + "' AND id = " + fixedEffect.getId())) {
if (res.next()) {
System.out.println("Tried to create a fixed effect with ID " + fixedEffect.getId() + " that already in the database!");
} else { // @formatter:off
String fixedEffectUUID = UUID.randomUUID().toString();
PlayerParticles.mySQL.updateSQL("INSERT INTO pp_fixed (uuid, player_uuid, id, effect, style, worldName, xPos, yPos, zPos) VALUES (" +
"'" + fixedEffectUUID + "', " +
"'" + fixedEffect.getOwnerUniqueId().toString() + "', " +
fixedEffect.getId() + ", " +
"'" + fixedEffect.getParticleEffect().getName() + "', " +
"'" + fixedEffect.getParticleStyle().getName() + "', " +
"'" + fixedEffect.getLocation().getWorld().getName() + "', " +
fixedEffect.getLocation().getX() + ", " +
fixedEffect.getLocation().getY() + ", " +
fixedEffect.getLocation().getZ() +
"); " +
"INSERT INTO pp_data_item (uuid, material, data) VALUES (" +
"'" + fixedEffectUUID + "', " +
"'" + fixedEffect.getItemData().getMaterial().name() + "', " +
fixedEffect.getItemData().getData() +
"); " +
"INSERT INTO pp_data_block (uuid, material, data) VALUES (" +
"'" + fixedEffectUUID + "', " +
"'" + fixedEffect.getBlockData().getMaterial().name() + "', " +
fixedEffect.getBlockData().getData() +
"); " +
"INSERT INTO pp_data_color (uuid, r, g, b) VALUES (" +
"'" + fixedEffectUUID + "', " +
fixedEffect.getColorData().getRed() + ", " +
fixedEffect.getColorData().getGreen() + ", " +
fixedEffect.getColorData().getBlue() +
"); " +
"INSERT INTO pp_data_note (uuid, note) VALUES (" +
"'" + fixedEffectUUID + "', " +
(byte) (fixedEffect.getNoteColorData().getValueX() * 24) +
");"
);
} // @formatter:on
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
ParticleManager.addFixedEffect(fixedEffect);
}
/**
* Deletes a fixed effect from save data
*
* @param playerUUID The player who owns the effect
* @param id The id of the effect to remove
*/
public void deleteFixedEffect(UUID playerUUID, int id) {
if (!PlayerParticles.useMySQL) {
if (!config.isConfigurationSection(playerUUID.toString() + ".fixedEffect." + id)) {
System.out.println("Tried to remove a fixed effect with ID " + id + " that doesn't exists!");
return;
}
config.set(playerUUID.toString() + ".fixedEffect." + id, null);
save();
} else {
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "' AND id = " + id)) {
if (!res.next()) {
System.out.println("Tried to remove a fixed effect with ID " + id + " doesn't exist in the database!");
return;
} else { // @formatter:off
String uuid = res.getString("uuid");
PlayerParticles.mySQL.updateSQL("DELETE FROM pp_fixed WHERE uuid = '" + uuid + "';" +
"DELETE FROM pp_data_item WHERE uuid = '" + uuid + "';" +
"DELETE FROM pp_data_block WHERE uuid = '" + uuid + "';" +
"DELETE FROM pp_data_color WHERE uuid = '" + uuid + "';" +
"DELETE FROM pp_data_note WHERE uuid '" + uuid + "';"
);
} // @formatter:on
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
ParticleManager.removeFixedEffectForPlayer(playerUUID, id);
}
/**
* Resets all fixed effects for a given player
*
* @param playerUUID The player to remove all effects from
*/
public void resetFixedEffects(UUID playerUUID) {
if (!PlayerParticles.useMySQL) {
config.set(playerUUID.toString() + ".fixedEffect", null);
save();
} else {
try { // @formatter:off
PlayerParticles.mySQL.updateSQL("DELETE FROM pp_data_item WHERE uuid IN (SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "');" +
"DELETE FROM pp_data_block WHERE uuid IN (SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "');" +
"DELETE FROM pp_data_color WHERE uuid IN (SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "');" +
"DELETE FROM pp_data_note WHERE uuid IN (SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "');" +
"DELETE FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "';"
); // @formatter:on
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
ParticleManager.removeAllFixedEffectsForPlayer(playerUUID);
}
/**
* Gets a list of all saved fixed particle effects
*
* @return A list of all saved fixed particle effects
*/
public List<FixedParticleEffect> getAllFixedEffects() {
if (!PlayerParticles.useMySQL) {
List<FixedParticleEffect> fixedEffects = new ArrayList<FixedParticleEffect>();
Set<String> playerKeys = config.getKeys(false);
for (String playerKey : playerKeys) {
if (config.isConfigurationSection(playerKey + ".fixedEffect")) {
Set<String> fixedEffectKeys = config.getConfigurationSection(playerKey + ".fixedEffect").getKeys(false);
for (String fixedEffectKey : fixedEffectKeys) {
ConfigurationSection section = config.getConfigurationSection(playerKey + ".fixedEffect." + fixedEffectKey);
ConfigurationSection effectSection = section.getConfigurationSection("effect");
ConfigurationSection styleSection = section.getConfigurationSection("style");
ConfigurationSection itemDataSection = section.getConfigurationSection("itemData");
ConfigurationSection blockDataSection = section.getConfigurationSection("blockData");
ConfigurationSection colorDataSection = section.getConfigurationSection("colorData");
ConfigurationSection noteColorDataSection = section.getConfigurationSection("noteColorData");
int id = section.getInt("id");
String worldName = section.getString("worldName");
double xPos = section.getDouble("xPos");
double yPos = section.getDouble("yPos");
double zPos = section.getDouble("zPos");
ParticleEffect particleEffect = ParticleEffect.fromName(effectSection.getString("name"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(styleSection.getString("name"));
ItemData particleItemData = new ItemData(Material.matchMaterial(itemDataSection.getString("material")), (byte) itemDataSection.getInt("data"));
BlockData particleBlockData = new BlockData(Material.matchMaterial(blockDataSection.getString("material")), (byte) blockDataSection.getInt("data"));
OrdinaryColor particleColorData = new OrdinaryColor(colorDataSection.getInt("r"), colorDataSection.getInt("g"), colorDataSection.getInt("b"));
NoteColor particleNoteColorData = new NoteColor(noteColorDataSection.getInt("note"));
fixedEffects.add(new FixedParticleEffect(UUID.fromString(playerKey), id, worldName, xPos, yPos, zPos, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData));
}
}
}
return fixedEffects;
} else { // @formatter:off
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT * FROM pp_fixed f " +
"JOIN pp_data_item i ON f.uuid = i.uuid " +
"JOIN pp_data_block b ON f.uuid = b.uuid " +
"JOIN pp_data_color c ON f.uuid = c.uuid " +
"JOIN pp_data_note n ON f.uuid = n.uuid")) { // @formatter:on
List<FixedParticleEffect> fixedEffects = new ArrayList<FixedParticleEffect>();
while (res.next()) {
UUID pplayerUUID = UUID.fromString(res.getString("f.player_uuid"));
int id = res.getInt("f.id");
String worldName = res.getString("f.worldName");
double xPos = res.getDouble("f.xPos");
double yPos = res.getDouble("f.yPos");
double zPos = res.getDouble("f.zPos");
ParticleEffect particleEffect = ParticleManager.particleFromString(res.getString("f.effect"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(res.getString("f.style"));
ItemData particleItemData = new ItemData(Material.matchMaterial(res.getString("i.material")), res.getByte("i.data"));
BlockData particleBlockData = new BlockData(Material.matchMaterial(res.getString("b.material")), res.getByte("b.data"));
OrdinaryColor particleColorData = new OrdinaryColor(res.getInt("c.r"), res.getInt("c.g"), res.getInt("c.b"));
NoteColor particleNoteColorData = new NoteColor(res.getByte("n.note"));
fixedEffects.add(new FixedParticleEffect(pplayerUUID, id, worldName, xPos, yPos, zPos, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData));
}
return fixedEffects;
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
return null; // Something went wrong somewhere
}
public int getNumberOfFixedEffectsForPlayer(UUID pplayerUUID) {
if (!PlayerParticles.useMySQL) {
if (config.isConfigurationSection(pplayerUUID.toString() + ".fixedEffect")) {
return config.getConfigurationSection(pplayerUUID.toString() + ".fixedEffect").getKeys(false).size();
} else return 0;
} else {
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT COUNT(1) FROM pp_fixed WHERE player_uuid = '" + pplayerUUID.toString() + "'")) {
if (res.next()) {
return res.getInt(1);
} else return 0;
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
return 0;
}
/**
* Gets the next Id for a player's fixed effects
*
* @param playerUUID The player to get the Id for
* @return The smallest available Id the player can use
*/
public int getNextFixedEffectId(UUID playerUUID) {
if (!PlayerParticles.useMySQL) {
if (!config.isConfigurationSection(playerUUID.toString() + ".fixedEffect")) return 0;
Set<String> keys = config.getConfigurationSection(playerUUID.toString() + ".fixedEffect").getKeys(false);
int[] ids = new int[keys.size()];
int i = 0;
for (String key : keys)
ids[i++] = Integer.parseInt(key);
return ParticlesUtils.getSmallestPositiveInt(ids);
} else { // @formatter:off
try (ResultSet res = PlayerParticles.mySQL.querySQL("SELECT MIN(t1.id + 1) AS nextId FROM pp_fixed t1 " +
"LEFT JOIN pp_fixed t2 ON t1.id + 1 = t2.id " +
"WHERE t2.id IS NULL AND t1.player_uuid = '" + playerUUID.toString() + "'")) {
if (res.next()) { // @formatter:on
return res.getInt(1);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
return -1;
}
/**

View file

@ -50,6 +50,14 @@ public class MessageManager {
ITEM_DATA_USAGE("message-item-data-usage"),
BLOCK_DATA_USAGE("message-block-data-usage"),
// Fixed Effects
NO_PERMISSION_FIXED("message-no-permission-fixed"),
INVALID_FIXED_COMMAND("message-invalid-fixed-command"),
FIXED_COMMAND_DESC_CREATE("message-fixed-command-desc-create"),
FIXED_COMMAND_DESC_REMOVE("message-fixed-command-desc-remove"),
FIXED_COMMAND_DESC_LIST("message-fixed-command-desc-list"),
FIXED_COMMAND_DESC_INFO("message-fixed-command-desc-info"),
// Prefixes
USE("message-use"),
USAGE("message-usage"),

View file

@ -6,10 +6,11 @@
* be distributed to any person by any means.
*/
package com.esophose.playerparticles;
package com.esophose.playerparticles.manager;
import java.awt.Color;
import java.util.ArrayList;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@ -21,16 +22,17 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.FixedParticleEffect;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.library.ParticleEffect;
import com.esophose.playerparticles.library.ParticleEffect.NoteColor;
import com.esophose.playerparticles.library.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.library.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.manager.ConfigManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
public class ParticleCreator extends BukkitRunnable implements Listener {
public class ParticleManager extends BukkitRunnable implements Listener {
/**
* How far away particles will spawn from players
@ -42,6 +44,11 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
*/
public static ArrayList<PPlayer> particlePlayers = new ArrayList<PPlayer>();
/**
* The list containing all the fixed effect info
*/
public static ArrayList<FixedParticleEffect> fixedParticleEffects = new ArrayList<FixedParticleEffect>();
/**
* Rainbow particle effect hue and note color used for rainbow colorable effects
* These should be moved to a more appropriate place later
@ -56,7 +63,7 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
*/
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId());
ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId(), true);
}
/**
@ -66,9 +73,51 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
*/
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
particlePlayers.remove(ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId()));
particlePlayers.remove(ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId(), false));
}
/**
* Adds all fixed effects from the config
*/
public static void addAllFixedEffects() {
fixedParticleEffects.addAll(ConfigManager.getInstance().getAllFixedEffects());
}
/**
* Removes all fixed effects for the given pplayer
*
* @param pplayerUUID The pplayer to remove the fixed effects from
*/
public static void removeAllFixedEffectsForPlayer(UUID pplayerUUID) {
for (int i = fixedParticleEffects.size() - 1; i >= 0; i--) {
if (fixedParticleEffects.get(i).getOwnerUniqueId().equals(pplayerUUID))
fixedParticleEffects.remove(i);
}
}
/**
* Adds a fixed effect
*
* @param fixedEffect The fixed effect to add
*/
public static void addFixedEffect(FixedParticleEffect fixedEffect) {
fixedParticleEffects.add(fixedEffect);
}
/**
* Removes a fixed effect for the given pplayer with the given id
*
* @param pplayerUUID The pplayer to remove the fixed effect from
* @param id The id of the fixed effect to remove
*/
public static void removeFixedEffectForPlayer(UUID pplayerUUID, int id) {
for (int i = fixedParticleEffects.size() - 1; i >= 0; i--) {
if (fixedParticleEffects.get(i).getOwnerUniqueId().equals(pplayerUUID) &&
fixedParticleEffects.get(i).getId() == id)
fixedParticleEffects.remove(i);
}
}
/**
* Clears the list then adds everybody on the server
* Used for when the server reloads and we can't rely on players rejoining
@ -76,7 +125,7 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
public static void refreshPPlayers() {
particlePlayers.clear();
for (Player player : Bukkit.getOnlinePlayers()) {
ConfigManager.getInstance().getPPlayer(player.getUniqueId());
ConfigManager.getInstance().getPPlayer(player.getUniqueId(), true);
}
}
@ -123,17 +172,51 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
note %= 24;
}
// Loop for PPlayers
for (PPlayer pplayer : particlePlayers) {
Player player = Bukkit.getPlayer(pplayer.getUniqueId());
if (!PermissionManager.hasEffectPermission(player, pplayer.getParticleEffect())) continue;
if (ConfigManager.getInstance().isWorldDisabled(player.getWorld().getName())) continue;
if (player.getGameMode() == GameMode.SPECTATOR) continue;
if (player == null) continue; // Skip if they aren't online
// Perform permission and validity checks
boolean valid = true;
// If the player no longer has permission for the effect, remove it
if (!PermissionManager.hasEffectPermission(player, pplayer.getParticleEffect())) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), ParticleEffect.NONE);
valid = false;
}
// If the player no longer has permission for the style, default to none
if (!PermissionManager.hasStylePermission(player, pplayer.getParticleStyle())) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), DefaultStyles.NONE);
valid = false;
}
if (ConfigManager.getInstance().isWorldDisabled(player.getWorld().getName()) || player.getGameMode() == GameMode.SPECTATOR) {
valid = false;
}
if (!valid) continue;
Location loc = player.getLocation();
loc.setY(loc.getY() + 1);
displayParticles(pplayer, loc);
}
// Loop for FixedParticleEffects
for (FixedParticleEffect effect : fixedParticleEffects) {
boolean valid = true;
for (PPlayer pplayer: particlePlayers) {
if (pplayer.getUniqueId() == effect.getOwnerUniqueId()) {
valid = PermissionManager.canUseFixedEffects(Bukkit.getPlayer(pplayer.getUniqueId()));
}
}
if (valid) {
displayFixedParticleEffect(effect);
}
}
}
/**
@ -178,6 +261,25 @@ public class ParticleCreator extends BukkitRunnable implements Listener {
}
}
/**
* Displays particles at the given fixed effect location
*
* @param fixedEffect The fixed effect to display
*/
private void displayFixedParticleEffect(FixedParticleEffect fixedEffect) {
PPlayer fakePPlayer = new PPlayer(fixedEffect.getOwnerUniqueId(), fixedEffect.getParticleEffect(), fixedEffect.getParticleStyle(), null, null, null, null);
ParticleEffect effect = fixedEffect.getParticleEffect();
for (PParticle particle : fixedEffect.getParticleStyle().getParticles(fakePPlayer, fixedEffect.getLocation())) {
if (effect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
effect.display(fixedEffect.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(fixedEffect.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
}
}
}
public static OrdinaryColor getRainbowParticleColor() {
Color rgb = Color.getHSBColor(hue / 360F, 1.0F, 1.0F);
return new OrdinaryColor(rgb.getRed(), rgb.getGreen(), rgb.getBlue());

View file

@ -78,8 +78,24 @@ public class PermissionManager {
return list;
}
/**
* Checks if a player has permission to execute commands for other players
*
* @param player The player to check the permission for
* @return True if the player has permission
*/
public static boolean canExecuteForOthers(Player player) {
return player.hasPermission("playerparticles.other");
return player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.altexecute");
}
/**
* Checks if a player has permission to created fixed effects
*
* @param player The player to check the permission for
* @return True if the player has permission
*/
public static boolean canUseFixedEffects(Player player) {
return player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.fixed");
}
}

View file

@ -24,6 +24,7 @@ public class DefaultStyles {
public static ParticleStyle CUBE = new ParticleStyleCube();
public static ParticleStyle ARROWS = new ParticleStyleArrows();
public static ParticleStyle SPIRAL = new ParticleStyleSpiral();
public static ParticleStyle THICK = new ParticleStyleThick();
/**
* Registers all the default styles to the ParticleStyleManager
@ -41,6 +42,7 @@ public class DefaultStyles {
ParticleStyleManager.registerStyle(CUBE);
ParticleStyleManager.registerStyle(ARROWS);
ParticleStyleManager.registerStyle(SPIRAL);
ParticleStyleManager.registerStyle(THICK);
Bukkit.getPluginManager().registerEvents((Listener) MOVE, PlayerParticles.getPlugin());
Bukkit.getPluginManager().registerEvents((Listener) ARROWS, PlayerParticles.getPlugin());

View file

@ -16,18 +16,18 @@ import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleArrows implements ParticleStyle, Listener {
private List<Arrow> arrows = new ArrayList<Arrow>();
public PParticle[] getParticles(PPlayer pplayer, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (Arrow arrow : arrows) {
if (((Player) arrow.getShooter()).getUniqueId() == pplayer.getUniqueId()) {
particles.add(new PParticle(arrow.getLocation(), 0.05F, 0.05F, 0.05F, 0.0F));
}
}
return particles.toArray(new PParticle[particles.size()]);
}
@ -36,15 +36,19 @@ public class ParticleStyleArrows implements ParticleStyle, Listener {
*/
public void updateTimers() {
for (int i = arrows.size() - 1; i >= 0; i--) {
if (arrows.get(i).isDead())
arrows.remove(i);
Arrow arrow = arrows.get(i);
if (arrow.getTicksLived() >= 1200 || arrow.isDead() || !arrow.isValid()) arrows.remove(i);
}
}
public String getName() {
return "arrows";
}
public boolean canBeFixed() {
return false;
}
/**
* The event used to get all arrows fired by players
* Adds all arrows fired from players to the array
@ -54,7 +58,7 @@ public class ParticleStyleArrows implements ParticleStyle, Listener {
@EventHandler
public void onArrowFired(EntityShootBowEvent e) {
if (e.getEntityType() == EntityType.PLAYER && e.getProjectile().getType() == EntityType.ARROW) {
arrows.add((Arrow) e.getProjectile());
arrows.add((Arrow) e.getProjectile());
}
}

View file

@ -35,5 +35,9 @@ public class ParticleStyleBeam implements ParticleStyle {
public String getName() {
return "beam";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -30,9 +30,9 @@ import org.bukkit.Location;
import org.bukkit.util.Vector;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.library.VectorUtils;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.VectorUtils;
/**
* Credit goes to Slikey who made all this logic for drawing a cube out of particles
@ -89,5 +89,9 @@ public class ParticleStyleCube implements ParticleStyle {
public String getName() {
return "cube";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -19,5 +19,9 @@ public class ParticleStyleFeet implements ParticleStyle {
public String getName() {
return "feet";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -36,5 +36,9 @@ public class ParticleStyleHalo implements ParticleStyle {
public String getName() {
return "halo";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -6,8 +6,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.ParticleCreator;
import com.esophose.playerparticles.manager.ConfigManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
public class ParticleStyleMove extends ParticleStyleNone implements Listener {
@ -23,14 +23,18 @@ public class ParticleStyleMove extends ParticleStyleNone implements Listener {
*/
@EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
PPlayer pplayer = ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId());
PPlayer pplayer = ConfigManager.getInstance().getPPlayer(e.getPlayer().getUniqueId(), false);
if (pplayer.getParticleStyle() == DefaultStyles.MOVE) {
if (PermissionManager.hasStylePermission(e.getPlayer(), DefaultStyles.MOVE)) {
Location loc = e.getPlayer().getLocation();
loc.setY(loc.getY() + 0.05);
ParticleCreator.displayParticles(pplayer, DefaultStyles.MOVE.getParticles(pplayer, loc));
ParticleManager.displayParticles(pplayer, DefaultStyles.MOVE.getParticles(pplayer, loc));
}
}
}
public boolean canBeFixed() {
return false;
}
}

View file

@ -125,5 +125,9 @@ public class ParticleStyleNone implements ParticleStyle {
public String getName() {
return "none";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -31,5 +31,9 @@ public class ParticleStyleOrbit implements ParticleStyle {
public String getName() {
return "orbit";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -18,5 +18,9 @@ public class ParticleStylePoint implements ParticleStyle {
public String getName() {
return "point";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -40,5 +40,9 @@ public class ParticleStyleQuadhelix implements ParticleStyle {
public String getName() {
return "quadhelix";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -31,5 +31,9 @@ public class ParticleStyleSpin implements ParticleStyle {
public String getName() {
return "spin";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -31,5 +31,9 @@ public class ParticleStyleSpiral implements ParticleStyle {
public String getName() {
return "spiral";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -0,0 +1,30 @@
package com.esophose.playerparticles.styles;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.styles.api.PParticle;
public class ParticleStyleThick extends ParticleStyleNone {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
PParticle[] baseParticles = super.getParticles(pplayer, location);
int multiplyingFactor = 15; // Uses the same logic as ParticleStyleNone except multiplies the resulting particles by 15x
PParticle[] particles = new PParticle[baseParticles.length * multiplyingFactor];
for (int i = 0; i < baseParticles.length * multiplyingFactor; i++) {
particles[i] = baseParticles[i % baseParticles.length];
}
return particles;
}
public void updateTimers() {
}
public String getName() {
return "thick";
}
}

View file

@ -23,8 +23,23 @@ public interface ParticleStyle {
*/
public PParticle[] getParticles(PPlayer pplayer, Location location);
/**
* Used to update timers for animations, called once per particle tick
*/
public void updateTimers();
/**
* The name of the style
*
* @return The style's name
*/
public String getName();
/**
* Gets if the style can be used in a FixedParticleEffect
*
* @return If the style can be used in a FixedParticleEffect
*/
public boolean canBeFixed();
}

View file

@ -0,0 +1,57 @@
/**
* Copyright Esophose 2016
* While using any of the code provided by this plugin
* you must not claim it as your own. This plugin may
* be modified and installed on a server, but may not
* be distributed to any person by any means.
*/
package com.esophose.playerparticles.util;
import java.util.ArrayList;
import org.bukkit.Material;
public class ParticlesUtils {
/**
* Finds a block/item as a material from a string
* There must be some better way to do this that reliably gets the correct material
*
* @param input The material name as a string
* @return The material from the string
*/
@SuppressWarnings("deprecation")
public static Material closestMatch(String input) {
ArrayList<Material> matchList = new ArrayList<Material>();
for (Material material : Material.values())
if (material.name().replace("_", " ").toLowerCase().equals(input.toLowerCase()) || String.valueOf(material.getId()).equals(input))
return material;
else if (material.name().replace("_", " ").toLowerCase().contains(input.toLowerCase()))
matchList.add(material);
if (matchList.size() == 1) return matchList.get(0);
else return null;
}
/**
* Gets the smallest positive integer from an array
*
* @param n The array containing non-available integers
* @return The smallest positive integer not in the given array
*/
public static int getSmallestPositiveInt(int[] n) {
for (int i = 0; i < n.length; ++i) {
while (n[i] != i + 1) {
if (n[i] <= 0 || n[i] > n.length || n[i] == n[n[i] - 1]) break;
int temp = n[i];
n[i] = n[temp - 1];
n[temp - 1] = temp;
}
}
for (int i = 0; i < n.length; ++i)
if (n[i] != i + 1) return i + 1;
return n.length + 1;
}
}

View file

@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.esophose.playerparticles.library;
package com.esophose.playerparticles.util;
import org.bukkit.Location;
import org.bukkit.util.Vector;

View file

@ -4,6 +4,7 @@
# | | | |__/ __ \\___ \ ___/| | \/ | / __ \| | \/| | | \ \___| |_\ ___/ \___ \ \ / ^ /
# |____| |____(____ / ____|\___ >__| |____| (____ /__| |__| |__|\___ >____/\___ >____ > \_/\____ |
# \/\/ \/ \/ \/ \/ \/ |__|
# Please excuse the cheesy ASCII Art
# ====================================================#
@ -13,7 +14,7 @@
# Changing this value will reset your config on the next server reload/restart.
# I don't recommend changing it
version: 4.2
version: 4.3
# How many ticks to wait before spawning more particles
# Increasing this value may cause less lag (if there was any), but will decrease prettiness
@ -33,6 +34,10 @@ disabled-worlds: []
# - your_world_name_here
# - add_more_under_these
# Max fixed effects per player
# Default: 5
max-fixed-effects: 5
# ================================================================ #
# MESSAGE CONFIGURATION #
# Important Notes: #
@ -180,6 +185,51 @@ message-available-commands: '&eAvailable commands: &beffect, effects, style, sty
# Default: '&eParticles are disabled in these worlds:&b'
message-disabled-worlds: '&eParticles are disabled in these worlds:&b'
# ------------------ #
# Alt. Execution
# ------------------ #
# Executed For Player
# Default: '&aCommand executed for &b{TYPE}'
message-executed-for-player: '&aCommand executed for &b{TYPE}'
# Failed Execute Not Found
# Default: '&cFailed to execute for &b{TYPE}&c! Player not found!'
message-failed-execute-not-found: '&cFailed to execute command for &b{TYPE}&c! Player not found!'
# Failed Execute No Permission
# Default: '&cFailed to execute for &b{TYPE}&c! You do not have permission!'
message-failed-execute-no-permission: '&cFailed to execute command for &b{TYPE}&c! You do not have permission!'
# ----------------- #
# Fixed Effects
# ----------------- #
# No Permission Fixed
# Default: '&cYou do not have permission to use fixed effects!'
message-no-permission-fixed: '&cYou do not have permission to use fixed effects!'
# Invalid Fixed Command
# Default: '&cInvalid sub-command for &b/pp fixed&c!'
message-invalid-fixed-command: '&cInvalid subcommand for &b/pp fixed&c! &eCommands: '
# Fixed Command Description For Create
# Default '&e/pp fixed create <x> <y> <z> <effect> <style> [data]'
message-fixed-command-desc-create: '&e/pp fixed create <x> <y> <z> <effect> <style> [data] - Creates a new fixed effect'
# Fixed Command Description For Remove
# Default: '&e/pp fixed remove <id>'
message-fixed-command-desc-remove: '&e/pp fixed remove <id> - Removes a fixed effect by its id'
# Fixed Command Description For List
# Default: '&e/pp fixed list - Lists all ids of your fixed effects'
message-fixed-command-desc-list: '&e/pp fixed list - Lists all ids of your fixed effects'
# Fixed Command Description For Information
# Default: '&e/pp fixed info <id> - Gets info on one of your fixed effects'
message-fixed-command-desc-info: '&e/pp fixed info <id> - Gets info on one of your fixed effects'
# ------------- #
# Other #
# ------------- #
@ -200,18 +250,6 @@ message-disabled-worlds-none: '&eParticles are not disabled in any worlds!'
# Default: '&eCommand Usage: /pp <command>'
message-command-usage: '&eCommand Usage: &b/pp <command>'
# Executed For Player
# Default: '&aCommand executed for &b{TYPE}'
message-executed-for-player: '&aCommand executed for &b{TYPE}'
# Failed Execute Not Found
# Default: '&cFailed to execute for &b{TYPE}&c! Player not found!'
message-failed-execute-not-found: '&cFailed to execute for &b{TYPE}&c! Player not found!'
# Failed Execute No Permission
# Default: '&cFailed to execute for &b{TYPE}&c! You do not have permission!'
message-failed-execute-no-permission: '&cFailed to execute for &b{TYPE}&c! You do not have permission!'
# ================================================================ #
# DATABASE CONFIGURATION #
# Information: #

View file

@ -1,6 +1,6 @@
name: PlayerParticles
main: com.esophose.playerparticles.PlayerParticles
version: 4.2
version: 4.3
description: Make particles around players in fancy ways.
author: Esophose
website: http://dev.bukkit.org/bukkit-plugins/playerparticles/