Add GUI, other changes

Added GUI, updated copyright to 2018, added styles sphere and wings,
reduced number of particles that spawn with the cube style, made some
minor documentation changes
This commit is contained in:
Esophose 2018-02-25 20:55:34 -07:00
parent 9c7659a092
commit 406a4fc6a3
24 changed files with 1418 additions and 157 deletions

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -11,9 +11,11 @@ package com.esophose.playerparticles;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.gui.PlayerParticlesGui;
import com.esophose.playerparticles.library.ParticleEffect;
import com.esophose.playerparticles.library.ParticleEffect.BlockData;
import com.esophose.playerparticles.library.ParticleEffect.ItemData;
@ -48,7 +50,7 @@ public class PPlayer {
private NoteColor particleNoteColorData;
/**
* Constructs a new PPlayer
* Constructs a new PPlayer
*
* @param uuid The player UUID
* @param effect The player's effect
@ -67,7 +69,7 @@ public class PPlayer {
this.setColorData(colorData);
this.setNoteColorData(noteColorData);
}
/**
* Gets the player's UUID
*
@ -76,7 +78,7 @@ public class PPlayer {
public UUID getUniqueId() {
return this.playerUUID;
}
/**
* Gets the Player from their UUID
*
@ -160,7 +162,7 @@ public class PPlayer {
if (style == null) style = DefaultStyles.NONE;
this.particleStyle = style;
}
/**
* Sets the player's item data
*
@ -170,9 +172,9 @@ public class PPlayer {
if (itemData == null) itemData = new ItemData(Material.IRON_SPADE, (byte) 0);
this.particleItemData = itemData;
}
/**
* Sets the player's block data
* Sets the player's block data
*
* @param blockData The player's new block data
*/
@ -180,7 +182,7 @@ public class PPlayer {
if (blockData == null) blockData = new BlockData(Material.STONE, (byte) 0);
this.particleBlockData = blockData;
}
/**
* Sets the player's color data
*
@ -190,7 +192,7 @@ public class PPlayer {
if (colorData == null) colorData = new OrdinaryColor(0, 0, 0);
this.particleColorData = colorData;
}
/**
* Sets the player's note color data
*
@ -208,10 +210,10 @@ public class PPlayer {
*/
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) {
if (this.particleEffect == ParticleEffect.ITEM_CRACK) {
return this.particleItemData;
} else {
return particleBlockData;
}
}
return null;
@ -240,6 +242,33 @@ public class PPlayer {
return null;
}
/**
* Gets the current particle data as a string
*
* @return The particle data in a human-readable string
*/
public String getParticleDataString() {
if (this.particleEffect == ParticleEffect.BLOCK_CRACK || this.particleEffect == ParticleEffect.BLOCK_DUST || this.particleEffect == ParticleEffect.FALLING_DUST) {
return particleBlockData.getMaterial().toString().toLowerCase() + ":" + particleBlockData.getData();
} else if (this.particleEffect == ParticleEffect.ITEM_CRACK) {
return particleItemData.getMaterial().toString().toLowerCase() + ":" + particleItemData.getData();
} else if (this.particleEffect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.particleEffect == ParticleEffect.NOTE) {
if (this.particleNoteColorData.getValueX() * 24 == 99) {
return PlayerParticlesGui.rainbowName;
}
return "note #" + (int)(this.particleNoteColorData.getValueX() * 24);
} else {
if (this.particleColorData.getRed() == 999 && this.particleColorData.getGreen() == 999 && this.particleColorData.getBlue() == 999) {
return PlayerParticlesGui.rainbowName;
} else {
return ChatColor.RED + "" + this.particleColorData.getRed() + " " + ChatColor.GREEN + this.particleColorData.getGreen() + " " + ChatColor.AQUA + this.particleColorData.getBlue();
}
}
}
return "None";
}
/**
* Gets a default PPlayer
* Used for when a new PPlayer is being created

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -22,7 +22,7 @@ import com.esophose.playerparticles.manager.PermissionManager;
public class ParticleCommandCompleter implements TabCompleter {
private final String[] COMMANDS = { "help", "effect", "effects", "style", "styles", "worlds", "version", "fixed", "reset" };
private final String[] COMMANDS = { "help", "gui", "effect", "effects", "style", "styles", "worlds", "version", "fixed", "reset" };
private final String[] FIXED_COMMANDS = { "create", "remove", "list", "info" };
/**
@ -39,7 +39,7 @@ public class ParticleCommandCompleter implements TabCompleter {
if (cmd.getName().equalsIgnoreCase("pp")) {
if (args.length > 1) {
if (args[0].equalsIgnoreCase("effect")) {
List<String> commands = PermissionManager.getParticlesUserHasPermissionFor((Player) sender);
List<String> commands = PermissionManager.getEffectsUserHasPermissionFor((Player) sender);
StringUtil.copyPartialMatches(args[1], commands, completions);
return completions;
} else if (args[0].equalsIgnoreCase("style")) {

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -23,6 +23,8 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.gui.PlayerParticlesGui;
import com.esophose.playerparticles.gui.PlayerParticlesGui.GuiState;
import com.esophose.playerparticles.library.ParticleEffect;
import com.esophose.playerparticles.library.ParticleEffect.BlockData;
import com.esophose.playerparticles.library.ParticleEffect.ItemData;
@ -56,7 +58,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
Player p = (Player) sender;
if (args.length == 0) {
MessageManager.sendMessage(p, MessageType.INVALID_ARGUMENTS);
onGUI(p, true);
return true;
} else {
String[] cmdArgs = new String[0];
@ -93,6 +95,9 @@ public class ParticleCommandExecutor implements CommandExecutor {
case "reset":
onReset(p, cmdArgs);
break;
case "gui":
onGUI(p, false);
break;
default:
MessageManager.sendMessage(p, MessageType.INVALID_ARGUMENTS);
}
@ -159,7 +164,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(), false).getParticleEffect();
ParticleEffect effect = ConfigManager.getInstance().getPPlayer(p.getUniqueId(), true).getParticleEffect();
if ((!effect.hasProperty(ParticleProperty.REQUIRES_DATA) && !effect.hasProperty(ParticleProperty.COLORABLE)) || args.length == 0) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
@ -357,8 +362,8 @@ public class ParticleCommandExecutor implements CommandExecutor {
return;
}
String argument = args[0].replace("_", "");
if (ParticleManager.particleFromString(argument) != null) {
ParticleEffect effect = ParticleManager.particleFromString(argument);
if (ParticleManager.effectFromString(argument) != null) {
ParticleEffect effect = ParticleManager.effectFromString(argument);
if (!PermissionManager.hasEffectPermission(p, effect)) {
MessageManager.sendMessage(p, MessageType.NO_PERMISSION, effect.getName().toLowerCase());
return;
@ -526,7 +531,7 @@ public class ParticleCommandExecutor implements CommandExecutor {
return;
}
ParticleEffect effect = ParticleManager.particleFromString(args[3]);
ParticleEffect effect = ParticleManager.effectFromString(args[3]);
if (effect == null) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_INVALID_EFFECT, args[3]);
return;
@ -774,5 +779,31 @@ public class ParticleCommandExecutor implements CommandExecutor {
if (p.hasPermission("playerparticles.fixed.clear")) MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_CLEAR);
}
}
private void onGUI(Player p, boolean byDefault) {
if (PlayerParticlesGui.isGuiDisabled()) {
if (byDefault) {
onHelp(p);
} else {
MessageManager.sendMessage(p, MessageType.GUI_DISABLED);
}
return;
}
if (PermissionManager.getEffectsUserHasPermissionFor(p).size() == 1) {
if (byDefault) {
onHelp(p);
} else {
MessageManager.sendMessage(p, MessageType.NO_PARTICLES);
}
return;
}
if (byDefault) {
MessageManager.sendMessage(p, MessageType.GUI_BY_DEFAULT);
}
PlayerParticlesGui.changeState(ConfigManager.getInstance().getPPlayer(p.getUniqueId(), true), GuiState.DEFAULT);
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -7,17 +7,37 @@
*/
/*
TODO: v4.4
TODO: v5
+ Add new style 'tornado'
+ Add new style 'fairy'
+ Add new style 'atom'
+ Add new style 'wings'
+ GUI for styles and effects - Requires no additional permissions
/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
+ Add new style 'rings'
+ Add new style 'jump'
+ Add new style 'blockbreak'
+ Add new style 'blockplace'
+ Add new style 'hurt'
+ Add new style 'swords'
+ Switch over to Spigot Particle API
+ Switch database management system, make async
+ Command to force set an effect/style for a player
*/
/*
Changelog v5:
+ Added GUI. Opens with /pp or /pp gui. Icons and messages are completely customizable from the config.
+ Added a way to disable the GUI, because I know somebody will ask
+ Added new style 'wings'
+ Added new style 'sphere'
- Minecraft 1.7 and 1.8 are no longer supported. There is no reason to still be on a version that old.
* Fixed a bug where typing /pp data when you haven't been added to the playerData.yml/database yet threw an error
* Switched over to the Spigot Particle API
* Plugin is now built against Java 1.8.0_161 and Spigot 1.9.4
* Servers running Java 7 are no longer supported. Please upgrade to Java 8 if you haven't yet.
* Rewrote database connection system, should fix any memory leaks from before
* Reduced particle render distance from 512 to 150, you won't notice a difference
* Performance improvements with database loading
*/
package com.esophose.playerparticles;
import java.io.File;
@ -29,6 +49,7 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.gui.PlayerParticlesGui;
import com.esophose.playerparticles.library.MySQL;
import com.esophose.playerparticles.manager.MessageManager;
import com.esophose.playerparticles.manager.ParticleManager;
@ -68,12 +89,14 @@ public class PlayerParticles extends JavaPlugin {
public void onEnable() {
DefaultStyles.registerStyles();
MessageManager.setup();
PlayerParticlesGui.setup();
saveDefaultConfig();
getCommand("pp").setTabCompleter(new ParticleCommandCompleter());
getCommand("pp").setExecutor(new ParticleCommandExecutor());
Bukkit.getPluginManager().registerEvents(new ParticleManager(), this);
Bukkit.getPluginManager().registerEvents(new PluginUpdateListener(), this);
if (getConfig().getDouble("version") < Double.parseDouble(getDescription().getVersion().substring(0, 3))) {
Bukkit.getPluginManager().registerEvents(new PlayerParticlesGui(), this);
if (getConfig().getDouble("version") < Double.parseDouble(getDescription().getVersion())) {
File configFile = new File(getDataFolder(), "config.yml");
configFile.delete();
saveDefaultConfig();
@ -86,12 +109,27 @@ public class PlayerParticles extends JavaPlugin {
if (shouldCheckUpdates()) {
try { // For some reason this can throw an exception sometimes. I suppose it happens when you run the server without an internet connection?
Updater updater = new Updater(this, 82823, this.getFile(), Updater.UpdateType.NO_DOWNLOAD, false);
if (Double.parseDouble(updater.getLatestName().replaceAll("PlayerParticles v", "").replaceAll("\\.", "")) > Double.parseDouble(getPlugin().getDescription().getVersion().replaceAll("\\.", ""))) {
if (Double.parseDouble(updater.getLatestName().replaceAll("PlayerParticles v", "")) > Double.parseDouble(getPlugin().getDescription().getVersion())) {
updateVersion = updater.getLatestName().replaceAll("PlayerParticles v", "");
getLogger().info("[PlayerParticles] An update (v" + updateVersion + ") is available! You are running v" + getPlugin().getDescription().getVersion());
getLogger().info("An update (v" + updateVersion + ") is available! You are running v" + getPlugin().getDescription().getVersion());
}
} catch (Exception e) {
getLogger().warning("[PlayerParticles] An error occurred checking for an update. There is either no established internet connection or the Curse API is down.");
getLogger().warning("An error occurred checking for an update. There is either no established internet connection or the Curse API is down.");
}
}
}
/**
* Clean up MySQL connection if it's open
*/
public void onDisable() {
if (useMySQL) {
try {
if (mySQL.checkConnection()) {
mySQL.closeConnection();
}
} catch (SQLException ex) {
getLogger().warning("An error occurred while cleaning up the mySQL database connection.");
}
}
}
@ -129,7 +167,7 @@ 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);
useMySQL = true; // If something goes wrong this will be set to false
// @formatter:off
@ -156,7 +194,7 @@ public class PlayerParticles extends JavaPlugin {
);
}
} 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("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;
@ -176,9 +214,9 @@ public class PlayerParticles extends JavaPlugin {
public void run() {
ParticleManager.refreshPPlayers(); // Add any online players who have particles
ParticleManager.addAllFixedEffects(); // Add all fixed effects
double ticks = getConfig().getInt("ticks-per-particle");
new ParticleManager().runTaskTimer(playerParticles, 20, (long) ticks);
long ticks = getConfig().getLong("ticks-per-particle");
new ParticleManager().runTaskTimer(playerParticles, 20, ticks);
}
}.runTaskLater(playerParticles, 20);
}

View file

@ -0,0 +1,61 @@
/**
* Copyright Esophose 2018
* 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.gui;
import org.bukkit.inventory.Inventory;
import com.esophose.playerparticles.gui.PlayerParticlesGui.GuiState;
public class GuiInventory {
private Inventory inventory;
private GuiState guiState;
public GuiInventory(Inventory inventory, GuiState guiState) {
this.inventory = inventory;
this.guiState = guiState;
}
/**
* Replaces the current inventory with a new inventory
*
* @param inventory The inventory this GuiInventory now manages
*/
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
/**
* Updates the current GuiState
*
* @param guiState The new GuiState
*/
public void setGuiState(GuiState guiState) {
this.guiState = guiState;
}
/**
* Gets the Inventory
*
* @return The Inventory
*/
public Inventory getInventory() {
return this.inventory;
}
/**
* Gets the GuiState
*
* @return The GuiState
*/
public GuiState getGuiState() {
return this.guiState;
}
}

View file

@ -0,0 +1,812 @@
/**
* Copyright Esophose 2018
* 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.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.SkullType;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.material.Dye;
import org.bukkit.material.Wool;
import org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.PlayerParticles;
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.ParticleProperty;
import com.esophose.playerparticles.manager.ConfigManager;
import com.esophose.playerparticles.manager.MessageManager.MessageType;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticleUtils;
/**
* This class provides a collection of static methods for modifying your
* particle/style/data through the use of a GUI
*/
public class PlayerParticlesGui extends BukkitRunnable implements Listener {
/**
* The possible states that the GUI can be in
* Used to figure out what the InventoryClickEvent should do
*/
public enum GuiState { // @formatter:off
DEFAULT,
EFFECT,
STYLE,
DATA
} // @formatter:on
public static final String rainbowName = ChatColor.RED + "r" + ChatColor.GOLD + "a" + ChatColor.YELLOW + "i" + ChatColor.GREEN + "n" + ChatColor.AQUA + "b" + ChatColor.BLUE + "o" + ChatColor.LIGHT_PURPLE + "w";
private static final int INVENTORY_SIZE = 54;
private static HashMap<UUID, GuiInventory> playerGuiInventories;
private static boolean guiEnabled;
/**
* Cached icons to prevent calling config over and over
*/
private static Material[] defaultMenuIcons = new Material[3];
private static HashMap<String, Material> effectIcons;
private static HashMap<String, Material> styleIcons;
/**
* Maps to convert from clicked materials to particle colors
*/
private static LinkedHashMap<DyeColor, OrdinaryColor> colorMapping;
private static String[] colorMappingNames;
/**
* DyeColor array in the order of the rainbow
* Color index for the wool color to display next
*/
private static DyeColor[] rainbowColors;
private static int rainbowColorsIndex = 0;
/**
* 28 of each block/item Materials for block/item data
*/
private static Material[] blockMaterials;
private static Material[] itemMaterials;
static { // @formatter:off
colorMapping = new LinkedHashMap<DyeColor, OrdinaryColor>();
colorMapping.put(DyeColor.RED, new OrdinaryColor(255, 0, 0));
colorMapping.put(DyeColor.ORANGE, new OrdinaryColor(255, 140, 0));
colorMapping.put(DyeColor.YELLOW, new OrdinaryColor(255, 255, 0));
colorMapping.put(DyeColor.LIME, new OrdinaryColor(50, 205, 50));
colorMapping.put(DyeColor.GREEN, new OrdinaryColor(0, 128, 0));
colorMapping.put(DyeColor.BLUE, new OrdinaryColor(0, 0, 255));
colorMapping.put(DyeColor.CYAN, new OrdinaryColor(0, 139, 139));
colorMapping.put(DyeColor.LIGHT_BLUE, new OrdinaryColor(173, 216, 230));
colorMapping.put(DyeColor.PURPLE, new OrdinaryColor(138, 43, 226));
colorMapping.put(DyeColor.MAGENTA, new OrdinaryColor(202, 31, 123));
colorMapping.put(DyeColor.PINK, new OrdinaryColor(255, 182, 193));
colorMapping.put(DyeColor.BROWN, new OrdinaryColor(139, 69, 19));
colorMapping.put(DyeColor.BLACK, new OrdinaryColor(0, 0, 0));
colorMapping.put(DyeColor.GRAY, new OrdinaryColor(128, 128, 128));
colorMapping.put(DyeColor.SILVER, new OrdinaryColor(192, 192, 192));
colorMapping.put(DyeColor.WHITE, new OrdinaryColor(255, 255, 255));
colorMappingNames = new String[] {
ChatColor.RED + "red",
ChatColor.GOLD + "orange",
ChatColor.YELLOW + "yellow",
ChatColor.GREEN + "lime green",
ChatColor.DARK_GREEN + "green",
ChatColor.DARK_BLUE + "blue",
ChatColor.DARK_AQUA + "cyan",
ChatColor.AQUA + "light blue",
ChatColor.DARK_PURPLE + "purple",
ChatColor.LIGHT_PURPLE + "magenta",
ChatColor.LIGHT_PURPLE + "pink",
ChatColor.GOLD + "brown",
ChatColor.DARK_GRAY + "black",
ChatColor.DARK_GRAY + "gray",
ChatColor.GRAY + "light gray",
ChatColor.WHITE + "white"
};
rainbowColors = new DyeColor[] { DyeColor.RED, DyeColor.ORANGE, DyeColor.YELLOW, DyeColor.LIME, DyeColor.LIGHT_BLUE, DyeColor.BLUE, DyeColor.PURPLE };
blockMaterials = new Material[] {
Material.STONE,
Material.GRASS,
Material.TNT,
Material.COBBLESTONE,
Material.WOOD,
Material.BEDROCK,
Material.SAND,
Material.LOG,
Material.SPONGE,
Material.GLASS,
Material.WOOL,
Material.IRON_BLOCK,
Material.GOLD_BLOCK,
Material.DIAMOND_BLOCK,
Material.EMERALD_BLOCK,
Material.COAL_BLOCK,
Material.REDSTONE_BLOCK,
Material.BOOKSHELF,
Material.ICE,
Material.CLAY,
Material.PUMPKIN,
Material.MELON_BLOCK,
Material.NETHERRACK,
Material.SOUL_SAND,
Material.GLOWSTONE,
Material.NETHER_BRICK,
Material.ENDER_STONE,
Material.PRISMARINE
};
itemMaterials = new Material[] {
Material.COAL,
Material.IRON_INGOT,
Material.GOLD_INGOT,
Material.REDSTONE,
Material.EMERALD,
Material.QUARTZ,
Material.CLAY_BRICK,
Material.GLOWSTONE_DUST,
Material.SUGAR_CANE,
Material.FLINT,
Material.POTATO_ITEM,
Material.CARROT_ITEM,
Material.SNOW_BALL,
Material.BONE,
Material.ENDER_PEARL,
Material.BLAZE_POWDER,
Material.NETHER_STALK,
Material.FIREBALL,
Material.CHORUS_FRUIT,
Material.PRISMARINE_CRYSTALS,
Material.SULPHUR,
Material.APPLE,
Material.MELON,
Material.COOKIE,
Material.IRON_SPADE,
Material.COMPASS,
Material.WATCH,
Material.NAME_TAG
};
} // @formatter:on
/**
* Initializes all the static values for this class
*/
public static void setup() {
FileConfiguration config = PlayerParticles.getPlugin().getConfig();
guiEnabled = config.getBoolean("gui-enabled");
if (!guiEnabled) return;
playerGuiInventories = new HashMap<UUID, GuiInventory>();
effectIcons = new HashMap<String, Material>();
styleIcons = new HashMap<String, Material>();
defaultMenuIcons[0] = ParticleUtils.closestMatch(config.getString("gui-icon.main-menu.EFFECT"));
defaultMenuIcons[1] = ParticleUtils.closestMatch(config.getString("gui-icon.main-menu.STYLE"));
defaultMenuIcons[2] = ParticleUtils.closestMatch(config.getString("gui-icon.main-menu.DATA"));
for (int i = 0; i < defaultMenuIcons.length; i++)
if (defaultMenuIcons[i] == null) defaultMenuIcons[i] = Material.BARRIER;
for (ParticleEffect effect : ParticleEffect.values()) {
String effectName = effect.name();
Material iconMaterial = ParticleUtils.closestMatch(config.getString("gui-icon.effect." + effectName));
if (iconMaterial == null) iconMaterial = Material.BARRIER; // Missing icon or invalid? Replace it with a barrier instead to fail safety.
effectIcons.put(effectName, iconMaterial);
}
for (ParticleStyle style : ParticleStyleManager.getStyles()) {
String styleName = style.getName().toUpperCase();
Material iconMaterial = ParticleUtils.closestMatch(config.getString("gui-icon.style." + styleName));
if (iconMaterial == null) iconMaterial = Material.BARRIER; // Missing icon or invalid? Replace it with a barrier instead to fail safety.
styleIcons.put(styleName, iconMaterial);
}
new PlayerParticlesGui().runTaskTimer(PlayerParticles.getPlugin(), 0, 10);
}
/**
* Updates all color/note data inventories to display the rainbow icon
* Removes any players who are no longer online from playerGuiInventories
*/
public void run() {
List<UUID> toRemoveList = new ArrayList<UUID>();
for (Map.Entry<UUID, GuiInventory> entry : playerGuiInventories.entrySet()) {
PPlayer pplayer = ConfigManager.getInstance().getPPlayer(entry.getKey(), false);
Player player = Bukkit.getPlayer(pplayer.getUniqueId());
if (player == null) {
toRemoveList.add(pplayer.getUniqueId());
continue;
}
GuiInventory guiInventory = entry.getValue();
Inventory inventory = guiInventory.getInventory();
if (player.getOpenInventory().getTopInventory().equals(inventory) && guiInventory.getGuiState() == GuiState.DATA && pplayer.getParticleEffect().hasProperty(ParticleProperty.COLORABLE)) {
ItemStack rainbowIcon;
if (pplayer.getParticleEffect() != ParticleEffect.NOTE) {
rainbowIcon = getItemForRainbowColorData(pplayer.getColorData(), rainbowColors[rainbowColorsIndex]);
} else {
rainbowIcon = getItemForRainbowNoteData(pplayer.getNoteColorData(), rainbowColors[rainbowColorsIndex]);
}
inventory.setItem(40, rainbowIcon);
}
}
for (UUID uuid : toRemoveList)
playerGuiInventories.remove(uuid);
rainbowColorsIndex++;
rainbowColorsIndex %= rainbowColors.length;
}
/**
* Gets if the GUI is disabled by the server owner or not
*
* @return True if the GUI is disabled
*/
public static boolean isGuiDisabled() {
return !guiEnabled;
}
/**
* Changes the GUI to the indicated state
* If the GUI isn't open yet, it gets opened
*
* @param p The pplayer
* @param state The new state
*/
public static void changeState(PPlayer p, GuiState state) {
Player player = p.getPlayer();
if (PermissionManager.getEffectsUserHasPermissionFor(player).size() == 1 || PermissionManager.getStylesUserHasPermissionFor(player).size() == 1 || (state == GuiState.DATA && p.getParticleSpawnData() == null && p.getParticleSpawnColor() == null)) return;
// Update the state and create an inventory for the player if one isn't already open for them
// If they have the wrong inventory open for some reason, create a new one and open it for them
if (playerGuiInventories.containsKey(p.getUniqueId())) {
GuiInventory guiInventory = playerGuiInventories.get(p.getUniqueId());
guiInventory.setGuiState(state);
if (player.getOpenInventory().getTopInventory() != guiInventory.getInventory()) {
Inventory ppInventory = Bukkit.createInventory(null, INVENTORY_SIZE, "PlayerParticles");
player.openInventory(ppInventory);
guiInventory.setInventory(ppInventory);
}
} else {
Inventory ppInventory = Bukkit.createInventory(null, INVENTORY_SIZE, "PlayerParticles");
player.openInventory(ppInventory);
playerGuiInventories.put(p.getUniqueId(), new GuiInventory(ppInventory, state));
}
switch (state) {
case DEFAULT:
populateDefault(p);
break;
case EFFECT:
populateEffect(p);
break;
case STYLE:
populateStyle(p);
break;
case DATA:
populateData(p);
break;
}
}
/**
* Opens the menu to go to other menus: effect, style, data
*
* @param p The PPlayer
*/
private static void populateDefault(PPlayer p) {
Player player = p.getPlayer();
Inventory inventory = player.getOpenInventory().getTopInventory();
inventory.clear(); // Make sure the inventory is always empty before we start adding items
ItemStack currentIcon = new ItemStack(Material.SKULL_ITEM, 1, (short) SkullType.PLAYER.ordinal());
SkullMeta currentIconMeta = (SkullMeta) currentIcon.getItemMeta();
currentIconMeta.setDisplayName(ChatColor.GREEN + player.getName());
String[] currentIconLore = new String[3];
currentIconLore[0] = ChatColor.YELLOW + "Effect: " + ChatColor.AQUA + p.getParticleEffect().getName();
currentIconLore[1] = ChatColor.YELLOW + "Style: " + ChatColor.AQUA + p.getParticleStyle().getName();
currentIconLore[2] = ChatColor.YELLOW + "Active Data: " + ChatColor.AQUA + p.getParticleDataString();
currentIconMeta.setLore(Arrays.asList(currentIconLore));
currentIconMeta.setOwner(player.getName());
currentIcon.setItemMeta(currentIconMeta);
ItemStack effectIcon = new ItemStack(defaultMenuIcons[0], 1);
ItemMeta effectIconMeta = effectIcon.getItemMeta();
effectIconMeta.setDisplayName(ChatColor.GREEN + "Effect");
effectIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SET_YOUR.getMessageReplaced("effect")));
if (PermissionManager.getEffectsUserHasPermissionFor(player).size() == 1) { // Always has access to NONE
effectIconMeta.setLore(Arrays.asList(MessageType.GUI_NO_ACCESS_TO.getMessageReplaced("effects")));
}
effectIcon.setItemMeta(effectIconMeta);
ItemStack styleIcon = new ItemStack(defaultMenuIcons[1], 1);
ItemMeta styleIconMeta = styleIcon.getItemMeta();
styleIconMeta.setDisplayName(ChatColor.GREEN + "Style");
styleIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SET_YOUR.getMessageReplaced("style")));
if (PermissionManager.getStylesUserHasPermissionFor(player).size() == 1) { // Always has access to NONE
styleIconMeta.setLore(Arrays.asList(MessageType.GUI_NO_ACCESS_TO.getMessageReplaced("styles")));
}
styleIcon.setItemMeta(styleIconMeta);
ItemStack dataIcon = new ItemStack(defaultMenuIcons[2], 1);
ItemMeta dataIconMeta = dataIcon.getItemMeta();
dataIconMeta.setDisplayName(ChatColor.GREEN + "Data");
ParticleEffect pe = p.getParticleEffect();
String dataType = "data";
if (pe.hasProperty(ParticleProperty.COLORABLE)) if (pe == ParticleEffect.NOTE) dataType = "note " + dataType;
else dataType = "color " + dataType;
else if (pe.hasProperty(ParticleProperty.REQUIRES_DATA)) if (pe == ParticleEffect.ITEM_CRACK) dataType = "item " + dataType;
else dataType = "block " + dataType;
dataIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SET_YOUR.getMessageReplaced(dataType)));
if (p.getParticleSpawnData() == null && p.getParticleSpawnColor() == null) {
dataIconMeta.setLore(Arrays.asList(MessageType.GUI_NO_DATA.getMessage()));
}
dataIcon.setItemMeta(dataIconMeta);
inventory.setItem(13, currentIcon);
inventory.setItem(38, effectIcon);
inventory.setItem(40, styleIcon);
inventory.setItem(42, dataIcon);
}
/**
* Opens the menu that allows you to select an effect you have permission for
*
* @param p The PPlayer
*/
private static void populateEffect(PPlayer p) {
Player player = p.getPlayer();
Inventory inventory = player.getOpenInventory().getTopInventory();
inventory.clear(); // Make sure the inventory is always empty before we start adding items
List<String> effectsUserHasPermissionFor = PermissionManager.getEffectsUserHasPermissionFor(player);
for (int i = 0; i < effectsUserHasPermissionFor.size(); i++) {
String s = effectsUserHasPermissionFor.get(i);
ParticleEffect effect = ParticleManager.effectFromString(s);
inventory.setItem(i, getItemForEffect(effect, effect == p.getParticleEffect()));
}
inventory.setItem(INVENTORY_SIZE - 1, getItemForBack());
}
/**
* Opens the menu that allows you to select a style you have permission for
*
* @param p The PPlayer
*/
private static void populateStyle(PPlayer p) {
Player player = p.getPlayer();
Inventory inventory = player.getOpenInventory().getTopInventory();
inventory.clear(); // Make sure the inventory is always empty before we start adding items
List<String> stylesUserHasPermissionFor = PermissionManager.getStylesUserHasPermissionFor(player);
for (int i = 0; i < stylesUserHasPermissionFor.size(); i++) {
String s = stylesUserHasPermissionFor.get(i);
ParticleStyle style = ParticleStyleManager.styleFromString(s);
inventory.setItem(i, getItemForStyle(style, style == p.getParticleStyle()));
}
inventory.setItem(INVENTORY_SIZE - 1, getItemForBack());
}
/**
* Opens the menu that allows you to select some preset data
*
* @param p The PPlayer
*/
private static void populateData(PPlayer p) {
Player player = p.getPlayer();
Inventory inventory = player.getOpenInventory().getTopInventory();
inventory.clear(); // Make sure the inventory is always empty before we start adding items
// There are a lot of for loops here, somebody submit a pull request if you have a better way of doing this
ParticleEffect pe = p.getParticleEffect();
if (pe.hasProperty(ParticleProperty.COLORABLE)) {
if (pe == ParticleEffect.NOTE) { // Note data
NoteColor currentNote = p.getNoteColorData();
int noteIndex = 0;
for (int i = 1; i <= 7; i++) { // Top row
inventory.setItem(i, getItemForNoteData(currentNote, noteIndex));
noteIndex++;
}
for (int i = 10; i <= 16; i++) { // Middle 1 row
inventory.setItem(i, getItemForNoteData(currentNote, noteIndex));
noteIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle 2 row
inventory.setItem(i, getItemForNoteData(currentNote, noteIndex));
noteIndex++;
}
for (int i = 28; i <= 30; i++) { // Bottom row
inventory.setItem(i, getItemForNoteData(currentNote, noteIndex));
noteIndex++;
}
inventory.setItem(40, getItemForRainbowNoteData(p.getNoteColorData(), rainbowColors[rainbowColorsIndex]));
} else { // Color data
OrdinaryColor currentColor = p.getColorData();
int colorIndex = 0;
for (int i = 10; i <= 16; i++) { // Top row
inventory.setItem(i, getItemForColorData(currentColor, colorIndex));
colorIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle row
inventory.setItem(i, getItemForColorData(currentColor, colorIndex));
colorIndex++;
}
for (int i = 28; i <= 29; i++) { // Bottom row
inventory.setItem(i, getItemForColorData(currentColor, colorIndex));
colorIndex++;
}
inventory.setItem(40, getItemForRainbowColorData(p.getColorData(), rainbowColors[rainbowColorsIndex]));
}
} else if (pe.hasProperty(ParticleProperty.REQUIRES_DATA)) {
if (pe == ParticleEffect.ITEM_CRACK) { // Item data
Material currentItemMaterial = p.getItemData().getMaterial();
int itemMaterialIndex = 0;
for (int i = 10; i <= 16; i++) { // Top row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", itemMaterials[itemMaterialIndex]));
itemMaterialIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle 1 row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", itemMaterials[itemMaterialIndex]));
itemMaterialIndex++;
}
for (int i = 28; i <= 34; i++) { // Middle 2 row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", itemMaterials[itemMaterialIndex]));
itemMaterialIndex++;
}
for (int i = 37; i <= 43; i++) { // Bottom row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", itemMaterials[itemMaterialIndex]));
itemMaterialIndex++;
}
} else { // Block data
Material currentBlockMaterial = p.getBlockData().getMaterial();
int blockMaterialIndex = 0;
for (int i = 10; i <= 16; i++) { // Top row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", blockMaterials[blockMaterialIndex]));
blockMaterialIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle 1 row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", blockMaterials[blockMaterialIndex]));
blockMaterialIndex++;
}
for (int i = 28; i <= 34; i++) { // Middle 2 row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", blockMaterials[blockMaterialIndex]));
blockMaterialIndex++;
}
for (int i = 37; i <= 43; i++) { // Bottom row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", blockMaterials[blockMaterialIndex]));
blockMaterialIndex++;
}
}
}
inventory.setItem(INVENTORY_SIZE - 1, getItemForBack());
}
/**
* Called whenever something is clicked in an inventory
* Will return immediately if not the particlesInventory
*
* @param e The InventoryClickEvent fired from this event
*/
@EventHandler
public void onInventoryInteract(InventoryClickEvent e) {
if (!(e.getWhoClicked() instanceof Player)) return; // Not sure if I actually have to check this
Player player = (Player) e.getWhoClicked();
GuiInventory guiInventory = playerGuiInventories.get(player.getUniqueId());
if (guiInventory == null || !guiInventory.getInventory().equals(e.getView().getTopInventory())) return; // Make sure it is the right inventory
PPlayer pplayer = ConfigManager.getInstance().getPPlayer(player.getUniqueId(), false);
e.setCancelled(true);
ItemStack clicked = e.getCurrentItem();
if (clicked == null || clicked.getType() == Material.AIR) return; // Clicked on an empty slot, do nothing
// Check back button. This is common for most menus
if (clicked.getItemMeta().getDisplayName().equals(MessageType.GUI_BACK_BUTTON.getMessage())) {
changeState(pplayer, GuiState.DEFAULT);
return;
}
String name = ChatColor.stripColor(clicked.getItemMeta().getDisplayName());
switch (guiInventory.getGuiState()) {
case DEFAULT:
if (name.equals("Effect")) {
changeState(pplayer, GuiState.EFFECT);
} else if (name.equals("Style")) {
changeState(pplayer, GuiState.STYLE);
} else if (name.equals("Data")) {
changeState(pplayer, GuiState.DATA);
}
break;
case EFFECT:
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), ParticleManager.effectFromString(name));
changeState(pplayer, GuiState.DEFAULT);
break;
case STYLE:
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), ParticleStyleManager.styleFromString(name));
changeState(pplayer, GuiState.DEFAULT);
break;
case DATA:
ParticleEffect pe = pplayer.getParticleEffect();
if (pe.hasProperty(ParticleProperty.COLORABLE)) {
if (pe == ParticleEffect.NOTE) {
if (clicked.getItemMeta().getDisplayName().equals(rainbowName)) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), new NoteColor(99));
} else {
int note = Integer.parseInt(ChatColor.stripColor(clicked.getItemMeta().getDisplayName()).substring(6));
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), new NoteColor(note));
}
} else {
if (clicked.getItemMeta().getDisplayName().equals(rainbowName)) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), new OrdinaryColor(999, 999, 999));
} else {
for (int i = 0; i < colorMappingNames.length; i++) {
if (clicked.getItemMeta().getDisplayName().equals(colorMappingNames[i])) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), getColorMappingEntry(i).getValue());
}
}
}
}
} else if (pe.hasProperty(ParticleProperty.REQUIRES_DATA)) {
Material clickedMaterial = clicked.getType(); // All preset materials have a data value of 0
if (pe == ParticleEffect.ITEM_CRACK) {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), new ItemData(clickedMaterial, (byte)0));
} else {
ConfigManager.getInstance().savePPlayer(pplayer.getUniqueId(), new BlockData(clickedMaterial, (byte)0));
}
}
changeState(pplayer, GuiState.DEFAULT);
break;
}
}
/**
* Gets a DyeColor, OrdinaryColor pair from the colorMapping LinkedHashSet
*
* @param colorIndex The index to get the pair from
* @return A DyeColor, OrdinaryColor pair
*/
@SuppressWarnings("unchecked")
private static Map.Entry<DyeColor, OrdinaryColor> getColorMappingEntry(int colorIndex) {
Set<Map.Entry<DyeColor, OrdinaryColor>> mapSet = colorMapping.entrySet();
return (Map.Entry<DyeColor, OrdinaryColor>) mapSet.toArray()[colorIndex];
}
/**
* Gets the icon for a given particle effect from the config
*
* @param effect The effect
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForEffect(ParticleEffect effect, boolean isActive) {
ItemStack icon = new ItemStack(effectIcons.get(effect.name()), 1);
ItemMeta iconMeta = icon.getItemMeta();
iconMeta.setDisplayName(MessageType.GUI_ICON_NAME_COLOR.getMessage() + effect.getName());
if (!isActive) {
iconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("effect") + effect.getName()));
} else {
iconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("effect") + effect.getName(), MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("effect")));
iconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
iconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
icon.setItemMeta(iconMeta);
return icon;
}
/**
* Gets the icon for a given particle style from the config
*
* @param style The style
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForStyle(ParticleStyle style, boolean isActive) {
ItemStack icon = new ItemStack(styleIcons.get(style.getName().toUpperCase()), 1);
ItemMeta iconMeta = icon.getItemMeta();
iconMeta.setDisplayName(MessageType.GUI_ICON_NAME_COLOR.getMessage() + style.getName());
if (!isActive) {
iconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("style") + style.getName()));
} else {
iconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("style") + style.getName(), MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("style")));
iconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
iconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
icon.setItemMeta(iconMeta);
return icon;
}
/**
* Gets the icon for a given material to be used for data
*
* @param currentMaterial What material the player is currently using
* @param dataType What type of data this is (block/item)
* @param material The material to use for the icon
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForMaterialData(Material currentMaterial, String dataType, Material material) {
ItemStack materialIcon = new ItemStack(material, 1);
ItemMeta materialIconMeta = materialIcon.getItemMeta();
materialIconMeta.setDisplayName(MessageType.GUI_ICON_NAME_COLOR.getMessage() + material.name().toLowerCase());
if (currentMaterial != material) {
materialIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced(dataType + " data") + material.name().toLowerCase()));
} else {
materialIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced(dataType + " data") + material.name().toLowerCase(), MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced(dataType + " data")));
materialIconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
materialIconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
materialIcon.setItemMeta(materialIconMeta);
return materialIcon;
}
/**
* Gets the icon for a color to be used for data
*
* @param currentColor What color the player is currently using
* @param colorIndex What color to use
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForColorData(OrdinaryColor currentColor, int colorIndex) {
Map.Entry<DyeColor, OrdinaryColor> colorMappingEntry = getColorMappingEntry(colorIndex);
DyeColor dyeColor = colorMappingEntry.getKey();
OrdinaryColor displayColor = colorMappingEntry.getValue();
String formattedDisplayColor = ChatColor.RED.toString() + displayColor.getRed() + " " + ChatColor.GREEN + displayColor.getGreen() + " " + ChatColor.AQUA + displayColor.getBlue();
ItemStack colorIcon = new Dye(dyeColor).toItemStack(1);
ItemMeta colorIconMeta = colorIcon.getItemMeta();
colorIconMeta.setDisplayName(colorMappingNames[colorIndex]);
if (!currentColor.equals(displayColor)) {
colorIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("color data") + formattedDisplayColor));
} else {
colorIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("color data") + formattedDisplayColor, MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("color data")));
colorIconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
colorIconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
colorIcon.setItemMeta(colorIconMeta);
return colorIcon;
}
/**
* Gets the icon for a note to be used for data
*
* @param currentNote What note the player is currently using
* @param noteIndex What note to use
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForNoteData(NoteColor currentNote, int noteIndex) {
ItemStack noteIcon = new ItemStack(Material.NOTE_BLOCK, noteIndex + 1);
ItemMeta noteIconMeta = noteIcon.getItemMeta();
noteIconMeta.setDisplayName(MessageType.GUI_ICON_NAME_COLOR.getMessage() + "note #" + noteIndex);
if (currentNote.getValueX() * 24 != noteIndex) {
noteIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("note data") + "note #" + noteIndex));
} else {
noteIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("note data") + "note #" + noteIndex, MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("note data")));
noteIconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
noteIconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
noteIcon.setItemMeta(noteIconMeta);
return noteIcon;
}
/**
* Gets the icon for rainbow color/note data
*
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForRainbowColorData(OrdinaryColor currentColor, DyeColor dyeColor) {
ItemStack rainbowIcon = new Wool(dyeColor).toItemStack(1);
ItemMeta rainbowIconMeta = rainbowIcon.getItemMeta();
rainbowIconMeta.setDisplayName(rainbowName);
if (currentColor.getRed() == 999 && currentColor.getGreen() == 999 && currentColor.getBlue() == 999) {
rainbowIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("color data") + rainbowName, MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("color data")));
rainbowIconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
rainbowIconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
} else {
rainbowIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("color data") + rainbowName));
}
rainbowIcon.setItemMeta(rainbowIconMeta);
return rainbowIcon;
}
/**
* Gets the icon for rainbow color/note data
*
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForRainbowNoteData(NoteColor currentColor, DyeColor dyeColor) {
ItemStack rainbowIcon = new Wool(dyeColor).toItemStack(1);
ItemMeta rainbowIconMeta = rainbowIcon.getItemMeta();
rainbowIconMeta.setDisplayName(rainbowName);
if (currentColor.getValueX() * 24 == 99) {
rainbowIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("note data") + rainbowName, MessageType.GUI_ICON_CURRENT_ACTIVE.getMessageReplaced("note data")));
rainbowIconMeta.addEnchant(Enchantment.ARROW_INFINITE, -1, true);
rainbowIconMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
} else {
rainbowIconMeta.setLore(Arrays.asList(MessageType.GUI_ICON_SETS_TO.getMessageReplaced("note data") + rainbowName));
}
rainbowIcon.setItemMeta(rainbowIconMeta);
return rainbowIcon;
}
/**
* Gets the icon used to return to the previous menu
*
* @return An ItemStack formatted to be displayed in the GUI
*/
private static ItemStack getItemForBack() {
ItemStack icon = new ItemStack(Material.ARROW, 1);
ItemMeta iconMeta = icon.getItemMeta();
iconMeta.setDisplayName(MessageType.GUI_BACK_BUTTON.getMessage());
icon.setItemMeta(iconMeta);
return icon;
}
}

View file

@ -46,9 +46,7 @@ import com.esophose.playerparticles.library.ReflectionUtils.PackageType;
/**
* Modified a couple things for the plugin
*
* Updated to 1.11
*
* Updated to 1.12
* @author (of changes) Esophose
*/
public enum ParticleEffect {
@ -738,8 +736,8 @@ public enum ParticleEffect {
/**
* Represents the particle data for effects like
* {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and
* {@link ParticleEffect#BLOCK_DUST}
* {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK},
* {@link ParticleEffect#BLOCK_DUST}, and {@link ParticleEffect#FALLING_DUST}
* <p>
* This class is part of the <b>ParticleEffect Library</b> and follows the
* same usage conditions

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -640,7 +640,7 @@ public class ConfigManager {
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"));
ParticleEffect particleEffect = ParticleManager.effectFromString(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"));
@ -701,7 +701,7 @@ public class ConfigManager {
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"));
ParticleEffect particleEffect = ParticleManager.effectFromString(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"));

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -34,7 +34,6 @@ public class MessageManager {
NO_STYLES("message-no-styles"),
NOW_USING_STYLE("message-now-using-style"),
CLEARED_STYLE("message-cleared-style"),
USE_STYLE("message-use-style"),
INVALID_TYPE_STYLE("message-invalid-type-style"),
STYLE_USAGE("message-style-usage"),
@ -84,6 +83,17 @@ public class MessageManager {
MAX_FIXED_EFFECTS_REACHED("message-max-fixed-effects-reached"),
INVALID_FIXED_COMMAND("message-invalid-fixed-command"),
// GUI
GUI_DISABLED("message-gui-disabled"),
GUI_BY_DEFAULT("message-gui-by-default"),
GUI_BACK_BUTTON("message-gui-back-button"),
GUI_ICON_NAME_COLOR("message-gui-icon-name-color"),
GUI_ICON_CURRENT_ACTIVE("message-gui-icon-current-active"),
GUI_ICON_SETS_TO("message-gui-icon-sets-to"),
GUI_ICON_SET_YOUR("message-gui-icon-set-your"),
GUI_NO_ACCESS_TO("message-gui-no-access-to"),
GUI_NO_DATA("message-gui-no-data"),
// Prefixes
USE("message-use"),
USAGE("message-usage"),
@ -99,19 +109,48 @@ public class MessageManager {
FAILED_EXECUTE_NOT_FOUND("message-failed-execute-not-found"),
FAILED_EXECUTE_NO_PERMISSION("message-failed-execute-no-permission");
public String configLocation;
private String configLocation;
private String message;
MessageType(String configLocation) {
this.configLocation = configLocation;
}
/**
* Sets the message from the config
*
* @param config The config to pull the message from
*/
protected void setMessage(FileConfiguration config) {
try {
String messageFromConfig = config.getString(configLocation);
if (messageFromConfig == null || messageFromConfig.length() == 0) {
messageFromConfig = "&cMissing message in config.yml. Contact a server administrator.";
PlayerParticles.getPlugin().getLogger().warning("Missing message in config.yml: " + this.configLocation);
}
this.message = ChatColor.translateAlternateColorCodes('&', messageFromConfig);
} catch (Exception ex) {
System.out.println(this.name());
}
}
/**
* Gets the message with the given config path
* Gets the message this enum represents
*
* @return The message from the config
* @return The message
*/
public String getMessage() {
return ChatColor.translateAlternateColorCodes('&', config.getString(this.configLocation));
return this.message;
}
/**
* Gets the message this enum represents and replace {TYPE} with a replacement value
*
* @param replacement The text to replace {TYPE} with
* @return The message with {TYPE} replaced with the replacement value
*/
public String getMessageReplaced(String replacement) {
return this.message.replaceAll("\\{TYPE\\}", replacement);
}
}
@ -138,6 +177,10 @@ public class MessageManager {
messagesEnabled = config.getBoolean("messages-enabled");
prefixEnabled = config.getBoolean("use-message-prefix");
messagePrefix = parseColors(config.getString("message-prefix"));
for (MessageType messageType : MessageType.values()) {
messageType.setMessage(config);
}
}
/**
@ -153,11 +196,15 @@ public class MessageManager {
if (prefixEnabled) {
message = messagePrefix + " " + message;
}
if (message.trim().equals("")) return;
player.sendMessage(message);
}
/**
* Sends a message to the given player and allows for replacing {TYPE}
*
* @param player The player to send the message to
* @param messageType The message to send to the player
* @param typeReplacement What {TYPE} should be replaced with
@ -165,10 +212,13 @@ public class MessageManager {
public static void sendMessage(Player player, MessageType messageType, String typeReplacement) {
if (!messagesEnabled) return;
String message = messageType.getMessage().replaceAll("\\{TYPE\\}", typeReplacement);
String message = messageType.getMessageReplaced(typeReplacement);
if (prefixEnabled) {
message = messagePrefix + " " + message;
}
if (message.trim().equals("")) return;
player.sendMessage(message);
}
@ -185,14 +235,17 @@ public class MessageManager {
if (prefixEnabled) {
message = messagePrefix + " " + message;
}
if (message.trim().equals("")) return;
player.sendMessage(message);
}
/**
* Translates all ampersand symbols into the Minecraft chat color symbol
*
* @param message The input
* @return The output, parsed
* @param message The input string
* @return The output string, parsed
*/
public static String parseColors(String message) {
return ChatColor.translateAlternateColorCodes('&', message);

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -36,7 +36,8 @@ public class ParticleManager extends BukkitRunnable implements Listener {
/**
* How far away particles will spawn from players
*/
public static final int PARTICLE_RANGE = 512;
public static final int PLAYER_PARTICLE_RANGE = 128;
public static final int FIXED_EFFECT_PARTICLE_RANGE = 256;
/**
* The list containing all the player effect info
@ -141,14 +142,14 @@ public class ParticleManager extends BukkitRunnable implements Listener {
}
/**
* Gets a particle type from a string, used for getting ParticleType's from the saved data
* Gets an effect type from a string, used for getting ParticleEffects from the saved data
*
* @param particle The name of the particle to check for
* @return The ParticleType with the given name, will be null if name was not found
* @param effectName The name of the particle to check for
* @return The ParticleEffect with the given name, will be null if name was not found
*/
public static ParticleEffect particleFromString(String particle) {
public static ParticleEffect effectFromString(String effectName) {
for (ParticleEffect effect : ParticleEffect.getSupportedEffects()) {
if (effect.getName().toLowerCase().replace("_", "").equals(particle.toLowerCase())) return effect;
if (effect.getName().toLowerCase().replace("_", "").equals(effectName.toLowerCase())) return effect;
}
return null;
}
@ -237,11 +238,11 @@ public class ParticleManager extends BukkitRunnable implements Listener {
if (effect == ParticleEffect.NONE) return;
for (PParticle particle : pplayer.getParticleStyle().getParticles(pplayer, location)) {
if (effect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
}
}
}
@ -258,11 +259,11 @@ public class ParticleManager extends BukkitRunnable implements Listener {
if (effect == ParticleEffect.NONE) return;
for (PParticle particle : particles) {
if (effect.hasProperty(ParticleProperty.REQUIRES_DATA)) {
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PLAYER_PARTICLE_RANGE);
}
}
}
@ -277,11 +278,11 @@ public class ParticleManager extends BukkitRunnable implements Listener {
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);
effect.display(fixedEffect.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), FIXED_EFFECT_PARTICLE_RANGE);
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(fixedEffect.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(fixedEffect.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), FIXED_EFFECT_PARTICLE_RANGE);
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), PARTICLE_RANGE);
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), FIXED_EFFECT_PARTICLE_RANGE);
}
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -56,7 +56,7 @@ public class PermissionManager {
* @param p The player to get effect names for
* @return A String List of all effect names the given player has permission for
*/
public static List<String> getParticlesUserHasPermissionFor(Player p) {
public static List<String> getEffectsUserHasPermissionFor(Player p) {
List<String> list = new ArrayList<String>();
for (ParticleEffect pe : ParticleEffect.getSupportedEffects()) {
if (hasEffectPermission(p, pe)) list.add(pe.getName().toLowerCase().replace("_", ""));
@ -97,5 +97,16 @@ public class PermissionManager {
public static boolean canUseFixedEffects(Player player) {
return player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.fixed");
}
/**
* Checks if a player has permission to open the GUI
* Access is restricted if they have the following permission
*
* @param player The player to check the permission for
* @return False if the player's access to the GUI is revoked
*/
public static boolean canUseGui(Player player) {
return !player.hasPermission("playerparticles.gui.revoke");
}
}

View file

@ -25,6 +25,8 @@ public class DefaultStyles {
public static final ParticleStyle ARROWS = new ParticleStyleArrows();
public static final ParticleStyle SPIRAL = new ParticleStyleSpiral();
public static final ParticleStyle THICK = new ParticleStyleThick();
public static final ParticleStyle WINGS = new ParticleStyleWings();
public static final ParticleStyle SPHERE = new ParticleStyleSphere();
/**
* Registers all the default styles to the ParticleStyleManager
@ -43,6 +45,8 @@ public class DefaultStyles {
ParticleStyleManager.registerStyle(ARROWS);
ParticleStyleManager.registerStyle(SPIRAL);
ParticleStyleManager.registerStyle(THICK);
ParticleStyleManager.registerStyle(WINGS);
ParticleStyleManager.registerStyle(SPHERE);
Bukkit.getPluginManager().registerEvents((Listener) MOVE, PlayerParticles.getPlugin());
Bukkit.getPluginManager().registerEvents((Listener) ARROWS, PlayerParticles.getPlugin());

View file

@ -36,60 +36,65 @@ import com.esophose.playerparticles.util.VectorUtils;
/**
* Credit goes to Slikey who made all this logic for drawing a cube out of particles
* The project this is from is called EffectLib and can be found here:
* The project this is from is called EffectLib and can be found here:
* https://github.com/Slikey/EffectLib
*/
public class ParticleStyleCube implements ParticleStyle {
private float edgeLength = 2;
private double angularVelocityX = (Math.PI / 200) / 5;
private double angularVelocityY = (Math.PI / 170) / 5;
private double angularVelocityZ = (Math.PI / 155) / 5;
private int particles = 8;
private int particles = 7;
private int step = 0;
private boolean skipNextStep = false; // Only spawn every 2 ticks
public PParticle[] getParticles(PPlayer pplayer, Location location) {
List<PParticle> pparticles = new ArrayList<PParticle>();
double xRotation = 0, yRotation = 0, zRotation = 0;
xRotation = step * angularVelocityX;
yRotation = step * angularVelocityY;
zRotation = step * angularVelocityZ;
float a = edgeLength / 2;
double angleX, angleY;
Vector v = new Vector();
for (int i = 0; i < 4; i++) {
angleY = i * Math.PI / 2;
for (int j = 0; j < 2; j++) {
angleX = j * Math.PI;
for (int p = 0; p <= particles; p++) {
v.setX(a).setY(a);
v.setZ(edgeLength * p / particles - a);
VectorUtils.rotateAroundAxisX(v, angleX);
VectorUtils.rotateAroundAxisY(v, angleY);
VectorUtils.rotateVector(v, xRotation, yRotation, zRotation);
pparticles.add(new PParticle(location.clone().add(v)));
}
}
for (int p = 0; p <= particles; p++) {
v.setX(a).setZ(a);
v.setY(edgeLength * p / particles - a);
VectorUtils.rotateAroundAxisY(v, angleY);
VectorUtils.rotateVector(v, xRotation, yRotation, zRotation);
pparticles.add(new PParticle(location.clone().add(v)));
}
}
if (!skipNextStep) {
double xRotation = 0, yRotation = 0, zRotation = 0;
xRotation = step * angularVelocityX;
yRotation = step * angularVelocityY;
zRotation = step * angularVelocityZ;
float a = edgeLength / 2;
double angleX, angleY;
Vector v = new Vector();
for (int i = 0; i < 4; i++) {
angleY = i * Math.PI / 2;
for (int j = 0; j < 2; j++) {
angleX = j * Math.PI;
for (int p = 0; p <= particles; p++) {
v.setX(a).setY(a);
v.setZ(edgeLength * p / particles - a);
VectorUtils.rotateAroundAxisX(v, angleX);
VectorUtils.rotateAroundAxisY(v, angleY);
VectorUtils.rotateVector(v, xRotation, yRotation, zRotation);
pparticles.add(new PParticle(location.clone().add(v)));
}
}
for (int p = 0; p <= particles; p++) {
v.setX(a).setZ(a);
v.setY(edgeLength * p / particles - a);
VectorUtils.rotateAroundAxisY(v, angleY);
VectorUtils.rotateVector(v, xRotation, yRotation, zRotation);
pparticles.add(new PParticle(location.clone().add(v)));
}
}
}
return pparticles.toArray(new PParticle[pparticles.size()]);
}
public void updateTimers() {
skipNextStep = !skipNextStep;
step++;
}
public String getName() {
return "cube";
}
public boolean canBeFixed() {
return true;
}

View file

@ -16,7 +16,7 @@ public class ParticleStyleQuadhelix implements ParticleStyle {
PParticle[] particles = new PParticle[4];
for (int i = 0; i < 4; i++) {
double dx = -(Math.cos((stepX / 90) * (Math.PI * 2) + ((Math.PI / 2) * i))) * ((60 - Math.abs(stepY)) / 60);
double dy = ((stepY) / 60) * 1.5;
double dy = (stepY / 60) * 1.5;
double dz = -(Math.sin((stepX / 90) * (Math.PI * 2) + ((Math.PI / 2) * i))) * ((60 - Math.abs(stepY)) / 60);
particles[i] = new PParticle(new Location(location.getWorld(), location.getX() + dx, location.getY() + dy, location.getZ() + dz));
}

View file

@ -0,0 +1,46 @@
package com.esophose.playerparticles.styles;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleSphere implements ParticleStyle {
@Override
public PParticle[] getParticles(PPlayer pplayer, Location location) {
int particleCount = 15;
float radius = 1.5f;
PParticle[] particles = new PParticle[particleCount];
for (int i = 0; i < particleCount; i++) {
double u = Math.random();
double v = Math.random();
double theta = 2 * Math.PI * u;
double phi = Math.acos(2 * v - 1);
double x = location.getX() + (radius * Math.sin(phi) * Math.cos(theta));
double y = location.getY() + (radius * Math.sin(phi) * Math.sin(theta));
double z = location.getZ() + (radius * Math.cos(phi));
particles[i] = new PParticle(new Location(location.getWorld(), x, y, z));
}
return particles;
}
@Override
public void updateTimers() {
}
@Override
public String getName() {
return "sphere";
}
@Override
public boolean canBeFixed() {
return true;
}
}

View file

@ -0,0 +1,45 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.VectorUtils;
public class ParticleStyleWings implements ParticleStyle {
int spawnTimer = 0; // Spawn particles every 3 ticks
public PParticle[] getParticles(PPlayer pplayer, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
if (spawnTimer == 0) {
for (double t = 0; t < Math.PI * 2; t += Math.PI / 64) {
double x = Math.sin(t) * (Math.pow(Math.E, Math.cos(t)) - 2 * Math.cos(t * 4) - Math.pow(Math.sin(t / 12), 5)) / 2;
double y = Math.cos(t) * (Math.pow(Math.E, Math.cos(t)) - 2 * Math.cos(t * 4) - Math.pow(Math.sin(t / 12), 5)) / 2;
Vector v = VectorUtils.rotateAroundAxisY(new Vector(x, y, -0.3), -Math.toRadians(location.getYaw()));
Location loc = new Location(location.getWorld(), location.getX() + v.getX(), location.getY() + v.getY(), location.getZ() + v.getZ());
particles.add(new PParticle(loc));
}
}
return particles.toArray(new PParticle[particles.size()]);
}
public void updateTimers() {
spawnTimer++;
spawnTimer %= 3;
}
public String getName() {
return "wings";
}
public boolean canBeFixed() {
return false;
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -80,7 +80,7 @@ public class PParticle {
}
/**
* Gets the offset on the x axis for the particle
* Gets the offset on the x-axis for the particle
*
* @return The x-axis offset
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -69,9 +69,8 @@ public class ParticleStyleManager {
* @return The ParticleStyle with the name requested
*/
public static ParticleStyle styleFromString(String styleName) {
for (ParticleStyle style : styles) {
for (ParticleStyle style : styles)
if (style.getName().toLowerCase().replace("_", "").equals(styleName)) return style;
}
return null;
}
@ -81,9 +80,8 @@ public class ParticleStyleManager {
* Do not call this in your plugin, it will mess with other styles
*/
public static void updateTimers() {
for (ParticleStyle style : styles) {
for (ParticleStyle style : styles)
style.updateTimers();
}
}
/**

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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

View file

@ -1,5 +1,5 @@
/**
* Copyright Esophose 2017
* Copyright Esophose 2018
* 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
@ -8,30 +8,28 @@
package com.esophose.playerparticles.util;
import java.util.ArrayList;
import org.bukkit.Material;
public class ParticleUtils {
/**
* 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().replaceAll("_", " ").toLowerCase().equals(input.toLowerCase()) || String.valueOf(material.getId()).equals(input))
return material;
else if (material.name().replaceAll("_", " ").toLowerCase().contains(input.toLowerCase()))
matchList.add(material);
if (matchList.size() == 1) return matchList.get(0);
else return null;
if (input == null) return null;
for (Material material : Material.values()) // First check for exact matches
if (material.name().equalsIgnoreCase(input) ||
material.toString().equalsIgnoreCase(input)) return material;
for (Material material : Material.values()) // Then check for partial matches
if (material.name().toLowerCase().contains(input.toLowerCase()) ||
material.toString().toLowerCase().contains(input.toLowerCase()) ||
material.name().replaceAll("_", "").toLowerCase().contains(input.toLowerCase()) ||
material.toString().replaceAll("_", "").toLowerCase().contains(input.toLowerCase()))
return material;
return null;
}
/**

View file

@ -1,11 +1,9 @@
# ____________ __________ __ __ __ _____
# \______ \ | _____ ___ __ __________\______ \_____ ________/ |_|__| ____ | | ____ ______ ___ __/ | |
# | ___/ | \__ \< | |/ __ \_ __ \ ___/\__ \\_ __ \ __\ |/ ___\| | _/ __ \ / ___/ \ \/ / | |_
# | | | |__/ __ \\___ \ ___/| | \/ | / __ \| | \/| | | \ \___| |_\ ___/ \___ \ \ / ^ /
# |____| |____(____ / ____|\___ >__| |____| (____ /__| |__| |__|\___ >____/\___ >____ > \_/\____ |
# \/\/ \/ \/ \/ \/ \/ |__|
# Please excuse the cheesy ASCII Art
# __________ __ __________ __ __ __ ________
# \______ \ | _____ ___ __ __________\______ \_____ ________/ |_|__| ____ | | ____ ______ ___ _| ____/
# | ___/ | \__ \< | |/ __ \_ __ \ ___/\__ \\_ __ \ __\ |/ ___\| | _/ __ \ / ___/ \ \/ /____ \
# | | | |__/ __ \\___ \ ___/| | \/ | / __ \| | \/| | | \ \___| |_\ ___/ \___ \ \ // \
# |____| |____(____ / ____|\___ >__| |____| (____ /__| |__| |__|\___ >____/\___ >____ > \_//______ /
# \/\/ \/ \/ \/ \/ \/ \/
# ==================================================== #
# PlayerParticles Config #
@ -14,19 +12,19 @@
# Changing this value will reset your config on the next server reload / restart.
# I don't recommend changing it
version: 4.5
# How many ticks to wait before spawning more particles
# Increasing this value may cause less lag (if there was any), but will decrease prettiness
# The lowest possible value is 1
# Going over 5 will likely look terrible
# Default: 1
ticks-per-particle: 1
# NOTE: Updating to a new version of the plugin will change this number and delete your config.
# Make sure you create a backup each time before you update!
version: 5.0
# Check for new versions of the plugin
# Default: true
check-updates: true
# If the command /pp gui is enabled
# Disable this if you have your own custom GUI through another plugin
# Default: true
gui-enabled: true
# The worlds which this plugin is disabled in
# Remove the [] before you enter world names
# Default: []
@ -42,15 +40,22 @@ 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: 256
max-fixed-effect-creation-distance: 256
# Default: 128
max-fixed-effect-creation-distance: 128
# How many ticks to wait before spawning more particles
# Increasing this value may cause less lag (if there was any), but will decrease prettiness
# Only use whole numbers greater than or equal to 1
# Going over 3 will likely look terrible
# Default: 1
ticks-per-particle: 1
# ================================================================ #
# MESSAGE CONFIGURATION #
# Important Notes: #
# * You can use the & symbol to color the messages #
# * {TYPE} Will be replaced with whatever that message requires #
# * You can not use the apostrophe character! ( ' ) #
# * You cannot use the apostrophe character! ( ' ) #
# ================================================================ #
# If you're using other plugins to execute commands you may wish to turn off messages
@ -164,12 +169,12 @@ message-color-data-usage: '&b/pp data [<0-255> <0-255> <0-255>]|[rainbow]'
# Item Data Usage
# You should not change the text here, only the coloring
# Default: '&b/pp data <itemName> <0-15>'
# Default: '&b/pp data <itemName/ID> <0-15>'
message-item-data-usage: '&b/pp data <itemName> <0-15>'
# Block Data Usage
# You should not change the text here, only the coloring
# Default: '&b/pp data <blockName> <0-15>'
# Default: '&b/pp data <blockName/ID> <0-15>'
message-block-data-usage: '&b/pp data <blockName> <0-15>'
# ---------------- #
@ -185,8 +190,8 @@ message-use: '&eYou can use:&b'
message-usage: '&eUsage:'
# Available Commands
# Default: '&eAvailable commands: &beffect, effects, style, styles, data, reset, worlds, version, help'
message-available-commands: '&eAvailable commands: &beffect, effects, style, styles, data, reset, worlds, version, help'
# Default: '&eAvailable commands: &beffect, effects, style, styles, data, reset, gui, worlds, version, help'
message-available-commands: '&eAvailable commands: &beffect, effects, style, styles, data, reset, gui, worlds, version, help'
# Disabled Worlds
# Default: '&eParticles are disabled in these worlds:&b'
@ -366,6 +371,47 @@ message-fixed-command-desc-info: '&e/pp fixed info <id> - Gets info on one of yo
# Default: '&e/pp fixed clear <radius> - Clears all fixed effects of all players within the given radius'
message-fixed-command-desc-clear: '&e/pp fixed clear <radius> - Clears all fixed effects of all players within the given radius'
# ------------- #
# GUI #
# ------------- #
# Disabled
# Default: '&cThe server administrator has disabled the GUI.'
message-gui-disabled: '&cThe server administrator has disabled the GUI.'
# Opened By Default
# Default: '&eWe opened the GUI for you because you did not specify a command. If you are looking to use a specific command, view them with &b/pp help'
message-gui-by-default: '&eWe opened the GUI for you because you did not specify a command. If you are looking to use a specific command, view them with &b/pp help'
# Back Button
# Default: '&eGo Back'
message-gui-back-button: '&eGo Back'
# Icon Name Color
# Default: '&a'
message-gui-icon-name-color: '&a'
# Currently Active Effect/Style
# Default: '&d- Your current {TYPE} -'
message-gui-icon-current-active: '&d- Your current {TYPE} -'
# Sets your style/effect to {effect name}
# The effect/style name will be added to the end
# Default: '&eSets your {TYPE} to '
message-gui-icon-sets-to: '&eSets your {TYPE} to &b'
# Select Your
# Default: '&eSelect your {TYPE}'
message-gui-icon-set-your: '&eSelect your {TYPE}'
# No Access To
# Default: '&cYou have no access to any {TYPE}!'
message-gui-no-access-to: '&cYou have no access to any {TYPE}!'
# No Data
# Default: '&cYour effect does not use any data!'
message-gui-no-data: '&cYour effect does not use any data!'
# ------------- #
# Other #
# ------------- #
@ -423,5 +469,90 @@ database-user-name: ''
# Default: ''
database-user-password: ''
# That's everything! You reached the end of the configuration
# =================================================================== #
# GUI ICON SETTINGS #
# This configuration option allows you to change any of the GUI #
# icons to whatever block/item you want. #
# #
# Important Notes: #
# * If any of the block/item names are invalid it will notify you #
# in console and the icon in the GUI will be the barrier icon to #
# show that it failed to load. #
# * Do NOT change the particle/style name #
# * You MUST use the Spigot-given name for it to work. You can see #
# all the Spigot-given names at the link below: #
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html #
# =================================================================== #
gui-icon:
main-menu:
EFFECT: BLAZE_POWDER
STYLE: NETHER_STAR
DATA: BOOK
effect:
NONE: THIN_GLASS
EXPLODE: SULPHUR
LARGE_EXPLODE: FIREBALL
HUGE_EXPLOSION: TNT
FIREWORKS_SPARK: FIREWORK
BUBBLE: GLASS
WAKE: WATER_LILY
SUSPENDED: RAW_FISH
DEPTH_SUSPEND: BEDROCK
CRIT: IRON_SWORD
MAGIC_CRIT: NETHER_STALK
SMOKE: TORCH
LARGE_SMOKE: WEB
SPELL: GLASS_BOTTLE
INSTANT_SPELL: POTION
MOB_SPELL: GLOWSTONE_DUST
MOB_SPELL_AMBIENT: BEACON
WITCH_MAGIC: CAULDRON_ITEM
DRIP_WATER: WATER_BUCKET
DRIP_LAVA: LAVA_BUCKET
ANGRY_VILLAGER: IRON_DOOR
HAPPY_VILLAGER: WOOD_DOOR
NOTE: NOTE_BLOCK
PORTAL: OBSIDIAN
ENCHANTMENT_TABLE: ENCHANTMENT_TABLE
FLAME: BLAZE_POWDER
LAVA: NETHER_BRICK
FOOTSTEP: GRASS
CLOUD: WOOL
RED_DUST: REDSTONE
SNOWBALL_POOF: SNOW_BALL
SNOW_SHOVEL: SNOW
SLIME: SLIME_BALL
HEART: RED_ROSE
BARRIER: BARRIER
ITEM_CRACK: STICK
BLOCK_CRACK: DEAD_BUSH
BLOCK_DUST: SOUL_SAND
DROPLET: LAPIS_ORE
DRAGON_BREATH: DRAGONS_BREATH
END_ROD: END_ROD
DAMAGE_INDICATOR: BOW
SWEEP_ATTACK: GOLD_SWORD
FALLING_DUST: SAND
TOTEM: TOTEM
SPIT: PUMPKIN_SEEDS
style:
NONE: THIN_GLASS
BEAM: POWERED_RAIL
HALO: ENDER_PORTAL_FRAME
POINT: STONE_BUTTON
MOVE: PISTON_BASE
SPIN: BEACON
QUADHELIX: ACTIVATOR_RAIL
ORBIT: ENCHANTMENT_TABLE
FEET: GRASS
CUBE: STONE
ARROWS: BOW
SPIRAL: HOPPER
THICK: VINE
WINGS: ELYTRA
SPHERE: SNOW_BALL
# That's everything! You reached the end of the configuration.
# Enjoy the plugin!

View file

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